mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Merge pull request #17535 from mesosphere/jdef_abspath_breaks_proxies
Auto commit by PR queue bot
This commit is contained in:
commit
03ecde1277
@ -55,7 +55,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer
|
|||||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||||
const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned"
|
const pkgUnversioned = "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
const pkgLatest = "k8s.io/kubernetes/pkg/api/latest"
|
const pkgLatest = "k8s.io/kubernetes/pkg/api/latest"
|
||||||
prefix := func(group string) string {
|
apiPath := func(group string) string {
|
||||||
if group == "legacy" {
|
if group == "legacy" {
|
||||||
return `"/api"`
|
return `"/api"`
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer
|
|||||||
"RESTClientFor": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "RESTClientFor"}),
|
"RESTClientFor": c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "RESTClientFor"}),
|
||||||
"latestGroup": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "Group"}),
|
"latestGroup": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "Group"}),
|
||||||
"GroupOrDie": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "GroupOrDie"}),
|
"GroupOrDie": c.Universe.Variable(types.Name{Package: pkgLatest, Name: "GroupOrDie"}),
|
||||||
"prefix": prefix(g.group),
|
"apiPath": apiPath(g.group),
|
||||||
}
|
}
|
||||||
sw.Do(groupInterfaceTemplate, m)
|
sw.Do(groupInterfaceTemplate, m)
|
||||||
sw.Do(groupClientTemplate, m)
|
sw.Do(groupClientTemplate, m)
|
||||||
@ -171,7 +171,7 @@ func setConfigDefaults(config *$.Config|raw$) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config.Prefix = $.prefix$
|
config.APIPath = $.apiPath$
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = $.DefaultKubernetesUserAgent|raw$()
|
config.UserAgent = $.DefaultKubernetesUserAgent|raw$()
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func setConfigDefaults(config *unversioned.Config) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config.Prefix = "/apis"
|
config.APIPath = "/apis"
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ func setConfigDefaults(config *unversioned.Config) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config.Prefix = "/apis"
|
config.APIPath = "/apis"
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func setConfigDefaults(config *unversioned.Config) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config.Prefix = "/api"
|
config.APIPath = "/api"
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
config.UserAgent = unversioned.DefaultKubernetesUserAgent()
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,6 @@ func (config DirectClientConfig) ClientConfig() (*client.Config, error) {
|
|||||||
clientConfig := &client.Config{}
|
clientConfig := &client.Config{}
|
||||||
clientConfig.Host = configClusterInfo.Server
|
clientConfig.Host = configClusterInfo.Server
|
||||||
if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 {
|
if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 {
|
||||||
clientConfig.Prefix = u.Path
|
|
||||||
u.Path = ""
|
|
||||||
u.RawQuery = ""
|
u.RawQuery = ""
|
||||||
u.Fragment = ""
|
u.Fragment = ""
|
||||||
clientConfig.Host = u.String()
|
clientConfig.Host = u.String()
|
||||||
|
@ -156,7 +156,7 @@ func TestCreateClean(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t)
|
matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t)
|
||||||
matchStringArg("", clientConfig.Prefix, t)
|
matchStringArg("", clientConfig.APIPath, t)
|
||||||
matchStringArg(config.Clusters["clean"].APIVersion, clientConfig.GroupVersion.String(), t)
|
matchStringArg(config.Clusters["clean"].APIVersion, clientConfig.GroupVersion.String(), t)
|
||||||
matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t)
|
matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t)
|
||||||
matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t)
|
matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t)
|
||||||
@ -166,22 +166,21 @@ func TestCreateCleanWithPrefix(t *testing.T) {
|
|||||||
tt := []struct {
|
tt := []struct {
|
||||||
server string
|
server string
|
||||||
host string
|
host string
|
||||||
prefix string
|
|
||||||
}{
|
}{
|
||||||
{"https://anything.com:8080/foo/bar", "https://anything.com:8080", "/foo/bar"},
|
{"https://anything.com:8080/foo/bar", "https://anything.com:8080/foo/bar"},
|
||||||
{"http://anything.com:8080/foo/bar", "http://anything.com:8080", "/foo/bar"},
|
{"http://anything.com:8080/foo/bar", "http://anything.com:8080/foo/bar"},
|
||||||
{"http://anything.com:8080/foo/bar/", "http://anything.com:8080", "/foo/bar/"},
|
{"http://anything.com:8080/foo/bar/", "http://anything.com:8080/foo/bar/"},
|
||||||
{"http://anything.com:8080/", "http://anything.com:8080/", ""},
|
{"http://anything.com:8080/", "http://anything.com:8080/"},
|
||||||
{"http://anything.com:8080//", "http://anything.com:8080", "//"},
|
{"http://anything.com:8080//", "http://anything.com:8080//"},
|
||||||
{"anything.com:8080/foo/bar", "anything.com:8080/foo/bar", ""},
|
{"anything.com:8080/foo/bar", "anything.com:8080/foo/bar"},
|
||||||
{"anything.com:8080", "anything.com:8080", ""},
|
{"anything.com:8080", "anything.com:8080"},
|
||||||
{"anything.com", "anything.com", ""},
|
{"anything.com", "anything.com"},
|
||||||
{"anything", "anything", ""},
|
{"anything", "anything"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: EnvVarCluster.Server is set during package loading time and can not be overriden by os.Setenv inside this test
|
// WARNING: EnvVarCluster.Server is set during package loading time and can not be overriden by os.Setenv inside this test
|
||||||
EnvVarCluster.Server = ""
|
EnvVarCluster.Server = ""
|
||||||
tt = append(tt, struct{ server, host, prefix string }{"", "http://localhost:8080", ""})
|
tt = append(tt, struct{ server, host string }{"", "http://localhost:8080"})
|
||||||
|
|
||||||
for _, tc := range tt {
|
for _, tc := range tt {
|
||||||
config := createValidTestConfig()
|
config := createValidTestConfig()
|
||||||
@ -198,7 +197,6 @@ func TestCreateCleanWithPrefix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
matchStringArg(tc.host, clientConfig.Host, t)
|
matchStringArg(tc.host, clientConfig.Host, t)
|
||||||
matchStringArg(tc.prefix, clientConfig.Prefix, t)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ func (d *DiscoveryClient) SwaggerSchema(version unversioned.GroupVersion) (*swag
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setDiscoveryDefaults(config *Config) error {
|
func setDiscoveryDefaults(config *Config) error {
|
||||||
config.Prefix = ""
|
config.APIPath = ""
|
||||||
config.GroupVersion = nil
|
config.GroupVersion = nil
|
||||||
// Discovery client deals with unversioned objects, so we use api.Codec.
|
// Discovery client deals with unversioned objects, so we use api.Codec.
|
||||||
config.Codec = api.Codec
|
config.Codec = api.Codec
|
||||||
|
@ -111,7 +111,7 @@ func setExtensionsDefaults(config *Config) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config.Prefix = "apis/"
|
config.APIPath = defaultAPIPath
|
||||||
if config.UserAgent == "" {
|
if config.UserAgent == "" {
|
||||||
config.UserAgent = DefaultKubernetesUserAgent()
|
config.UserAgent = DefaultKubernetesUserAgent()
|
||||||
}
|
}
|
||||||
|
@ -50,23 +50,27 @@ type RESTClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Get() *unversioned.Request {
|
func (c *RESTClient) Get() *unversioned.Request {
|
||||||
return unversioned.NewRequest(c, "GET", &url.URL{Host: "localhost"}, *testapi.Default.GroupVersion(), c.Codec, nil)
|
return c.request("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Put() *unversioned.Request {
|
func (c *RESTClient) Put() *unversioned.Request {
|
||||||
return unversioned.NewRequest(c, "PUT", &url.URL{Host: "localhost"}, *testapi.Default.GroupVersion(), c.Codec, nil)
|
return c.request("PUT")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Patch(_ api.PatchType) *unversioned.Request {
|
func (c *RESTClient) Patch(_ api.PatchType) *unversioned.Request {
|
||||||
return unversioned.NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, *testapi.Default.GroupVersion(), c.Codec, nil)
|
return c.request("PATCH")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Post() *unversioned.Request {
|
func (c *RESTClient) Post() *unversioned.Request {
|
||||||
return unversioned.NewRequest(c, "POST", &url.URL{Host: "localhost"}, *testapi.Default.GroupVersion(), c.Codec, nil)
|
return c.request("POST")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Delete() *unversioned.Request {
|
func (c *RESTClient) Delete() *unversioned.Request {
|
||||||
return unversioned.NewRequest(c, "DELETE", &url.URL{Host: "localhost"}, *testapi.Default.GroupVersion(), c.Codec, nil)
|
return c.request("DELETE")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RESTClient) request(verb string) *unversioned.Request {
|
||||||
|
return unversioned.NewRequest(c, verb, &url.URL{Host: "localhost"}, "", *testapi.Default.GroupVersion(), c.Codec, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RESTClient) Do(req *http.Request) (*http.Response, error) {
|
func (c *RESTClient) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
@ -40,14 +40,21 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/version"
|
"k8s.io/kubernetes/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
legacyAPIPath = "/api"
|
||||||
|
defaultAPIPath = "/apis"
|
||||||
|
)
|
||||||
|
|
||||||
// Config holds the common attributes that can be passed to a Kubernetes client on
|
// Config holds the common attributes that can be passed to a Kubernetes client on
|
||||||
// initialization.
|
// initialization.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Host must be a host string, a host:port pair, or a URL to the base of the API.
|
// Host must be a host string, a host:port pair, or a URL to the base of the apiserver.
|
||||||
|
// If a URL is given then the (optional) Path of that URL represents a prefix that must
|
||||||
|
// be appended to all request URIs used to access the apiserver. This allows a frontend
|
||||||
|
// proxy to easily relocate all of the apiserver endpoints.
|
||||||
Host string
|
Host string
|
||||||
// Prefix is the sub path of the server. If not specified, the client will set
|
// APIPath is a sub-path that points to an API root.
|
||||||
// a default value. Use "/" to indicate the server root should be used
|
APIPath string
|
||||||
Prefix string
|
|
||||||
// GroupVersion is the API version to talk to. Must be provided when initializing
|
// GroupVersion is the API version to talk to. Must be provided when initializing
|
||||||
// a RESTClient directly. When initializing a Client, will be set with the default
|
// a RESTClient directly. When initializing a Client, will be set with the default
|
||||||
// code version.
|
// code version.
|
||||||
@ -180,7 +187,7 @@ func ExtractGroupVersions(l *unversioned.APIGroupList) []string {
|
|||||||
|
|
||||||
// ServerAPIVersions returns the GroupVersions supported by the API server.
|
// ServerAPIVersions returns the GroupVersions supported by the API server.
|
||||||
// It creates a RESTClient based on the passed in config, but it doesn't rely
|
// It creates a RESTClient based on the passed in config, but it doesn't rely
|
||||||
// on the Version, Codec, and Prefix of the config, because it uses AbsPath and
|
// on the Version and Codec of the config, because it uses AbsPath and
|
||||||
// takes the raw response.
|
// takes the raw response.
|
||||||
func ServerAPIVersions(c *Config) (groupVersions []string, err error) {
|
func ServerAPIVersions(c *Config) (groupVersions []string, err error) {
|
||||||
transport, err := TransportFor(c)
|
transport, err := TransportFor(c)
|
||||||
@ -191,13 +198,14 @@ func ServerAPIVersions(c *Config) (groupVersions []string, err error) {
|
|||||||
|
|
||||||
configCopy := *c
|
configCopy := *c
|
||||||
configCopy.GroupVersion = nil
|
configCopy.GroupVersion = nil
|
||||||
configCopy.Prefix = ""
|
configCopy.APIPath = ""
|
||||||
baseURL, err := defaultServerUrlFor(c)
|
baseURL, _, err := defaultServerUrlFor(&configCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Get the groupVersions exposed at /api
|
// Get the groupVersions exposed at /api
|
||||||
baseURL.Path = "/api"
|
originalPath := baseURL.Path
|
||||||
|
baseURL.Path = path.Join(originalPath, legacyAPIPath)
|
||||||
resp, err := client.Get(baseURL.String())
|
resp, err := client.Get(baseURL.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -211,7 +219,7 @@ func ServerAPIVersions(c *Config) (groupVersions []string, err error) {
|
|||||||
|
|
||||||
groupVersions = append(groupVersions, v.Versions...)
|
groupVersions = append(groupVersions, v.Versions...)
|
||||||
// Get the groupVersions exposed at /apis
|
// Get the groupVersions exposed at /apis
|
||||||
baseURL.Path = "/apis"
|
baseURL.Path = path.Join(originalPath, defaultAPIPath)
|
||||||
resp2, err := client.Get(baseURL.String())
|
resp2, err := client.Get(baseURL.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -357,8 +365,8 @@ func NewInCluster() (*Client, error) {
|
|||||||
// Kubernetes API or returns an error if any of the defaults are impossible or invalid.
|
// Kubernetes API or returns an error if any of the defaults are impossible or invalid.
|
||||||
// TODO: this method needs to be split into one that sets defaults per group, expected to be fix in PR "Refactoring clientcache.go and helper.go #14592"
|
// TODO: this method needs to be split into one that sets defaults per group, expected to be fix in PR "Refactoring clientcache.go and helper.go #14592"
|
||||||
func SetKubernetesDefaults(config *Config) error {
|
func SetKubernetesDefaults(config *Config) error {
|
||||||
if config.Prefix == "" {
|
if config.APIPath == "" {
|
||||||
config.Prefix = "/api"
|
config.APIPath = legacyAPIPath
|
||||||
}
|
}
|
||||||
if len(config.UserAgent) == 0 {
|
if len(config.UserAgent) == 0 {
|
||||||
config.UserAgent = DefaultKubernetesUserAgent()
|
config.UserAgent = DefaultKubernetesUserAgent()
|
||||||
@ -398,12 +406,12 @@ func RESTClientFor(config *Config) (*RESTClient, error) {
|
|||||||
return nil, fmt.Errorf("Codec is required when initializing a RESTClient")
|
return nil, fmt.Errorf("Codec is required when initializing a RESTClient")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL, err := defaultServerUrlFor(config)
|
baseURL, versionedAPIPath, err := defaultServerUrlFor(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewRESTClient(baseURL, *config.GroupVersion, config.Codec, config.QPS, config.Burst)
|
client := NewRESTClient(baseURL, versionedAPIPath, *config.GroupVersion, config.Codec, config.QPS, config.Burst)
|
||||||
|
|
||||||
transport, err := TransportFor(config)
|
transport, err := TransportFor(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -423,12 +431,12 @@ func UnversionedRESTClientFor(config *Config) (*RESTClient, error) {
|
|||||||
return nil, fmt.Errorf("Codec is required when initializing a RESTClient")
|
return nil, fmt.Errorf("Codec is required when initializing a RESTClient")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL, err := defaultServerUrlFor(config)
|
baseURL, versionedAPIPath, err := defaultServerUrlFor(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := NewRESTClient(baseURL, unversioned.SchemeGroupVersion, config.Codec, config.QPS, config.Burst)
|
client := NewRESTClient(baseURL, versionedAPIPath, unversioned.SchemeGroupVersion, config.Codec, config.QPS, config.Burst)
|
||||||
|
|
||||||
transport, err := TransportFor(config)
|
transport, err := TransportFor(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -444,14 +452,14 @@ func UnversionedRESTClientFor(config *Config) (*RESTClient, error) {
|
|||||||
// DefaultServerURL converts a host, host:port, or URL string to the default base server API path
|
// DefaultServerURL converts a host, host:port, or URL string to the default base server API path
|
||||||
// to use with a Client at a given API version following the standard conventions for a
|
// to use with a Client at a given API version following the standard conventions for a
|
||||||
// Kubernetes API.
|
// Kubernetes API.
|
||||||
func DefaultServerURL(host, prefix string, groupVersion unversioned.GroupVersion, defaultTLS bool) (*url.URL, error) {
|
func DefaultServerURL(host, apiPath string, groupVersion unversioned.GroupVersion, defaultTLS bool) (*url.URL, string, error) {
|
||||||
if host == "" {
|
if host == "" {
|
||||||
return nil, fmt.Errorf("host must be a URL or a host:port pair")
|
return nil, "", fmt.Errorf("host must be a URL or a host:port pair")
|
||||||
}
|
}
|
||||||
base := host
|
base := host
|
||||||
hostURL, err := url.Parse(base)
|
hostURL, err := url.Parse(base)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if hostURL.Scheme == "" {
|
if hostURL.Scheme == "" {
|
||||||
scheme := "http://"
|
scheme := "http://"
|
||||||
@ -460,32 +468,34 @@ func DefaultServerURL(host, prefix string, groupVersion unversioned.GroupVersion
|
|||||||
}
|
}
|
||||||
hostURL, err = url.Parse(scheme + base)
|
hostURL, err = url.Parse(scheme + base)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if hostURL.Path != "" && hostURL.Path != "/" {
|
if hostURL.Path != "" && hostURL.Path != "/" {
|
||||||
return nil, fmt.Errorf("host must be a URL or a host:port pair: %q", base)
|
return nil, "", fmt.Errorf("host must be a URL or a host:port pair: %q", base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user specified a URL without a path component (http://server.com), automatically
|
// hostURL.Path is optional; a non-empty Path is treated as a prefix that is to be applied to
|
||||||
// append the default prefix
|
// all URIs used to access the host. this is useful when there's a proxy in front of the
|
||||||
if hostURL.Path == "" {
|
// apiserver that has relocated the apiserver endpoints, forwarding all requests from, for
|
||||||
if prefix == "" {
|
// example, /a/b/c to the apiserver. in this case the Path should be /a/b/c.
|
||||||
prefix = "/"
|
//
|
||||||
}
|
// if running without a frontend proxy (that changes the location of the apiserver), then
|
||||||
hostURL.Path = prefix
|
// hostURL.Path should be blank.
|
||||||
}
|
//
|
||||||
|
// versionedAPIPath, a path relative to baseURL.Path, points to a versioned API base
|
||||||
|
versionedAPIPath := path.Join("/", apiPath)
|
||||||
|
|
||||||
// Add the version to the end of the path
|
// Add the version to the end of the path
|
||||||
if len(groupVersion.Group) > 0 {
|
if len(groupVersion.Group) > 0 {
|
||||||
hostURL.Path = path.Join(hostURL.Path, groupVersion.Group, groupVersion.Version)
|
versionedAPIPath = path.Join(versionedAPIPath, groupVersion.Group, groupVersion.Version)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
hostURL.Path = path.Join(hostURL.Path, groupVersion.Version)
|
versionedAPIPath = path.Join(versionedAPIPath, groupVersion.Version)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hostURL, nil
|
return hostURL, versionedAPIPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsConfigTransportTLS returns true if and only if the provided config will result in a protected
|
// IsConfigTransportTLS returns true if and only if the provided config will result in a protected
|
||||||
@ -499,7 +509,7 @@ func IsConfigTransportTLS(config Config) bool {
|
|||||||
// modify the copy of the config we got to satisfy preconditions for defaultServerUrlFor
|
// modify the copy of the config we got to satisfy preconditions for defaultServerUrlFor
|
||||||
config.GroupVersion = defaultVersionFor(&config)
|
config.GroupVersion = defaultVersionFor(&config)
|
||||||
|
|
||||||
baseURL, err := defaultServerUrlFor(&config)
|
baseURL, _, err := defaultServerUrlFor(&config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -508,7 +518,7 @@ func IsConfigTransportTLS(config Config) bool {
|
|||||||
|
|
||||||
// defaultServerUrlFor is shared between IsConfigTransportTLS and RESTClientFor. It
|
// defaultServerUrlFor is shared between IsConfigTransportTLS and RESTClientFor. It
|
||||||
// requires Host and Version to be set prior to being called.
|
// requires Host and Version to be set prior to being called.
|
||||||
func defaultServerUrlFor(config *Config) (*url.URL, error) {
|
func defaultServerUrlFor(config *Config) (*url.URL, string, error) {
|
||||||
// TODO: move the default to secure when the apiserver supports TLS by default
|
// TODO: move the default to secure when the apiserver supports TLS by default
|
||||||
// config.Insecure is taken to mean "I want HTTPS but don't bother checking the certs against a CA."
|
// config.Insecure is taken to mean "I want HTTPS but don't bother checking the certs against a CA."
|
||||||
hasCA := len(config.CAFile) != 0 || len(config.CAData) != 0
|
hasCA := len(config.CAFile) != 0 || len(config.CAData) != 0
|
||||||
@ -520,12 +530,12 @@ func defaultServerUrlFor(config *Config) (*url.URL, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.GroupVersion != nil {
|
if config.GroupVersion != nil {
|
||||||
return DefaultServerURL(host, config.Prefix, *config.GroupVersion, defaultTLS)
|
return DefaultServerURL(host, config.APIPath, *config.GroupVersion, defaultTLS)
|
||||||
}
|
}
|
||||||
return DefaultServerURL(host, config.Prefix, unversioned.GroupVersion{}, defaultTLS)
|
return DefaultServerURL(host, config.APIPath, unversioned.GroupVersion{}, defaultTLS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultVersionFor is shared between defaultServerUrlFor and RESTClientFor
|
// defaultVersionFor is shared between IsConfigTransportTLS and RESTClientFor
|
||||||
func defaultVersionFor(config *Config) *unversioned.GroupVersion {
|
func defaultVersionFor(config *Config) *unversioned.GroupVersion {
|
||||||
if config.GroupVersion == nil {
|
if config.GroupVersion == nil {
|
||||||
// Clients default to the preferred code API version
|
// Clients default to the preferred code API version
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -91,7 +92,7 @@ func TestSetKubernetesDefaults(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Config{},
|
Config{},
|
||||||
Config{
|
Config{
|
||||||
Prefix: "/api",
|
APIPath: "/api",
|
||||||
GroupVersion: testapi.Default.GroupVersion(),
|
GroupVersion: testapi.Default.GroupVersion(),
|
||||||
Codec: testapi.Default.Codec(),
|
Codec: testapi.Default.Codec(),
|
||||||
QPS: 5,
|
QPS: 5,
|
||||||
@ -202,7 +203,7 @@ func TestSetsCodec(t *testing.T) {
|
|||||||
Prefix string
|
Prefix string
|
||||||
Codec runtime.Codec
|
Codec runtime.Codec
|
||||||
}{
|
}{
|
||||||
testapi.Default.GroupVersion().Version: {false, "/api/" + testapi.Default.GroupVersion().Version + "/", testapi.Default.Codec()},
|
testapi.Default.GroupVersion().Version: {false, "/api/" + testapi.Default.GroupVersion().Version, testapi.Default.Codec()},
|
||||||
// Add this test back when we fixed config and SetKubernetesDefaults
|
// Add this test back when we fixed config and SetKubernetesDefaults
|
||||||
// "invalidVersion": {true, "", nil},
|
// "invalidVersion": {true, "", nil},
|
||||||
}
|
}
|
||||||
@ -218,7 +219,7 @@ func TestSetsCodec(t *testing.T) {
|
|||||||
case err != nil:
|
case err != nil:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if e, a := expected.Prefix, client.RESTClient.baseURL.Path; e != a {
|
if e, a := expected.Prefix, client.RESTClient.versionedAPIPath; e != a {
|
||||||
t.Errorf("expected %#v, got %#v", e, a)
|
t.Errorf("expected %#v, got %#v", e, a)
|
||||||
}
|
}
|
||||||
if e, a := expected.Codec, client.RESTClient.Codec; e != a {
|
if e, a := expected.Codec, client.RESTClient.Codec; e != a {
|
||||||
@ -241,8 +242,8 @@ func TestRESTClientRequires(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidatesHostParameter(t *testing.T) {
|
func TestValidatesHostParameter(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Host string
|
Host string
|
||||||
Prefix string
|
APIPath string
|
||||||
|
|
||||||
URL string
|
URL string
|
||||||
Err bool
|
Err bool
|
||||||
@ -257,7 +258,7 @@ func TestValidatesHostParameter(t *testing.T) {
|
|||||||
{"host/server", "", "", true},
|
{"host/server", "", "", true},
|
||||||
}
|
}
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
u, err := DefaultServerURL(testCase.Host, testCase.Prefix, *testapi.Default.GroupVersion(), false)
|
u, versionedAPIPath, err := DefaultServerURL(testCase.Host, testCase.APIPath, *testapi.Default.GroupVersion(), false)
|
||||||
switch {
|
switch {
|
||||||
case err == nil && testCase.Err:
|
case err == nil && testCase.Err:
|
||||||
t.Errorf("expected error but was nil")
|
t.Errorf("expected error but was nil")
|
||||||
@ -268,6 +269,7 @@ func TestValidatesHostParameter(t *testing.T) {
|
|||||||
case err != nil:
|
case err != nil:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
u.Path = path.Join(u.Path, versionedAPIPath)
|
||||||
if e, a := testCase.URL, u.String(); e != a {
|
if e, a := testCase.URL, u.String(); e != a {
|
||||||
t.Errorf("%d: expected host %s, got %s", i, e, a)
|
t.Errorf("%d: expected host %s, got %s", i, e, a)
|
||||||
continue
|
continue
|
||||||
|
@ -190,7 +190,7 @@ func TestRequestExecuteRemoteCommand(t *testing.T) {
|
|||||||
server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount))
|
server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount))
|
||||||
|
|
||||||
url, _ := url.ParseRequestURI(server.URL)
|
url, _ := url.ParseRequestURI(server.URL)
|
||||||
c := client.NewRESTClient(url, unversioned.GroupVersion{Group: "x"}, nil, -1, -1)
|
c := client.NewRESTClient(url, "", unversioned.GroupVersion{Group: "x"}, nil, -1, -1)
|
||||||
req := c.Post().Resource("testing")
|
req := c.Post().Resource("testing")
|
||||||
req.SetHeader(httpstream.HeaderProtocolVersion, StreamProtocolV2Name)
|
req.SetHeader(httpstream.HeaderProtocolVersion, StreamProtocolV2Name)
|
||||||
req.Param("command", "ls")
|
req.Param("command", "ls")
|
||||||
@ -275,7 +275,7 @@ func TestRequestAttachRemoteCommand(t *testing.T) {
|
|||||||
server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, 1))
|
server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, 1))
|
||||||
|
|
||||||
url, _ := url.ParseRequestURI(server.URL)
|
url, _ := url.ParseRequestURI(server.URL)
|
||||||
c := client.NewRESTClient(url, unversioned.GroupVersion{Group: "x"}, nil, -1, -1)
|
c := client.NewRESTClient(url, "", unversioned.GroupVersion{Group: "x"}, nil, -1, -1)
|
||||||
req := c.Post().Resource("testing")
|
req := c.Post().Resource("testing")
|
||||||
|
|
||||||
conf := &client.Config{
|
conf := &client.Config{
|
||||||
|
@ -87,10 +87,10 @@ type Request struct {
|
|||||||
codec runtime.Codec
|
codec runtime.Codec
|
||||||
|
|
||||||
// generic components accessible via method setters
|
// generic components accessible via method setters
|
||||||
path string
|
pathPrefix string
|
||||||
subpath string
|
subpath string
|
||||||
params url.Values
|
params url.Values
|
||||||
headers http.Header
|
headers http.Header
|
||||||
|
|
||||||
// structural elements of the request that are part of the Kubernetes API conventions
|
// structural elements of the request that are part of the Kubernetes API conventions
|
||||||
namespace string
|
namespace string
|
||||||
@ -115,17 +115,22 @@ type Request struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRequest creates a new request helper object for accessing runtime.Objects on a server.
|
// NewRequest creates a new request helper object for accessing runtime.Objects on a server.
|
||||||
func NewRequest(client HTTPClient, verb string, baseURL *url.URL, groupVersion unversioned.GroupVersion, codec runtime.Codec, backoff BackoffManager) *Request {
|
func NewRequest(client HTTPClient, verb string, baseURL *url.URL, versionedAPIPath string, groupVersion unversioned.GroupVersion, codec runtime.Codec, backoff BackoffManager) *Request {
|
||||||
if backoff == nil {
|
if backoff == nil {
|
||||||
glog.V(2).Infof("Not implementing request backoff strategy.")
|
glog.V(2).Infof("Not implementing request backoff strategy.")
|
||||||
backoff = &NoBackoff{}
|
backoff = &NoBackoff{}
|
||||||
}
|
}
|
||||||
metrics.Register()
|
metrics.Register()
|
||||||
|
|
||||||
|
pathPrefix := "/"
|
||||||
|
if baseURL != nil {
|
||||||
|
pathPrefix = path.Join(pathPrefix, baseURL.Path)
|
||||||
|
}
|
||||||
return &Request{
|
return &Request{
|
||||||
client: client,
|
client: client,
|
||||||
verb: verb,
|
verb: verb,
|
||||||
baseURL: baseURL,
|
baseURL: baseURL,
|
||||||
path: baseURL.Path,
|
pathPrefix: path.Join(pathPrefix, versionedAPIPath),
|
||||||
groupVersion: groupVersion,
|
groupVersion: groupVersion,
|
||||||
codec: codec,
|
codec: codec,
|
||||||
backoffMgr: backoff,
|
backoffMgr: backoff,
|
||||||
@ -139,7 +144,7 @@ func (r *Request) Prefix(segments ...string) *Request {
|
|||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
r.path = path.Join(r.path, path.Join(segments...))
|
r.pathPrefix = path.Join(r.pathPrefix, path.Join(segments...))
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,11 +249,10 @@ func (r *Request) AbsPath(segments ...string) *Request {
|
|||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
if len(segments) == 1 {
|
r.pathPrefix = path.Join(r.baseURL.Path, path.Join(segments...))
|
||||||
|
if len(segments) == 1 && (len(r.baseURL.Path) > 1 || len(segments[0]) > 1) && strings.HasSuffix(segments[0], "/") {
|
||||||
// preserve any trailing slashes for legacy behavior
|
// preserve any trailing slashes for legacy behavior
|
||||||
r.path = segments[0]
|
r.pathPrefix += "/"
|
||||||
} else {
|
|
||||||
r.path = path.Join(segments...)
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -264,7 +268,7 @@ func (r *Request) RequestURI(uri string) *Request {
|
|||||||
r.err = err
|
r.err = err
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
r.path = locator.Path
|
r.pathPrefix = locator.Path
|
||||||
if len(locator.Query()) > 0 {
|
if len(locator.Query()) > 0 {
|
||||||
if r.params == nil {
|
if r.params == nil {
|
||||||
r.params = make(url.Values)
|
r.params = make(url.Values)
|
||||||
@ -554,14 +558,14 @@ func (r *Request) Body(obj interface{}) *Request {
|
|||||||
|
|
||||||
// URL returns the current working URL.
|
// URL returns the current working URL.
|
||||||
func (r *Request) URL() *url.URL {
|
func (r *Request) URL() *url.URL {
|
||||||
p := r.path
|
p := r.pathPrefix
|
||||||
if r.namespaceSet && len(r.namespace) > 0 {
|
if r.namespaceSet && len(r.namespace) > 0 {
|
||||||
p = path.Join(p, "namespaces", r.namespace)
|
p = path.Join(p, "namespaces", r.namespace)
|
||||||
}
|
}
|
||||||
if len(r.resource) != 0 {
|
if len(r.resource) != 0 {
|
||||||
p = path.Join(p, strings.ToLower(r.resource))
|
p = path.Join(p, strings.ToLower(r.resource))
|
||||||
}
|
}
|
||||||
// Join trims trailing slashes, so preserve r.path's trailing slash for backwards compat if nothing was changed
|
// Join trims trailing slashes, so preserve r.pathPrefix's trailing slash for backwards compat if nothing was changed
|
||||||
if len(r.resourceName) != 0 || len(r.subpath) != 0 || len(r.subresource) != 0 {
|
if len(r.resourceName) != 0 || len(r.subpath) != 0 || len(r.subresource) != 0 {
|
||||||
p = path.Join(p, r.resourceName, r.subresource, r.subpath)
|
p = path.Join(p, r.resourceName, r.subresource, r.subpath)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func TestRequestWithErrorWontChange(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRequestPreservesBaseTrailingSlash(t *testing.T) {
|
func TestRequestPreservesBaseTrailingSlash(t *testing.T) {
|
||||||
r := &Request{baseURL: &url.URL{}, path: "/path/"}
|
r := &Request{baseURL: &url.URL{}, pathPrefix: "/path/"}
|
||||||
if s := r.URL().String(); s != "/path/" {
|
if s := r.URL().String(); s != "/path/" {
|
||||||
t.Errorf("trailing slash should be preserved: %s", s)
|
t.Errorf("trailing slash should be preserved: %s", s)
|
||||||
}
|
}
|
||||||
@ -113,8 +113,8 @@ func TestRequestSetsNamespace(t *testing.T) {
|
|||||||
|
|
||||||
func TestRequestOrdersNamespaceInPath(t *testing.T) {
|
func TestRequestOrdersNamespaceInPath(t *testing.T) {
|
||||||
r := (&Request{
|
r := (&Request{
|
||||||
baseURL: &url.URL{},
|
baseURL: &url.URL{},
|
||||||
path: "/test/",
|
pathPrefix: "/test/",
|
||||||
}).Name("bar").Resource("baz").Namespace("foo")
|
}).Name("bar").Resource("baz").Namespace("foo")
|
||||||
if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar" {
|
if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar" {
|
||||||
t.Errorf("namespace should be in order in path: %s", s)
|
t.Errorf("namespace should be in order in path: %s", s)
|
||||||
@ -123,8 +123,8 @@ func TestRequestOrdersNamespaceInPath(t *testing.T) {
|
|||||||
|
|
||||||
func TestRequestOrdersSubResource(t *testing.T) {
|
func TestRequestOrdersSubResource(t *testing.T) {
|
||||||
r := (&Request{
|
r := (&Request{
|
||||||
baseURL: &url.URL{},
|
baseURL: &url.URL{},
|
||||||
path: "/test/",
|
pathPrefix: "/test/",
|
||||||
}).Name("bar").Resource("baz").Namespace("foo").Suffix("test").SubResource("a", "b")
|
}).Name("bar").Resource("baz").Namespace("foo").Suffix("test").SubResource("a", "b")
|
||||||
if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar/a/b/test" {
|
if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar/a/b/test" {
|
||||||
t.Errorf("namespace should be in order in path: %s", s)
|
t.Errorf("namespace should be in order in path: %s", s)
|
||||||
@ -217,7 +217,7 @@ func TestRequestURI(t *testing.T) {
|
|||||||
r := (&Request{}).Param("foo", "a")
|
r := (&Request{}).Param("foo", "a")
|
||||||
r.Prefix("other")
|
r.Prefix("other")
|
||||||
r.RequestURI("/test?foo=b&a=b&c=1&c=2")
|
r.RequestURI("/test?foo=b&a=b&c=1&c=2")
|
||||||
if r.path != "/test" {
|
if r.pathPrefix != "/test" {
|
||||||
t.Errorf("path is wrong: %#v", r)
|
t.Errorf("path is wrong: %#v", r)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(r.params, url.Values{"a": []string{"b"}, "foo": []string{"b"}, "c": []string{"1", "2"}}) {
|
if !reflect.DeepEqual(r.params, url.Values{"a": []string{"b"}, "foo": []string{"b"}, "c": []string{"1", "2"}}) {
|
||||||
@ -265,7 +265,7 @@ func TestResultIntoWithErrReturnsErr(t *testing.T) {
|
|||||||
|
|
||||||
func TestURLTemplate(t *testing.T) {
|
func TestURLTemplate(t *testing.T) {
|
||||||
uri, _ := url.Parse("http://localhost")
|
uri, _ := url.Parse("http://localhost")
|
||||||
r := NewRequest(nil, "POST", uri, unversioned.GroupVersion{Group: "test"}, nil, nil)
|
r := NewRequest(nil, "POST", uri, "", unversioned.GroupVersion{Group: "test"}, nil, nil)
|
||||||
r.Prefix("pre1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0")
|
r.Prefix("pre1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0")
|
||||||
full := r.URL()
|
full := r.URL()
|
||||||
if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" {
|
if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" {
|
||||||
@ -326,7 +326,7 @@ func TestTransformResponse(t *testing.T) {
|
|||||||
{Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid},
|
{Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid},
|
||||||
}
|
}
|
||||||
for i, test := range testCases {
|
for i, test := range testCases {
|
||||||
r := NewRequest(nil, "", uri, *testapi.Default.GroupVersion(), testapi.Default.Codec(), nil)
|
r := NewRequest(nil, "", uri, "", *testapi.Default.GroupVersion(), testapi.Default.Codec(), nil)
|
||||||
if test.Response.Body == nil {
|
if test.Response.Body == nil {
|
||||||
test.Response.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
test.Response.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||||
}
|
}
|
||||||
@ -450,7 +450,7 @@ func TestRequestWatch(t *testing.T) {
|
|||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Request: &Request{baseURL: &url.URL{}, path: "%"},
|
Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"},
|
||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -579,7 +579,7 @@ func TestRequestStream(t *testing.T) {
|
|||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Request: &Request{baseURL: &url.URL{}, path: "%"},
|
Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"},
|
||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -665,7 +665,7 @@ func TestRequestDo(t *testing.T) {
|
|||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Request: &Request{baseURL: &url.URL{}, path: "%"},
|
Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"},
|
||||||
Err: true,
|
Err: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1062,11 +1062,37 @@ func TestVerbs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAbsPath(t *testing.T) {
|
func TestAbsPath(t *testing.T) {
|
||||||
expectedPath := "/bar/foo"
|
for i, tc := range []struct {
|
||||||
c := testRESTClient(t, nil)
|
configPrefix string
|
||||||
r := c.Post().Prefix("/foo").AbsPath(expectedPath)
|
resourcePrefix string
|
||||||
if r.path != expectedPath {
|
absPath string
|
||||||
t.Errorf("unexpected path: %s, expected %s", r.path, expectedPath)
|
wantsAbsPath string
|
||||||
|
}{
|
||||||
|
{"", "", "", "/"},
|
||||||
|
{"", "", "/", "/"},
|
||||||
|
{"", "", "/api", "/api"},
|
||||||
|
{"", "", "/api/", "/api/"},
|
||||||
|
{"", "", "/apis", "/apis"},
|
||||||
|
{"", "/foo", "/bar/foo", "/bar/foo"},
|
||||||
|
{"", "/api/foo/123", "/bar/foo", "/bar/foo"},
|
||||||
|
{"/p1", "", "", "/p1"},
|
||||||
|
{"/p1", "", "/", "/p1/"},
|
||||||
|
{"/p1", "", "/api", "/p1/api"},
|
||||||
|
{"/p1", "", "/apis", "/p1/apis"},
|
||||||
|
{"/p1", "/r1", "/apis", "/p1/apis"},
|
||||||
|
{"/p1", "/api/r1", "/apis", "/p1/apis"},
|
||||||
|
{"/p1/api/p2", "", "", "/p1/api/p2"},
|
||||||
|
{"/p1/api/p2", "", "/", "/p1/api/p2/"},
|
||||||
|
{"/p1/api/p2", "", "/api", "/p1/api/p2/api"},
|
||||||
|
{"/p1/api/p2", "", "/api/", "/p1/api/p2/api/"},
|
||||||
|
{"/p1/api/p2", "/r1", "/api/", "/p1/api/p2/api/"},
|
||||||
|
{"/p1/api/p2", "/api/r1", "/api/", "/p1/api/p2/api/"},
|
||||||
|
} {
|
||||||
|
c := NewOrDie(&Config{Host: "http://localhost:123" + tc.configPrefix})
|
||||||
|
r := c.Post().Prefix(tc.resourcePrefix).AbsPath(tc.absPath)
|
||||||
|
if r.pathPrefix != tc.wantsAbsPath {
|
||||||
|
t.Errorf("test case %d failed, unexpected path: %q, expected %q", i, r.pathPrefix, tc.wantsAbsPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,7 +1109,7 @@ func TestUintParam(t *testing.T) {
|
|||||||
|
|
||||||
for _, item := range table {
|
for _, item := range table {
|
||||||
u, _ := url.Parse("http://localhost")
|
u, _ := url.Parse("http://localhost")
|
||||||
r := NewRequest(nil, "GET", u, unversioned.GroupVersion{Group: "test"}, nil, nil).AbsPath("").UintParam(item.name, item.testVal)
|
r := NewRequest(nil, "GET", u, "", unversioned.GroupVersion{Group: "test"}, nil, nil).AbsPath("").UintParam(item.name, item.testVal)
|
||||||
if e, a := item.expectStr, r.URL().String(); e != a {
|
if e, a := item.expectStr, r.URL().String(); e != a {
|
||||||
t.Errorf("expected %v, got %v", e, a)
|
t.Errorf("expected %v, got %v", e, a)
|
||||||
}
|
}
|
||||||
@ -1255,6 +1281,6 @@ func testRESTClient(t testing.TB, srv *httptest.Server) *RESTClient {
|
|||||||
t.Fatalf("failed to parse test URL: %v", err)
|
t.Fatalf("failed to parse test URL: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
baseURL.Path = testapi.Default.ResourcePath("", "", "")
|
versionedAPIPath := testapi.Default.ResourcePath("", "", "")
|
||||||
return NewRESTClient(baseURL, *testapi.Default.GroupVersion(), testapi.Default.Codec(), 0, 0)
|
return NewRESTClient(baseURL, versionedAPIPath, *testapi.Default.GroupVersion(), testapi.Default.Codec(), 0, 0)
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@ const (
|
|||||||
//
|
//
|
||||||
// Most consumers should use client.New() to get a Kubernetes API client.
|
// Most consumers should use client.New() to get a Kubernetes API client.
|
||||||
type RESTClient struct {
|
type RESTClient struct {
|
||||||
baseURL *url.URL
|
baseURL *url.URL
|
||||||
|
versionedAPIPath string
|
||||||
// A string identifying the version of the API this client is expected to use.
|
// A string identifying the version of the API this client is expected to use.
|
||||||
groupVersion unversioned.GroupVersion
|
groupVersion unversioned.GroupVersion
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ type RESTClient struct {
|
|||||||
// NewRESTClient creates a new RESTClient. This client performs generic REST functions
|
// NewRESTClient creates a new RESTClient. This client performs generic REST functions
|
||||||
// such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and
|
// such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and
|
||||||
// decoding of responses from the server.
|
// decoding of responses from the server.
|
||||||
func NewRESTClient(baseURL *url.URL, groupVersion unversioned.GroupVersion, c runtime.Codec, maxQPS float32, maxBurst int) *RESTClient {
|
func NewRESTClient(baseURL *url.URL, versionedAPIPath string, groupVersion unversioned.GroupVersion, c runtime.Codec, maxQPS float32, maxBurst int) *RESTClient {
|
||||||
base := *baseURL
|
base := *baseURL
|
||||||
if !strings.HasSuffix(base.Path, "/") {
|
if !strings.HasSuffix(base.Path, "/") {
|
||||||
base.Path += "/"
|
base.Path += "/"
|
||||||
@ -77,10 +78,11 @@ func NewRESTClient(baseURL *url.URL, groupVersion unversioned.GroupVersion, c ru
|
|||||||
throttle = util.NewTokenBucketRateLimiter(maxQPS, maxBurst)
|
throttle = util.NewTokenBucketRateLimiter(maxQPS, maxBurst)
|
||||||
}
|
}
|
||||||
return &RESTClient{
|
return &RESTClient{
|
||||||
baseURL: &base,
|
baseURL: &base,
|
||||||
groupVersion: groupVersion,
|
versionedAPIPath: versionedAPIPath,
|
||||||
Codec: c,
|
groupVersion: groupVersion,
|
||||||
Throttle: throttle,
|
Codec: c,
|
||||||
|
Throttle: throttle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +125,9 @@ func (c *RESTClient) Verb(verb string) *Request {
|
|||||||
backoff := readExpBackoffConfig()
|
backoff := readExpBackoffConfig()
|
||||||
|
|
||||||
if c.Client == nil {
|
if c.Client == nil {
|
||||||
return NewRequest(nil, verb, c.baseURL, c.groupVersion, c.Codec, backoff)
|
return NewRequest(nil, verb, c.baseURL, c.versionedAPIPath, c.groupVersion, c.Codec, backoff)
|
||||||
}
|
}
|
||||||
return NewRequest(c.Client, verb, c.baseURL, c.groupVersion, c.Codec, backoff)
|
return NewRequest(c.Client, verb, c.baseURL, c.versionedAPIPath, c.groupVersion, c.Codec, backoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post begins a POST request. Short for c.Verb("POST").
|
// Post begins a POST request. Short for c.Verb("POST").
|
||||||
|
@ -145,14 +145,10 @@ func TestSetWithPathPrefixIntoExistingStruct(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
expectedHost := "http://cow.org:8080"
|
expectedHost := "http://cow.org:8080/foo/baz"
|
||||||
if expectedHost != dcc.Host {
|
if expectedHost != dcc.Host {
|
||||||
t.Fatalf("expected client.Config.Host = %q instead of %q", expectedHost, dcc.Host)
|
t.Fatalf("expected client.Config.Host = %q instead of %q", expectedHost, dcc.Host)
|
||||||
}
|
}
|
||||||
expectedPrefix := "/foo/baz"
|
|
||||||
if expectedPrefix != dcc.Prefix {
|
|
||||||
t.Fatalf("expected client.Config.Prefix = %q instead of %q", expectedPrefix, dcc.Prefix)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnsetStruct(t *testing.T) {
|
func TestUnsetStruct(t *testing.T) {
|
||||||
|
@ -204,7 +204,6 @@ var _ = Describe("Kubectl client", func() {
|
|||||||
Failf("Unable to parse URL %s. Error=%s", apiServer, err)
|
Failf("Unable to parse URL %s. Error=%s", apiServer, err)
|
||||||
}
|
}
|
||||||
apiServerUrl.Scheme = "https"
|
apiServerUrl.Scheme = "https"
|
||||||
apiServerUrl.Path = "/api"
|
|
||||||
if !strings.Contains(apiServer, ":443") {
|
if !strings.Contains(apiServer, ":443") {
|
||||||
apiServerUrl.Host = apiServerUrl.Host + ":443"
|
apiServerUrl.Host = apiServerUrl.Host + ":443"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user