diff --git a/cmd/integration/integration.go b/cmd/integration/integration.go index 2dd3f07ace5..bb6ee8ee8a9 100644 --- a/cmd/integration/integration.go +++ b/cmd/integration/integration.go @@ -39,7 +39,6 @@ import ( apierrors "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/client/record" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -132,11 +131,11 @@ func startComponents(firstManifestURL, secondManifestURL string) (string, string // We will fix this by supporting multiple group versions in Config cl.ExperimentalClient = client.NewExperimentalOrDie(&client.Config{Host: apiServer.URL, Version: testapi.Experimental.Version()}) - etcdStorage, err := master.NewEtcdStorage(etcdClient, latest.InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) + etcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) if err != nil { glog.Fatalf("Unable to get etcd storage: %v", err) } - expEtcdStorage, err := master.NewEtcdStorage(etcdClient, explatest.InterfacesFor, testapi.Experimental.Version(), etcdtest.PathPrefix()) + expEtcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("experimental").InterfacesFor, testapi.Experimental.Version(), etcdtest.PathPrefix()) if err != nil { glog.Fatalf("Unable to get etcd storage for experimental: %v", err) } diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index c421167bc02..e5dfde1eb1e 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -35,7 +35,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/capabilities" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -340,13 +339,21 @@ func (s *APIServer) Run(_ []string) error { glog.Fatalf("Invalid server address: %v", err) } - etcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, latest.InterfacesFor, latest.Version, s.StorageVersion, s.EtcdPathPrefix) + etcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, latest.GroupOrDie("").InterfacesFor, latest.GroupOrDie("").Version, s.StorageVersion, s.EtcdPathPrefix) if err != nil { glog.Fatalf("Invalid storage version or misconfigured etcd: %v", err) } - expEtcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, explatest.InterfacesFor, explatest.Version, s.ExpStorageVersion, s.EtcdPathPrefix) - if err != nil { - glog.Fatalf("Invalid experimental storage version or misconfigured etcd: %v", err) + + var expEtcdStorage storage.Interface + if enableExp { + g, err := latest.Group("experimental") + if err != nil { + glog.Fatalf("experimental API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err) + } + expEtcdStorage, err = newEtcd(s.EtcdConfigFile, s.EtcdServerList, g.InterfacesFor, g.Version, s.ExpStorageVersion, s.EtcdPathPrefix) + if err != nil { + glog.Fatalf("Invalid experimental storage version or misconfigured etcd: %v", err) + } } n := s.ServiceClusterIPRange diff --git a/cmd/kube-version-change/version.go b/cmd/kube-version-change/version.go index a5715d76ecb..4ae8c3b7e50 100644 --- a/cmd/kube-version-change/version.go +++ b/cmd/kube-version-change/version.go @@ -39,7 +39,7 @@ var ( inputSource = flag.StringP("input", "i", "-", "Input source; '-' means stdin") outputDest = flag.StringP("output", "o", "-", "Output destination; '-' means stdout") rewrite = flag.StringP("rewrite", "r", "", "If nonempty, use this as both input and output.") - outputVersion = flag.StringP("out-version", "v", latest.Version, "Version to convert input to") + outputVersion = flag.StringP("out-version", "v", latest.GroupOrDie("").Version, "Version to convert input to") ) // isYAML determines whether data is JSON or YAML formatted by seeing diff --git a/examples/examples_test.go b/examples/examples_test.go index 087c0780221..3a43c1dbc58 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -27,7 +27,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/capabilities" "k8s.io/kubernetes/pkg/runtime" @@ -366,7 +366,7 @@ func TestExampleObjectSchemas(t *testing.T) { } //TODO: Add validate method for &schedulerapi.Policy } else { - if err := latest.Codec.DecodeInto(data, expectedType); err != nil { + if err := testapi.Default.Codec().DecodeInto(data, expectedType); err != nil { t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data)) return } @@ -452,14 +452,14 @@ func TestReadme(t *testing.T) { if err != nil { t.Errorf("%s could not be converted to JSON: %v\n%s", path, err, string(content)) } - if err := latest.Codec.DecodeInto(json, expectedType); err != nil { + if err := testapi.Default.Codec().DecodeInto(json, expectedType); err != nil { t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(content)) continue } if errors := validateObject(expectedType); len(errors) > 0 { t.Errorf("%s did not validate correctly: %v", path, errors) } - _, err = latest.Codec.Encode(expectedType) + _, err = testapi.Default.Codec().Encode(expectedType) if err != nil { t.Errorf("Could not encode object: %v", err) continue diff --git a/examples/https-nginx/make_secret.go b/examples/https-nginx/make_secret.go index 67a93ee70ba..308f071e82f 100644 --- a/examples/https-nginx/make_secret.go +++ b/examples/https-nginx/make_secret.go @@ -62,5 +62,5 @@ func main() { "nginx.key": nginxKey, }, } - fmt.Printf(runtime.EncodeOrDie(latest.Codec, secret)) + fmt.Printf(runtime.EncodeOrDie(latest.GroupOrDie("").Codec, secret)) } diff --git a/examples/sharing-clusters/make_secret.go b/examples/sharing-clusters/make_secret.go index 6cf03c77f9d..492299c28e8 100644 --- a/examples/sharing-clusters/make_secret.go +++ b/examples/sharing-clusters/make_secret.go @@ -59,5 +59,5 @@ func main() { "config": cfg, }, } - fmt.Printf(runtime.EncodeOrDie(latest.Codec, secret)) + fmt.Printf(runtime.EncodeOrDie(latest.GroupOrDie("").Codec, secret)) } diff --git a/hack/after-build/update-swagger-spec.sh b/hack/after-build/update-swagger-spec.sh index 05634762a58..1c4b85d582b 100755 --- a/hack/after-build/update-swagger-spec.sh +++ b/hack/after-build/update-swagger-spec.sh @@ -50,7 +50,7 @@ kube::etcd::start # Start kube-apiserver kube::log::status "Starting kube-apiserver" -KUBE_API_VERSIONS="v1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ +KUBE_API_VERSIONS="v1,experimental/v1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ --address="127.0.0.1" \ --public-address-override="127.0.0.1" \ --port="${API_PORT}" \ diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 2ffa525c381..ea58af617a7 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -128,7 +128,7 @@ kube::util::wait_for_url "http://127.0.0.1:${KUBELET_HEALTHZ_PORT}/healthz" "kub # Start kube-apiserver kube::log::status "Starting kube-apiserver" -KUBE_API_VERSIONS="v1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ +KUBE_API_VERSIONS="v1,experimental/v1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ --address="127.0.0.1" \ --public-address-override="127.0.0.1" \ --port="${API_PORT}" \ @@ -813,7 +813,7 @@ kube_api_versions=( v1 ) for version in "${kube_api_versions[@]}"; do - KUBE_API_VERSIONS="v1" runTests "${version}" + KUBE_API_VERSIONS="v1,experimental/v1" runTests "${version}" done kube::log::status "TEST PASSED" diff --git a/hack/test-go.sh b/hack/test-go.sh index 59e8881c0c1..c54a27947d8 100755 --- a/hack/test-go.sh +++ b/hack/test-go.sh @@ -283,7 +283,7 @@ for (( i=0, j=0; ; )); do # KUBE_TEST_API sets the version of each group to be tested. KUBE_API_VERSIONS # register the groups/versions as supported by k8s. So KUBE_API_VERSIONS # needs to be the superset of KUBE_TEST_API. - KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1" ETCD_PREFIX=${etcdPrefix} runTests "$@" + KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1,experimental/v1" ETCD_PREFIX=${etcdPrefix} runTests "$@" i=${i}+1 j=${j}+1 if [[ i -eq ${apiVersionsCount} ]] && [[ j -eq ${etcdPrefixesCount} ]]; then diff --git a/hack/test-integration.sh b/hack/test-integration.sh index dcd9c9e87d4..1e103d87a6e 100755 --- a/hack/test-integration.sh +++ b/hack/test-integration.sh @@ -47,18 +47,18 @@ runTests() { KUBE_GOFLAGS="-tags 'integration no-docker' " \ KUBE_RACE="-race" \ KUBE_TEST_API_VERSIONS="$1" \ - KUBE_API_VERSIONS="v1" \ + KUBE_API_VERSIONS="v1,experimental/v1" \ "${KUBE_ROOT}/hack/test-go.sh" test/integration kube::log::status "Running integration test scenario" - KUBE_API_VERSIONS="v1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \ + KUBE_API_VERSIONS="v1,experimental/v1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \ --max-concurrency="${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY}" cleanup } -KUBE_API_VERSIONS="v1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration +KUBE_API_VERSIONS="v1,experimental/v1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration # Run cleanup to stop etcd on interrupt or other kill signal. trap cleanup EXIT diff --git a/pkg/api/install/install.go b/pkg/api/install/install.go new file mode 100644 index 00000000000..14293ac14dc --- /dev/null +++ b/pkg/api/install/install.go @@ -0,0 +1,116 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package install installs the v1 monolithic api, making it available as an +// option to all of the API encoding/decoding machinery. +package install + +import ( + "fmt" + "strings" + + "github.com/golang/glog" + + "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/util/sets" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/registered" + apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/runtime" +) + +// userResources is a group of resources mostly used by a kubectl user +var userResources = []string{"rc", "svc", "pods", "pvc"} + +const importPrefix = "k8s.io/kubernetes/pkg/api" + +var accessor = meta.NewAccessor() + +func init() { + groupMeta, err := latest.RegisterGroup("") + if err != nil { + glog.V(4).Infof("%v", err) + return + } + // Use the first API version in the list of registered versions as the latest. + registeredGroupVersions := registered.GroupVersionsForGroup("") + groupVersion := registeredGroupVersions[0] + *groupMeta = latest.GroupMeta{ + GroupVersion: groupVersion, + Group: apiutil.GetGroup(groupVersion), + Version: apiutil.GetVersion(groupVersion), + Codec: runtime.CodecFor(api.Scheme, groupVersion), + } + var versions []string + for i := len(registeredGroupVersions) - 1; i >= 0; i-- { + versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) + } + groupMeta.Versions = versions + + groupMeta.SelfLinker = runtime.SelfLinker(accessor) + + // the list of kinds that are scoped at the root of the api hierarchy + // if a kind is not enumerated here, it is assumed to have a namespace scope + // the list of kinds that are scoped at the root of the api hierarchy + // if a kind is not enumerated here, it is assumed to have a namespace scope + rootScoped := sets.NewString( + "Node", + "Minion", + "Namespace", + "PersistentVolume", + ) + + // these kinds should be excluded from the list of resources + ignoredKinds := sets.NewString( + "ListOptions", + "DeleteOptions", + "Status", + "PodLogOptions", + "PodExecOptions", + "PodAttachOptions", + "PodProxyOptions", + "ThirdPartyResource", + "ThirdPartyResourceData", + "ThirdPartyResourceList") + + mapper := api.NewDefaultRESTMapper("api", versions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + // setup aliases for groups of resources + mapper.AddResourceAlias("all", userResources...) + groupMeta.RESTMapper = mapper + api.RegisterRESTMapper(groupMeta.RESTMapper) + groupMeta.InterfacesFor = interfacesFor +} + +// InterfacesFor returns the default Codec and ResourceVersioner for a given version +// string, or an error if the version is not known. +func interfacesFor(version string) (*meta.VersionInterfaces, error) { + switch version { + case "v1": + return &meta.VersionInterfaces{ + Codec: v1.Codec, + ObjectConvertor: api.Scheme, + MetadataAccessor: accessor, + }, nil + default: + { + g, _ := latest.Group("") + return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(g.Versions, ", ")) + } + } +} diff --git a/pkg/api/latest/latest_test.go b/pkg/api/install/install_test.go similarity index 69% rename from pkg/api/latest/latest_test.go rename to pkg/api/install/install_test.go index bfce20aa74a..e2c59ce8b09 100644 --- a/pkg/api/latest/latest_test.go +++ b/pkg/api/install/install_test.go @@ -14,13 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package latest +package install import ( "encoding/json" "testing" internal "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/latest" ) func TestResourceVersioner(t *testing.T) { @@ -45,7 +46,9 @@ func TestResourceVersioner(t *testing.T) { func TestCodec(t *testing.T) { pod := internal.Pod{} - data, err := Codec.Encode(&pod) + // We do want to use package latest rather than testapi here, because we + // want to test if the package install and package latest work as expected. + data, err := latest.GroupOrDie("").Codec.Encode(&pod) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -53,33 +56,33 @@ func TestCodec(t *testing.T) { if err := json.Unmarshal(data, &other); err != nil { t.Fatalf("unexpected error: %v", err) } - if other.APIVersion != Version || other.Kind != "Pod" { + if other.APIVersion != latest.GroupOrDie("").Version || other.Kind != "Pod" { t.Errorf("unexpected unmarshalled object %#v", other) } } func TestInterfacesFor(t *testing.T) { - if _, err := InterfacesFor(""); err == nil { + if _, err := latest.GroupOrDie("").InterfacesFor(""); err == nil { t.Fatalf("unexpected non-error: %v", err) } - for i, version := range append([]string{Version, OldestVersion}, Versions...) { - if vi, err := InterfacesFor(version); err != nil || vi == nil { + for i, version := range append([]string{latest.GroupOrDie("").Version}, latest.GroupOrDie("").Versions...) { + if vi, err := latest.GroupOrDie("").InterfacesFor(version); err != nil || vi == nil { t.Fatalf("%d: unexpected result: %v", i, err) } } } func TestRESTMapper(t *testing.T) { - if v, k, err := RESTMapper.VersionAndKindForResource("replicationcontrollers"); err != nil || v != "v1" || k != "ReplicationController" { + if v, k, err := latest.GroupOrDie("").RESTMapper.VersionAndKindForResource("replicationcontrollers"); err != nil || v != "v1" || k != "ReplicationController" { t.Errorf("unexpected version mapping: %s %s %v", v, k, err) } - if m, err := RESTMapper.RESTMapping("PodTemplate", ""); err != nil || m.APIVersion != "v1" || m.Resource != "podtemplates" { + if m, err := latest.GroupOrDie("").RESTMapper.RESTMapping("PodTemplate", ""); err != nil || m.APIVersion != "v1" || m.Resource != "podtemplates" { t.Errorf("unexpected version mapping: %#v %v", m, err) } - for _, version := range Versions { - mapping, err := RESTMapper.RESTMapping("ReplicationController", version) + for _, version := range latest.GroupOrDie("").Versions { + mapping, err := latest.GroupOrDie("").RESTMapper.RESTMapping("ReplicationController", version) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -91,7 +94,7 @@ func TestRESTMapper(t *testing.T) { t.Errorf("incorrect version: %v", mapping) } - interfaces, _ := InterfacesFor(version) + interfaces, _ := latest.GroupOrDie("").InterfacesFor(version) if mapping.Codec != interfaces.Codec { t.Errorf("unexpected codec: %#v, expected: %#v", mapping, interfaces) } diff --git a/pkg/api/latest/latest.go b/pkg/api/latest/latest.go index 2e53b4f00f3..250b7783aac 100644 --- a/pkg/api/latest/latest.go +++ b/pkg/api/latest/latest.go @@ -18,105 +18,96 @@ package latest import ( "fmt" - "strings" - "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" - "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/sets" ) -// Version is the string that represents the current external default version. -var Version string +var ( + allGroups = GroupMetaMap{} + // Group is a shortcut to allGroups.Group. + Group = allGroups.Group + // RegisterGroup is a shortcut to allGroups.RegisterGroup. + RegisterGroup = allGroups.RegisterGroup + // GroupOrDie is a shortcut to allGroups.GroupOrDie. + GroupOrDie = allGroups.GroupOrDie +) -// OldestVersion is the string that represents the oldest server version supported, -// for client code that wants to hardcode the lowest common denominator. -var OldestVersion string +// GroupMetaMap is a map between group names and their metadata. +type GroupMetaMap map[string]*GroupMeta -// Versions is the list of versions that are recognized in code. The order provided -// may be assumed to be least feature rich to most feature rich, and clients may -// choose to prefer the latter items in the list over the former items when presented -// with a set of versions to choose. -var Versions []string - -// Codec is the default codec for serializing output that should use -// the latest supported version. Use this Codec when writing to -// disk, a data store that is not dynamically versioned, or in tests. -// This codec can decode any object that Kubernetes is aware of. -var Codec runtime.Codec - -// accessor is the shared static metadata accessor for the API. -var accessor = meta.NewAccessor() - -// SelfLinker can set or get the SelfLink field of all API types. -// TODO: when versioning changes, make this part of each API definition. -// TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses -// to go through the InterfacesFor method below. -var SelfLinker = runtime.SelfLinker(accessor) - -// RESTMapper provides the default mapping between REST paths and the objects declared in api.Scheme and all known -// Kubernetes versions. -var RESTMapper meta.RESTMapper - -// userResources is a group of resources mostly used by a kubectl user -var userResources = []string{"rc", "svc", "pods", "pvc"} - -const importPrefix = "k8s.io/kubernetes/pkg/api" - -func init() { - // Use the first API version in the list of registered versions as the latest. - Version = registered.RegisteredVersions[0] - OldestVersion = registered.RegisteredVersions[len(registered.RegisteredVersions)-1] - Codec = runtime.CodecFor(api.Scheme, Version) - // Put the registered versions in Versions in reverse order. - versions := registered.RegisteredVersions - Versions = []string{} - for i := len(versions) - 1; i >= 0; i-- { - Versions = append(Versions, versions[i]) +// RegisterGroup registers a group to GroupMetaMap. +func (g GroupMetaMap) RegisterGroup(group string) (*GroupMeta, error) { + _, found := g[group] + if found { + return nil, fmt.Errorf("group %v is already registered", g) } - - // the list of kinds that are scoped at the root of the api hierarchy - // if a kind is not enumerated here, it is assumed to have a namespace scope - rootScoped := sets.NewString( - "Node", - "Minion", - "Namespace", - "PersistentVolume", - ) - - // these kinds should be excluded from the list of resources - ignoredKinds := sets.NewString( - "ListOptions", - "DeleteOptions", - "Status", - "PodLogOptions", - "PodExecOptions", - "PodAttachOptions", - "PodProxyOptions", - "ThirdPartyResource", - "ThirdPartyResourceData", - "ThirdPartyResourceList") - - mapper := api.NewDefaultRESTMapper("api", versions, InterfacesFor, importPrefix, ignoredKinds, rootScoped) - // setup aliases for groups of resources - mapper.AddResourceAlias("all", userResources...) - RESTMapper = mapper - api.RegisterRESTMapper(RESTMapper) + if len(registered.GroupVersionsForGroup(group)) == 0 { + return nil, fmt.Errorf("No version is registered for group %v", group) + } + g[group] = &GroupMeta{} + return g[group], nil } -// InterfacesFor returns the default Codec and ResourceVersioner for a given version -// string, or an error if the version is not known. -func InterfacesFor(version string) (*meta.VersionInterfaces, error) { - switch version { - case "v1": - return &meta.VersionInterfaces{ - Codec: v1.Codec, - ObjectConvertor: api.Scheme, - MetadataAccessor: accessor, - }, nil - default: - return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", ")) +// Group returns the metadata of a group if the gruop is registered, otherwise +// an erorr is returned. +func (g GroupMetaMap) Group(group string) (*GroupMeta, error) { + groupMeta, found := g[group] + if !found { + return nil, fmt.Errorf("no version is registered for group %v", group) } + return groupMeta, nil +} + +// TODO: This is an expedient function, because we don't check if a Group is +// supported throughout the code base. We will abandon this function and +// checking the error returned by the Group() function. +func (g GroupMetaMap) GroupOrDie(group string) *GroupMeta { + groupMeta, found := g[group] + if !found { + panic(fmt.Sprintf("no version is registered for group %v", group)) + } + return groupMeta +} + +// GroupMeta stores the metadata of a group, such as the latest supported version. +type GroupMeta struct { + // GroupVersion represents the current external default version of the group. It + // is in the form of "group/version". + GroupVersion string + + // Version represents the current external default version of the group. + // It equals to the "version" part of GroupVersion. + Version string + + // Group represents the name of the group + Group string + + // Versions is the list of versions that are recognized in code. The order + // provided is assumed to be from the oldest to the newest, e.g., + // Versions[0] == oldest and Versions[N-1] == newest. + // Clients may choose to prefer the latter items in the list over the former + // items when presented with a set of versions to choose. + Versions []string + + // Codec is the default codec for serializing output that should use + // the latest supported version. Use this Codec when writing to + // disk, a data store that is not dynamically versioned, or in tests. + // This codec can decode any object that Kubernetes is aware of. + Codec runtime.Codec + + // SelfLinker can set or get the SelfLink field of all API types. + // TODO: when versioning changes, make this part of each API definition. + // TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses + // to go through the InterfacesFor method below. + SelfLinker runtime.SelfLinker + + // RESTMapper provides the default mapping between REST paths and the objects declared in api.Scheme and all known + // Kubernetes versions. + RESTMapper meta.RESTMapper + + // InterfacesFor returns the default Codec and ResourceVersioner for a given version + // string, or an error if the version is not known. + InterfacesFor func(version string) (*meta.VersionInterfaces, error) } diff --git a/pkg/api/registered/registered.go b/pkg/api/registered/registered.go index 9248dd831f9..c1601c2af4c 100644 --- a/pkg/api/registered/registered.go +++ b/pkg/api/registered/registered.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/golang/glog" + apiutil "k8s.io/kubernetes/pkg/api/util" ) // List of registered API versions. @@ -29,12 +30,14 @@ import ( var RegisteredVersions []string func init() { + // TODO: caesarxuchao: rename this variable to validGroupVersions validAPIVersions := map[string]bool{ - "v1": true, + "v1": true, + "experimental/v1": true, } // The default list of supported api versions, in order of most preferred to the least. - defaultSupportedVersions := "v1" + defaultSupportedVersions := "v1,experimental/v1" // Env var KUBE_API_VERSIONS is a comma separated list of API versions that should be registered in the scheme. // The versions should be in the order of most preferred to the least. supportedVersions := os.Getenv("KUBE_API_VERSIONS") @@ -63,3 +66,15 @@ func IsRegisteredAPIVersion(version string) bool { } return false } + +// GroupVersionsForGroup returns the registered versions of a group in the form +// of "group/version". +func GroupVersionsForGroup(group string) []string { + ret := []string{} + for _, v := range RegisteredVersions { + if apiutil.GetGroup(v) == group { + ret = append(ret, v) + } + } + return ret +} diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index c500623bb5e..5ebab117c3b 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -25,7 +25,6 @@ import ( "github.com/davecgh/go-spew/spew" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/testapi" apitesting "k8s.io/kubernetes/pkg/api/testing" @@ -167,8 +166,8 @@ func TestEncode_Ptr(t *testing.T) { }, } obj := runtime.Object(pod) - data, err := latest.Codec.Encode(obj) - obj2, err2 := latest.Codec.Decode(data) + data, err := testapi.Default.Codec().Encode(obj) + obj2, err2 := testapi.Default.Codec().Decode(data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } @@ -182,11 +181,11 @@ func TestEncode_Ptr(t *testing.T) { func TestBadJSONRejection(t *testing.T) { badJSONMissingKind := []byte(`{ }`) - if _, err := latest.Codec.Decode(badJSONMissingKind); err == nil { + if _, err := testapi.Default.Codec().Decode(badJSONMissingKind); err == nil { t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) } badJSONUnknownType := []byte(`{"kind": "bar"}`) - if _, err1 := latest.Codec.Decode(badJSONUnknownType); err1 == nil { + if _, err1 := testapi.Default.Codec().Decode(badJSONUnknownType); err1 == nil { t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) } /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) @@ -202,7 +201,7 @@ func BenchmarkEncode(b *testing.B) { apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) for i := 0; i < b.N; i++ { - latest.Codec.Encode(&pod) + testapi.Default.Codec().Encode(&pod) } } @@ -220,9 +219,9 @@ func BenchmarkDecode(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) - data, _ := latest.Codec.Encode(&pod) + data, _ := testapi.Default.Codec().Encode(&pod) for i := 0; i < b.N; i++ { - latest.Codec.Decode(data) + testapi.Default.Codec().Decode(data) } } @@ -230,10 +229,10 @@ func BenchmarkDecodeInto(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) - data, _ := latest.Codec.Encode(&pod) + data, _ := testapi.Default.Codec().Encode(&pod) for i := 0; i < b.N; i++ { obj := api.Pod{} - latest.Codec.DecodeInto(data, &obj) + testapi.Default.Codec().DecodeInto(data, &obj) } } @@ -242,7 +241,7 @@ func BenchmarkDecodeJSON(b *testing.B) { pod := api.Pod{} apiObjectFuzzer := apitesting.FuzzerFor(nil, "", rand.NewSource(benchmarkSeed)) apiObjectFuzzer.Fuzz(&pod) - data, _ := latest.Codec.Encode(&pod) + data, _ := testapi.Default.Codec().Encode(&pod) for i := 0; i < b.N; i++ { obj := api.Pod{} json.Unmarshal(data, &obj) diff --git a/pkg/api/testapi/testapi.go b/pkg/api/testapi/testapi.go index 8b0cbe59d20..50e94e69c6c 100644 --- a/pkg/api/testapi/testapi.go +++ b/pkg/api/testapi/testapi.go @@ -22,10 +22,12 @@ import ( "os" "strings" + _ "k8s.io/kubernetes/pkg/api/install" + _ "k8s.io/kubernetes/pkg/apis/experimental/install" + "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" apiutil "k8s.io/kubernetes/pkg/api/util" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/runtime" ) @@ -59,12 +61,12 @@ func init() { // TODO: caesarxuchao: we need a central place to store all available API // groups and their metadata. if _, ok := Groups[""]; !ok { - // TODO: The second latest.Version will be latest.GroupVersion after we + // TODO: The second latest.GroupOrDie("").Version will be latest.GroupVersion after we // have multiple group support - Groups[""] = TestGroup{"", latest.Version, latest.Version} + Groups[""] = TestGroup{"", latest.GroupOrDie("").Version, latest.GroupOrDie("").Version} } if _, ok := Groups["experimental"]; !ok { - Groups["experimental"] = TestGroup{"experimental", explatest.Version, explatest.Version} + Groups["experimental"] = TestGroup{"experimental", latest.GroupOrDie("experimental").Version, latest.GroupOrDie("experimental").Version} } Default = Groups[""] @@ -88,14 +90,14 @@ func (g TestGroup) GroupAndVersion() string { func (g TestGroup) Codec() runtime.Codec { // TODO: caesarxuchao: Restructure the body once we have a central `latest`. if g.Group == "" { - interfaces, err := latest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } return interfaces.Codec } if g.Group == "experimental" { - interfaces, err := explatest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("experimental").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } @@ -109,14 +111,14 @@ func (g TestGroup) Codec() runtime.Codec { func (g TestGroup) Converter() runtime.ObjectConvertor { // TODO: caesarxuchao: Restructure the body once we have a central `latest`. if g.Group == "" { - interfaces, err := latest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } return interfaces.ObjectConvertor } if g.Group == "experimental" { - interfaces, err := explatest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("experimental").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } @@ -131,14 +133,14 @@ func (g TestGroup) Converter() runtime.ObjectConvertor { func (g TestGroup) MetadataAccessor() meta.MetadataAccessor { // TODO: caesarxuchao: Restructure the body once we have a central `latest`. if g.Group == "" { - interfaces, err := latest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } return interfaces.MetadataAccessor } if g.Group == "experimental" { - interfaces, err := explatest.InterfacesFor(g.VersionUnderTest) + interfaces, err := latest.GroupOrDie("experimental").InterfacesFor(g.VersionUnderTest) if err != nil { panic(err) } @@ -202,3 +204,7 @@ func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name stri func (g TestGroup) ResourcePath(resource, namespace, name string) string { return g.ResourcePathWithPrefix("", resource, namespace, name) } + +func (g TestGroup) RESTMapper() meta.RESTMapper { + return latest.GroupOrDie(g.Group).RESTMapper +} diff --git a/pkg/apis/experimental/latest/latest.go b/pkg/apis/experimental/install/install.go similarity index 52% rename from pkg/apis/experimental/latest/latest.go rename to pkg/apis/experimental/install/install.go index 5a231b0b9d4..192d8e94ac2 100644 --- a/pkg/apis/experimental/latest/latest.go +++ b/pkg/apis/experimental/install/install.go @@ -14,40 +14,53 @@ See the License for the specific language governing permissions and limitations under the License. */ -package latest +// Package install installs the experimental API group, making it available as +// an option to all of the API encoding/decoding machinery. +package install import ( "fmt" "strings" + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" + apiutil "k8s.io/kubernetes/pkg/api/util" _ "k8s.io/kubernetes/pkg/apis/experimental" "k8s.io/kubernetes/pkg/apis/experimental/v1" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/sets" ) -var ( - Version string - Versions []string - - accessor = meta.NewAccessor() - Codec runtime.Codec - SelfLinker = runtime.SelfLinker(accessor) - RESTMapper meta.RESTMapper -) - const importPrefix = "k8s.io/kubernetes/pkg/apis/experimental" +var accessor = meta.NewAccessor() + func init() { - Version = registered.RegisteredVersions[0] - Codec = runtime.CodecFor(api.Scheme, Version) - // Put the registered versions in Versions in reverse order. - for i := len(registered.RegisteredVersions) - 1; i >= 0; i-- { - Versions = append(Versions, registered.RegisteredVersions[i]) + groupMeta, err := latest.RegisterGroup("experimental") + if err != nil { + glog.V(4).Infof("%v", err) + return } + registeredGroupVersions := registered.GroupVersionsForGroup("experimental") + groupVersion := registeredGroupVersions[0] + *groupMeta = latest.GroupMeta{ + GroupVersion: groupVersion, + Group: apiutil.GetGroup(groupVersion), + Version: apiutil.GetVersion(groupVersion), + // TODO: caesarxuchao: change it to groupVersion when we support multiple groups + Codec: runtime.CodecFor(api.Scheme, apiutil.GetVersion(groupVersion)), + } + var versions []string + for i := len(registeredGroupVersions) - 1; i >= 0; i-- { + versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) + } + groupMeta.Versions = versions + + groupMeta.SelfLinker = runtime.SelfLinker(accessor) // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope @@ -55,13 +68,14 @@ func init() { ignoredKinds := sets.NewString() - RESTMapper = api.NewDefaultRESTMapper("experimental", Versions, InterfacesFor, importPrefix, ignoredKinds, rootScoped) - api.RegisterRESTMapper(RESTMapper) + groupMeta.RESTMapper = api.NewDefaultRESTMapper("experimental", versions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + api.RegisterRESTMapper(groupMeta.RESTMapper) + groupMeta.InterfacesFor = interfacesFor } // InterfacesFor returns the default Codec and ResourceVersioner for a given version // string, or an error if the version is not known. -func InterfacesFor(version string) (*meta.VersionInterfaces, error) { +func interfacesFor(version string) (*meta.VersionInterfaces, error) { switch version { case "v1": return &meta.VersionInterfaces{ @@ -70,6 +84,7 @@ func InterfacesFor(version string) (*meta.VersionInterfaces, error) { MetadataAccessor: accessor, }, nil default: - return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(Versions, ", ")) + g, _ := latest.Group("experimental") + return nil, fmt.Errorf("unsupported storage version: %s (valid: %s)", version, strings.Join(g.Versions, ", ")) } } diff --git a/pkg/apis/experimental/install/install_test.go b/pkg/apis/experimental/install/install_test.go new file mode 100644 index 00000000000..cbb5132a8c4 --- /dev/null +++ b/pkg/apis/experimental/install/install_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package install + +import ( + "encoding/json" + "testing" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/apis/experimental" +) + +func TestResourceVersioner(t *testing.T) { + daemonSet := experimental.DaemonSet{ObjectMeta: api.ObjectMeta{ResourceVersion: "10"}} + version, err := accessor.ResourceVersion(&daemonSet) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if version != "10" { + t.Errorf("unexpected version %v", version) + } + + daemonSetList := experimental.DaemonSetList{ListMeta: api.ListMeta{ResourceVersion: "10"}} + version, err = accessor.ResourceVersion(&daemonSetList) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if version != "10" { + t.Errorf("unexpected version %v", version) + } +} + +func TestCodec(t *testing.T) { + daemonSet := experimental.DaemonSet{} + // We do want to use package latest rather than testapi here, because we + // want to test if the package install and package latest work as expected. + data, err := latest.GroupOrDie("experimental").Codec.Encode(&daemonSet) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + other := experimental.DaemonSet{} + if err := json.Unmarshal(data, &other); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if other.APIVersion != latest.GroupOrDie("experimental").Version || other.Kind != "DaemonSet" { + t.Errorf("unexpected unmarshalled object %#v", other) + } +} + +func TestInterfacesFor(t *testing.T) { + if _, err := latest.GroupOrDie("experimental").InterfacesFor(""); err == nil { + t.Fatalf("unexpected non-error: %v", err) + } + for i, version := range append([]string{latest.GroupOrDie("experimental").Version}, latest.GroupOrDie("experimental").Versions...) { + if vi, err := latest.GroupOrDie("experimental").InterfacesFor(version); err != nil || vi == nil { + t.Fatalf("%d: unexpected result: %v", i, err) + } + } +} + +func TestRESTMapper(t *testing.T) { + if v, k, err := latest.GroupOrDie("experimental").RESTMapper.VersionAndKindForResource("horizontalpodautoscalers"); err != nil || v != "v1" || k != "HorizontalPodAutoscaler" { + t.Errorf("unexpected version mapping: %s %s %v", v, k, err) + } + + if m, err := latest.GroupOrDie("experimental").RESTMapper.RESTMapping("DaemonSet", ""); err != nil || m.APIVersion != "v1" || m.Resource != "daemonsets" { + t.Errorf("unexpected version mapping: %#v %v", m, err) + } + + for _, version := range latest.GroupOrDie("experimental").Versions { + mapping, err := latest.GroupOrDie("experimental").RESTMapper.RESTMapping("HorizontalPodAutoscaler", version) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if mapping.Resource != "horizontalpodautoscalers" { + t.Errorf("incorrect resource name: %#v", mapping) + } + if mapping.APIVersion != version { + t.Errorf("incorrect version: %v", mapping) + } + + interfaces, _ := latest.GroupOrDie("experimental").InterfacesFor(version) + if mapping.Codec != interfaces.Codec { + t.Errorf("unexpected codec: %#v, expected: %#v", mapping, interfaces) + } + + rc := &experimental.HorizontalPodAutoscaler{ObjectMeta: api.ObjectMeta{Name: "foo"}} + name, err := mapping.MetadataAccessor.Name(rc) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if name != "foo" { + t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor) + } + } +} diff --git a/pkg/apis/experimental/testapi/testapi.go b/pkg/apis/experimental/testapi/testapi.go deleted file mode 100644 index 229a1bf04ac..00000000000 --- a/pkg/apis/experimental/testapi/testapi.go +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testapi - -import ( - "strings" - - "k8s.io/kubernetes/pkg/apis/experimental/latest" -) - -// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name. -// For example, this is of the form: -// /experimental/v1/watch/namespaces/foo/pods/pod0 for v1. -func ResourcePathWithPrefix(prefix, resource, namespace, name string) string { - path := "/experimental/" + latest.Version - if prefix != "" { - path = path + "/" + prefix - } - if namespace != "" { - path = path + "/namespaces/" + namespace - } - // Resource names are lower case. - resource = strings.ToLower(resource) - if resource != "" { - path = path + "/" + resource - } - if name != "" { - path = path + "/" + name - } - return path -} - -// Returns the appropriate path for the given resource, namespace and name. -// For example, this is of the form: -// /experimental/v1/namespaces/foo/pods/pod0 for v1. -func ResourcePath(resource, namespace, name string) string { - return ResourcePathWithPrefix("", resource, namespace, name) -} diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index a15e626d09f..9e1f7bdd66d 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -177,7 +177,7 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter) glog.Errorln(buffer.String()) // TODO: make status unversioned or plumb enough of the request to deduce the requested API version - errorJSON(apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", "", "", "", 0, false), latest.Codec, httpWriter) + errorJSON(apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", "", "", "", 0, false), latest.GroupOrDie("").Codec, httpWriter) } func InstallServiceErrorHandler(container *restful.Container, requestResolver *APIRequestInfoResolver, apiVersions []string) { @@ -188,7 +188,7 @@ func InstallServiceErrorHandler(container *restful.Container, requestResolver *A func serviceErrorHandler(requestResolver *APIRequestInfoResolver, apiVersions []string, serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) { requestInfo, err := requestResolver.GetAPIRequestInfo(request.Request) - codec := latest.Codec + codec := latest.GroupOrDie("").Codec if err == nil && requestInfo.APIVersion != "" { // check if the api version is valid. for _, version := range apiVersions { diff --git a/pkg/apiserver/handlers_test.go b/pkg/apiserver/handlers_test.go index c296a0cdb65..cab2f0c4fb0 100644 --- a/pkg/apiserver/handlers_test.go +++ b/pkg/apiserver/handlers_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/util/sets" ) @@ -246,7 +245,7 @@ func TestGetAPIRequestInfo(t *testing.T) { {"PUT", "/namespaces/other/finalize", "update", "", "other", "finalize", "", "", "", []string{"finalize"}}, } - apiRequestInfoResolver := &APIRequestInfoResolver{sets.NewString("api"), latest.RESTMapper} + apiRequestInfoResolver := &APIRequestInfoResolver{sets.NewString("api"), testapi.Default.RESTMapper()} for _, successCase := range successCases { req, _ := http.NewRequest(successCase.method, successCase.url, nil) diff --git a/pkg/client/unversioned/clientcmd/client_config_test.go b/pkg/client/unversioned/clientcmd/client_config_test.go index 4bf6eebd696..cb6f861d1cd 100644 --- a/pkg/client/unversioned/clientcmd/client_config_test.go +++ b/pkg/client/unversioned/clientcmd/client_config_test.go @@ -20,7 +20,7 @@ import ( "reflect" "testing" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" ) @@ -34,7 +34,7 @@ func createValidTestConfig() *clientcmdapi.Config { config := clientcmdapi.NewConfig() config.Clusters["clean"] = &clientcmdapi.Cluster{ Server: server, - APIVersion: latest.Version, + APIVersion: testapi.Default.Version(), } config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ Token: token, @@ -89,7 +89,7 @@ func TestCertificateData(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["clean"] = &clientcmdapi.Cluster{ Server: "https://localhost:8443", - APIVersion: latest.Version, + APIVersion: testapi.Default.Version(), CertificateAuthorityData: caData, } config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ @@ -122,7 +122,7 @@ func TestBasicAuthData(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["clean"] = &clientcmdapi.Cluster{ Server: "https://localhost:8443", - APIVersion: latest.Version, + APIVersion: testapi.Default.Version(), } config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ Username: username, diff --git a/pkg/client/unversioned/experimental.go b/pkg/client/unversioned/experimental.go index 00f33daa1c0..68b8ca90b80 100644 --- a/pkg/client/unversioned/experimental.go +++ b/pkg/client/unversioned/experimental.go @@ -22,7 +22,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" + "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/version" ) @@ -119,17 +119,23 @@ func NewExperimentalOrDie(c *Config) *ExperimentalClient { } func setExperimentalDefaults(config *Config) error { + // if experimental group is not registered, return an error + g, err := latest.Group("experimental") + if err != nil { + return err + } config.Prefix = "/experimental" if config.UserAgent == "" { config.UserAgent = DefaultKubernetesUserAgent() } if config.Version == "" { - config.Version = explatest.Version + config.Version = g.Version } - versionInterfaces, err := explatest.InterfacesFor(config.Version) + + versionInterfaces, err := g.InterfacesFor(config.Version) if err != nil { return fmt.Errorf("Experimental API version '%s' is not recognized (valid values: %s)", - config.Version, strings.Join(explatest.Versions, ", ")) + config.Version, strings.Join(latest.GroupOrDie("experimental").Versions, ", ")) } if config.Codec == nil { config.Codec = versionInterfaces.Codec diff --git a/pkg/client/unversioned/fake.go b/pkg/client/unversioned/fake.go deleted file mode 100644 index a52cdb09727..00000000000 --- a/pkg/client/unversioned/fake.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package unversioned - -import ( - "net/http" - "net/url" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" -) - -type HTTPClientFunc func(*http.Request) (*http.Response, error) - -func (f HTTPClientFunc) Do(req *http.Request) (*http.Response, error) { - return f(req) -} - -// FakeRESTClient provides a fake RESTClient interface. -type FakeRESTClient struct { - Client HTTPClient - Codec runtime.Codec - Req *http.Request - Resp *http.Response - Err error -} - -func (c *FakeRESTClient) Get() *Request { - return NewRequest(c, "GET", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) -} - -func (c *FakeRESTClient) Put() *Request { - return NewRequest(c, "PUT", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) -} - -func (c *FakeRESTClient) Patch(_ api.PatchType) *Request { - return NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) -} - -func (c *FakeRESTClient) Post() *Request { - return NewRequest(c, "POST", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) -} - -func (c *FakeRESTClient) Delete() *Request { - return NewRequest(c, "DELETE", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) -} - -func (c *FakeRESTClient) Do(req *http.Request) (*http.Response, error) { - c.Req = req - if c.Client != HTTPClient(nil) { - return c.Client.Do(req) - } - return c.Resp, c.Err -} diff --git a/pkg/client/unversioned/fake/fake.go b/pkg/client/unversioned/fake/fake.go new file mode 100644 index 00000000000..8e77910a649 --- /dev/null +++ b/pkg/client/unversioned/fake/fake.go @@ -0,0 +1,72 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This is made a separate package and should only be imported by tests, because +// it imports testapi +package fake + +import ( + "net/http" + "net/url" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/runtime" +) + +type HTTPClientFunc func(*http.Request) (*http.Response, error) + +func (f HTTPClientFunc) Do(req *http.Request) (*http.Response, error) { + return f(req) +} + +// RESTClient provides a fake RESTClient interface. +type RESTClient struct { + Client unversioned.HTTPClient + Codec runtime.Codec + Req *http.Request + Resp *http.Response + Err error +} + +func (c *RESTClient) Get() *unversioned.Request { + return unversioned.NewRequest(c, "GET", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) +} + +func (c *RESTClient) Put() *unversioned.Request { + return unversioned.NewRequest(c, "PUT", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) +} + +func (c *RESTClient) Patch(_ api.PatchType) *unversioned.Request { + return unversioned.NewRequest(c, "PATCH", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) +} + +func (c *RESTClient) Post() *unversioned.Request { + return unversioned.NewRequest(c, "POST", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) +} + +func (c *RESTClient) Delete() *unversioned.Request { + return unversioned.NewRequest(c, "DELETE", &url.URL{Host: "localhost"}, testapi.Default.Version(), c.Codec) +} + +func (c *RESTClient) Do(req *http.Request) (*http.Response, error) { + c.Req = req + if c.Client != unversioned.HTTPClient(nil) { + return c.Client.Do(req) + } + return c.Resp, c.Err +} diff --git a/pkg/client/unversioned/helper.go b/pkg/client/unversioned/helper.go index 081e5f9214a..c762abbc6fe 100644 --- a/pkg/client/unversioned/helper.go +++ b/pkg/client/unversioned/helper.go @@ -140,6 +140,10 @@ func New(c *Config) (*Client, error) { if err != nil { return nil, err } + + if _, err := latest.Group("experimental"); err != nil { + return &Client{RESTClient: client, ExperimentalClient: nil}, nil + } experimentalConfig := *c experimentalClient, err := NewExperimental(&experimentalConfig) if err != nil { @@ -290,9 +294,9 @@ func SetKubernetesDefaults(config *Config) error { config.Version = defaultVersionFor(config) } version := config.Version - versionInterfaces, err := latest.InterfacesFor(version) + versionInterfaces, err := latest.GroupOrDie("").InterfacesFor(version) if err != nil { - return fmt.Errorf("API version '%s' is not recognized (valid values: %s)", version, strings.Join(latest.Versions, ", ")) + return fmt.Errorf("API version '%s' is not recognized (valid values: %s)", version, strings.Join(latest.GroupOrDie("").Versions, ", ")) } if config.Codec == nil { config.Codec = versionInterfaces.Codec @@ -543,7 +547,7 @@ func defaultVersionFor(config *Config) string { if version == "" { // Clients default to the preferred code API version // TODO: implement version negotiation (highest version supported by server) - version = latest.Version + version = latest.GroupOrDie("").Version } return version } diff --git a/pkg/client/unversioned/helper_blackbox_test.go b/pkg/client/unversioned/helper_blackbox_test.go new file mode 100644 index 00000000000..5a1309e869a --- /dev/null +++ b/pkg/client/unversioned/helper_blackbox_test.go @@ -0,0 +1,112 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package unversioned_test + +import ( + "bytes" + "encoding/json" + "io" + "io/ioutil" + "net/http" + "testing" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" +) + +func objBody(object interface{}) io.ReadCloser { + output, err := json.MarshalIndent(object, "", "") + if err != nil { + panic(err) + } + return ioutil.NopCloser(bytes.NewReader([]byte(output))) +} + +func TestNegotiateVersion(t *testing.T) { + tests := []struct { + name, version, expectedVersion string + serverVersions []string + clientVersions []string + config *unversioned.Config + expectErr bool + }{ + { + name: "server supports client default", + version: "version1", + config: &unversioned.Config{}, + serverVersions: []string{"version1", testapi.Default.Version()}, + clientVersions: []string{"version1", testapi.Default.Version()}, + expectedVersion: "version1", + expectErr: false, + }, + { + name: "server falls back to client supported", + version: testapi.Default.Version(), + config: &unversioned.Config{}, + serverVersions: []string{"version1"}, + clientVersions: []string{"version1", testapi.Default.Version()}, + expectedVersion: "version1", + expectErr: false, + }, + { + name: "explicit version supported", + version: "", + config: &unversioned.Config{Version: testapi.Default.Version()}, + serverVersions: []string{"version1", testapi.Default.Version()}, + clientVersions: []string{"version1", testapi.Default.Version()}, + expectedVersion: testapi.Default.Version(), + expectErr: false, + }, + { + name: "explicit version not supported", + version: "", + config: &unversioned.Config{Version: testapi.Default.Version()}, + serverVersions: []string{"version1"}, + clientVersions: []string{"version1", testapi.Default.Version()}, + expectedVersion: "", + expectErr: true, + }, + } + codec := testapi.Default.Codec() + + for _, test := range tests { + fakeClient := &fake.RESTClient{ + Codec: codec, + Resp: &http.Response{ + StatusCode: 200, + Body: objBody(&api.APIVersions{Versions: test.serverVersions}), + }, + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{StatusCode: 200, Body: objBody(&api.APIVersions{Versions: test.serverVersions})}, nil + }), + } + c := unversioned.NewOrDie(test.config) + c.Client = fakeClient.Client + response, err := unversioned.NegotiateVersion(c, test.config, test.version, test.clientVersions) + if err == nil && test.expectErr { + t.Errorf("expected error, got nil for [%s].", test.name) + } + if err != nil && !test.expectErr { + t.Errorf("unexpected error for [%s]: %v.", test.name, err) + } + if response != test.expectedVersion { + t.Errorf("expected version %s, got %s.", test.expectedVersion, response) + } + } +} diff --git a/pkg/client/unversioned/helper_test.go b/pkg/client/unversioned/helper_test.go index a81c5d9a612..21c70a890cb 100644 --- a/pkg/client/unversioned/helper_test.go +++ b/pkg/client/unversioned/helper_test.go @@ -17,17 +17,11 @@ limitations under the License. package unversioned import ( - "bytes" - "encoding/json" - "io" - "io/ioutil" "net/http" "reflect" "strings" "testing" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" ) @@ -222,7 +216,7 @@ func TestTLSTransportCache(t *testing.T) { "host": {Insecure: true, Host: "foo"}, "prefix": {Insecure: true, Prefix: "foo"}, "version": {Insecure: true, Version: "foo"}, - "codec": {Insecure: true, Codec: latest.Codec}, + "codec": {Insecure: true, Codec: testapi.Default.Codec()}, "basic": {Insecure: true, Username: "bob", Password: "password"}, "bearer": {Insecure: true, BearerToken: "token"}, "user agent": {Insecure: true, UserAgent: "useragent"}, @@ -336,8 +330,8 @@ func TestSetKubernetesDefaults(t *testing.T) { Config{}, Config{ Prefix: "/api", - Version: latest.Version, - Codec: latest.Codec, + Version: testapi.Default.Version(), + Codec: testapi.Default.Codec(), QPS: 5, Burst: 10, }, @@ -380,84 +374,3 @@ func TestSetKubernetesDefaultsUserAgent(t *testing.T) { t.Errorf("no user agent set: %#v", config) } } - -func objBody(object interface{}) io.ReadCloser { - output, err := json.MarshalIndent(object, "", "") - if err != nil { - panic(err) - } - return ioutil.NopCloser(bytes.NewReader([]byte(output))) -} - -func TestNegotiateVersion(t *testing.T) { - tests := []struct { - name, version, expectedVersion string - serverVersions []string - clientVersions []string - config *Config - expectErr bool - }{ - { - name: "server supports client default", - version: "version1", - config: &Config{}, - serverVersions: []string{"version1", testapi.Default.Version()}, - clientVersions: []string{"version1", testapi.Default.Version()}, - expectedVersion: "version1", - expectErr: false, - }, - { - name: "server falls back to client supported", - version: testapi.Default.Version(), - config: &Config{}, - serverVersions: []string{"version1"}, - clientVersions: []string{"version1", testapi.Default.Version()}, - expectedVersion: "version1", - expectErr: false, - }, - { - name: "explicit version supported", - version: "", - config: &Config{Version: testapi.Default.Version()}, - serverVersions: []string{"version1", testapi.Default.Version()}, - clientVersions: []string{"version1", testapi.Default.Version()}, - expectedVersion: testapi.Default.Version(), - expectErr: false, - }, - { - name: "explicit version not supported", - version: "", - config: &Config{Version: testapi.Default.Version()}, - serverVersions: []string{"version1"}, - clientVersions: []string{"version1", testapi.Default.Version()}, - expectedVersion: "", - expectErr: true, - }, - } - codec := testapi.Default.Codec() - - for _, test := range tests { - fakeClient := &FakeRESTClient{ - Codec: codec, - Resp: &http.Response{ - StatusCode: 200, - Body: objBody(&api.APIVersions{Versions: test.serverVersions}), - }, - Client: HTTPClientFunc(func(req *http.Request) (*http.Response, error) { - return &http.Response{StatusCode: 200, Body: objBody(&api.APIVersions{Versions: test.serverVersions})}, nil - }), - } - c := NewOrDie(test.config) - c.Client = fakeClient.Client - response, err := NegotiateVersion(c, test.config, test.version, test.clientVersions) - if err == nil && test.expectErr { - t.Errorf("expected error, got nil for [%s].", test.name) - } - if err != nil && !test.expectErr { - t.Errorf("unexpected error for [%s]: %v.", test.name, err) - } - if response != test.expectedVersion { - t.Errorf("expected version %s, got %s.", test.expectedVersion, response) - } - } -} diff --git a/pkg/client/unversioned/import_known_versions.go b/pkg/client/unversioned/import_known_versions.go new file mode 100644 index 00000000000..ded32975213 --- /dev/null +++ b/pkg/client/unversioned/import_known_versions.go @@ -0,0 +1,23 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package unversioned + +// These imports are the API groups the client will support. +import ( + _ "k8s.io/kubernetes/pkg/api/install" + _ "k8s.io/kubernetes/pkg/apis/experimental/install" +) diff --git a/pkg/client/unversioned/request_test.go b/pkg/client/unversioned/request_test.go index 7fbe26c5556..40681d7aaa4 100644 --- a/pkg/client/unversioned/request_test.go +++ b/pkg/client/unversioned/request_test.go @@ -34,7 +34,6 @@ import ( "k8s.io/kubernetes/pkg/api" apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" @@ -193,7 +192,7 @@ func TestRequestBody(t *testing.T) { } // test unencodable api object - r = (&Request{codec: latest.Codec}).Body(&NotAnAPIObject{}) + r = (&Request{codec: testapi.Default.Codec()}).Body(&NotAnAPIObject{}) if r.err == nil || r.body != nil { t.Errorf("should have set err and left body nil: %#v", r) } @@ -356,7 +355,7 @@ func TestTransformUnstructuredError(t *testing.T) { for _, testCase := range testCases { r := &Request{ - codec: latest.Codec, + codec: testapi.Default.Codec(), resourceName: testCase.Name, resource: testCase.Resource, } @@ -543,7 +542,7 @@ func TestRequestStream(t *testing.T) { })))), }, nil }), - codec: latest.Codec, + codec: testapi.Default.Codec(), baseURL: &url.URL{}, }, Err: true, @@ -1185,7 +1184,7 @@ func TestWatch(t *testing.T) { w.WriteHeader(http.StatusOK) flusher.Flush() - encoder := watchjson.NewEncoder(w, latest.Codec) + encoder := watchjson.NewEncoder(w, testapi.Default.Codec()) for _, item := range table { if err := encoder.Encode(&watch.Event{Type: item.t, Object: item.obj}); err != nil { panic(err) diff --git a/pkg/client/unversioned/restclient_test.go b/pkg/client/unversioned/restclient_test.go index 942ccf5570e..817ad0c9a07 100644 --- a/pkg/client/unversioned/restclient_test.go +++ b/pkg/client/unversioned/restclient_test.go @@ -23,7 +23,6 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" @@ -109,7 +108,7 @@ func TestValidatesHostParameter(t *testing.T) { func TestDoRequestBearer(t *testing.T) { status := &api.Status{Status: api.StatusFailure} - expectedBody, _ := latest.Codec.Encode(status) + expectedBody, _ := testapi.Default.Codec().Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 400, ResponseBody: string(expectedBody), @@ -138,7 +137,7 @@ func TestDoRequestBearer(t *testing.T) { func TestDoRequestWithoutPassword(t *testing.T) { status := &api.Status{Status: api.StatusFailure} - expectedBody, _ := latest.Codec.Encode(status) + expectedBody, _ := testapi.Default.Codec().Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 400, ResponseBody: string(expectedBody), @@ -177,7 +176,7 @@ func TestDoRequestWithoutPassword(t *testing.T) { func TestDoRequestSuccess(t *testing.T) { status := &api.Status{Status: api.StatusSuccess} - expectedBody, _ := latest.Codec.Encode(status) + expectedBody, _ := testapi.Default.Codec().Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), @@ -202,7 +201,7 @@ func TestDoRequestSuccess(t *testing.T) { if fakeHandler.RequestReceived.Header["Authorization"] == nil { t.Errorf("Request is missing authorization header: %#v", fakeHandler.RequestReceived) } - statusOut, err := latest.Codec.Decode(body) + statusOut, err := testapi.Default.Codec().Decode(body) if err != nil { t.Errorf("Unexpected error %#v", err) } @@ -220,7 +219,7 @@ func TestDoRequestFailed(t *testing.T) { Message: " \"\" not found", Details: &api.StatusDetails{}, } - expectedBody, _ := latest.Codec.Encode(status) + expectedBody, _ := testapi.Default.Codec().Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 404, ResponseBody: string(expectedBody), @@ -252,7 +251,7 @@ func TestDoRequestFailed(t *testing.T) { func TestDoRequestCreated(t *testing.T) { status := &api.Status{Status: api.StatusSuccess} - expectedBody, _ := latest.Codec.Encode(status) + expectedBody, _ := testapi.Default.Codec().Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 201, ResponseBody: string(expectedBody), @@ -278,7 +277,7 @@ func TestDoRequestCreated(t *testing.T) { if !created { t.Errorf("Expected object to be created") } - statusOut, err := latest.Codec.Decode(body) + statusOut, err := testapi.Default.Codec().Decode(body) if err != nil { t.Errorf("Unexpected error %#v", err) } diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index 6bb59bfc9e1..7229227f248 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -39,7 +39,7 @@ func NewSimpleFake(objects ...runtime.Object) *Fake { } fakeClient := &Fake{} - fakeClient.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) + fakeClient.AddReactor("*", "*", ObjectReaction(o, latest.GroupOrDie("").RESTMapper)) return fakeClient } diff --git a/pkg/client/unversioned/testclient/testclient_test.go b/pkg/client/unversioned/testclient/testclient_test.go index a8e1f85381d..257d7fb8c9f 100644 --- a/pkg/client/unversioned/testclient/testclient_test.go +++ b/pkg/client/unversioned/testclient/testclient_test.go @@ -21,7 +21,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" ) @@ -32,7 +32,7 @@ func TestNewClient(t *testing.T) { t.Fatal(err) } client := &Fake{} - client.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", ObjectReaction(o, testapi.Default.RESTMapper())) list, err := client.Services("test").List(labels.Everything()) if err != nil { t.Fatal(err) @@ -63,7 +63,7 @@ func TestErrors(t *testing.T) { }, }) client := &Fake{} - client.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", ObjectReaction(o, testapi.Default.RESTMapper())) _, err := client.Services("test").List(labels.Everything()) if !errors.IsNotFound(err) { t.Fatalf("unexpected error: %v", err) diff --git a/pkg/client/unversioned/transport_test.go b/pkg/client/unversioned/transport_test.go index 3b8d1bed0a2..baa09c3e04b 100644 --- a/pkg/client/unversioned/transport_test.go +++ b/pkg/client/unversioned/transport_test.go @@ -21,7 +21,7 @@ import ( "net/http" "testing" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" ) func TestUnsecuredTLSTransport(t *testing.T) { @@ -109,7 +109,7 @@ func TestTLSConfigKey(t *testing.T) { "host": {Host: "foo"}, "prefix": {Prefix: "foo"}, "version": {Version: "foo"}, - "codec": {Codec: latest.Codec}, + "codec": {Codec: testapi.Default.Codec()}, "basic": {Username: "bob", Password: "password"}, "bearer": {BearerToken: "token"}, "user agent": {UserAgent: "useragent"}, diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index d49d720981b..94dfe3a550d 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -244,7 +244,7 @@ func getReplicaAnnotationSet(template *api.PodTemplateSpec, object runtime.Objec if err != nil { return desiredAnnotations, fmt.Errorf("unable to get controller reference: %v", err) } - createdByRefJson, err := latest.Codec.Encode(&api.SerializedReference{ + createdByRefJson, err := latest.GroupOrDie("").Codec.Encode(&api.SerializedReference{ Reference: *createdByRef, }) if err != nil { diff --git a/pkg/kubectl/cmd/annotate_test.go b/pkg/kubectl/cmd/annotate_test.go index ea45b030d06..d518846bc3f 100644 --- a/pkg/kubectl/cmd/annotate_test.go +++ b/pkg/kubectl/cmd/annotate_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" ) @@ -420,9 +421,9 @@ func TestAnnotateObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.Method { case "GET": switch req.URL.Path { @@ -467,9 +468,9 @@ func TestAnnotateObjectFromFile(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.Method { case "GET": switch req.URL.Path { @@ -515,9 +516,9 @@ func TestAnnotateMultipleObjects(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.Method { case "GET": switch req.URL.Path { diff --git a/pkg/kubectl/cmd/attach_test.go b/pkg/kubectl/cmd/attach_test.go index b7d336cd06f..6c66d1946d5 100644 --- a/pkg/kubectl/cmd/attach_test.go +++ b/pkg/kubectl/cmd/attach_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) type fakeRemoteAttach struct { @@ -76,9 +77,9 @@ func TestPodAndContainerAttach(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return nil, nil }), + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return nil, nil }), } tf.Namespace = "test" tf.ClientConfig = &client.Config{} @@ -129,9 +130,9 @@ func TestAttach(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.podPath && m == "GET": body := objBody(codec, test.pod) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index bd7c08b4550..fa01cb56002 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -28,11 +28,11 @@ import ( "time" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/validation" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" @@ -175,7 +175,7 @@ func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { func NewMixedFactory(apiClient resource.RESTClient) (*cmdutil.Factory, *testFactory, runtime.Codec) { f, t, c := NewTestFactory() f.Object = func() (meta.RESTMapper, runtime.ObjectTyper) { - return meta.MultiRESTMapper{t.Mapper, latest.RESTMapper}, runtime.MultiObjectTyper{t.Typer, api.Scheme} + return meta.MultiRESTMapper{t.Mapper, testapi.Default.RESTMapper()}, runtime.MultiObjectTyper{t.Typer, api.Scheme} } f.RESTClient = func(m *meta.RESTMapping) (resource.RESTClient, error) { if m.ObjectConvertor == api.Scheme { @@ -197,11 +197,11 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { } return &cmdutil.Factory{ Object: func() (meta.RESTMapper, runtime.ObjectTyper) { - return latest.RESTMapper, api.Scheme + return testapi.Default.RESTMapper(), api.Scheme }, Client: func() (*client.Client, error) { // Swap out the HTTP client out of the client with the fake's version. - fakeClient := t.Client.(*client.FakeRESTClient) + fakeClient := t.Client.(*fake.RESTClient) c := client.NewOrDie(t.ClientConfig) c.Client = fakeClient.Client return c, t.Err @@ -262,7 +262,7 @@ func stringBody(body string) io.ReadCloser { func ExamplePrintReplicationControllerWithNamespace() { f, tf, codec := NewAPIFactory() tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, []string{}) - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Client: nil, } @@ -304,7 +304,7 @@ func ExamplePrintReplicationControllerWithNamespace() { func ExamplePrintPodWithWideFormat() { f, tf, codec := NewAPIFactory() tf.Printer = kubectl.NewHumanReadablePrinter(false, false, true, false, []string{}) - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Client: nil, } @@ -431,7 +431,7 @@ func newAllPhasePodList() *api.PodList { func ExamplePrintPodHideTerminated() { f, tf, codec := NewAPIFactory() tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, []string{}) - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Client: nil, } @@ -451,7 +451,7 @@ func ExamplePrintPodHideTerminated() { func ExamplePrintPodShowAll() { f, tf, codec := NewAPIFactory() tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, true, []string{}) - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Client: nil, } @@ -473,7 +473,7 @@ func ExamplePrintPodShowAll() { func ExamplePrintServiceWithNamespacesAndLabels() { f, tf, codec := NewAPIFactory() tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, []string{"l1"}) - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Client: nil, } diff --git a/pkg/kubectl/cmd/create_test.go b/pkg/kubectl/cmd/create_test.go index aed138bd9f2..d1f2cfe0f9b 100644 --- a/pkg/kubectl/cmd/create_test.go +++ b/pkg/kubectl/cmd/create_test.go @@ -22,7 +22,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" ) @@ -42,9 +42,9 @@ func TestCreateObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers" && m == "POST": return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil @@ -73,9 +73,9 @@ func TestCreateMultipleObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services" && m == "POST": return &http.Response{StatusCode: 201, Body: objBody(codec, &svc.Items[0])}, nil @@ -108,9 +108,9 @@ func TestCreateDirectory(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services" && m == "POST": return &http.Response{StatusCode: 201, Body: objBody(codec, &svc.Items[0])}, nil diff --git a/pkg/kubectl/cmd/delete_test.go b/pkg/kubectl/cmd/delete_test.go index 8be48805d0a..4995bce2ef7 100644 --- a/pkg/kubectl/cmd/delete_test.go +++ b/pkg/kubectl/cmd/delete_test.go @@ -25,7 +25,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/testapi" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) func TestDeleteObjectByTuple(t *testing.T) { @@ -33,9 +33,9 @@ func TestDeleteObjectByTuple(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -65,9 +65,9 @@ func TestDeleteNamedObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -97,9 +97,9 @@ func TestDeleteObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -127,9 +127,9 @@ func TestDeleteObject(t *testing.T) { func TestDeleteObjectNotFound(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 404, Body: stringBody("")}, nil @@ -157,9 +157,9 @@ func TestDeleteObjectNotFound(t *testing.T) { func TestDeleteObjectIgnoreNotFound(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 404, Body: stringBody("")}, nil @@ -194,9 +194,9 @@ func TestDeleteAllNotFound(t *testing.T) { notFoundError := &errors.NewNotFound("Service", "foo").(*errors.StatusError).ErrStatus tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services" && m == "GET": return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil @@ -236,9 +236,9 @@ func TestDeleteAllIgnoreNotFound(t *testing.T) { notFoundError := &errors.NewNotFound("Service", "foo").(*errors.StatusError).ErrStatus tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services" && m == "GET": return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil @@ -271,9 +271,9 @@ func TestDeleteMultipleObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -305,9 +305,9 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 404, Body: stringBody("")}, nil @@ -342,9 +342,9 @@ func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { _, svc, rc := testData() f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/baz" && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -378,9 +378,9 @@ func TestDeleteDirectory(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case strings.HasPrefix(p, "/namespaces/test/services/") && m == "DELETE": return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil @@ -411,9 +411,9 @@ func TestDeleteMultipleSelector(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/pods" && m == "GET": if req.URL.Query().Get(api.LabelSelectorQueryParam(testapi.Default.Version())) != "a=b" { diff --git a/pkg/kubectl/cmd/describe_test.go b/pkg/kubectl/cmd/describe_test.go index 2637ba0f044..4c473eb9e82 100644 --- a/pkg/kubectl/cmd/describe_test.go +++ b/pkg/kubectl/cmd/describe_test.go @@ -22,7 +22,7 @@ import ( "net/http" "testing" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. @@ -30,7 +30,7 @@ func TestDescribeUnknownSchemaObject(t *testing.T) { d := &testDescriber{Output: "test output"} f, tf, codec := NewTestFactory() tf.Describer = d - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, } @@ -54,9 +54,9 @@ func TestDescribeObject(t *testing.T) { f, tf, codec := NewAPIFactory() d := &testDescriber{Output: "test output"} tf.Describer = d - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET": return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -87,7 +87,7 @@ func TestDescribeListObjects(t *testing.T) { f, tf, codec := NewAPIFactory() d := &testDescriber{Output: "test output"} tf.Describer = d - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, } diff --git a/pkg/kubectl/cmd/exec_test.go b/pkg/kubectl/cmd/exec_test.go index 34b147718a8..b9a5ace0035 100644 --- a/pkg/kubectl/cmd/exec_test.go +++ b/pkg/kubectl/cmd/exec_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) type fakeRemoteExecutor struct { @@ -97,9 +98,9 @@ func TestPodAndContainer(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return nil, nil }), + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return nil, nil }), } tf.Namespace = "test" tf.ClientConfig = &client.Config{} @@ -153,9 +154,9 @@ func TestExec(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.podPath && m == "GET": body := objBody(codec, test.pod) diff --git a/pkg/kubectl/cmd/expose_test.go b/pkg/kubectl/cmd/expose_test.go index bb4a14ba273..cc5755ce06a 100644 --- a/pkg/kubectl/cmd/expose_test.go +++ b/pkg/kubectl/cmd/expose_test.go @@ -23,7 +23,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" ) @@ -213,9 +213,9 @@ func TestRunExposeService(t *testing.T) { for _, test := range tests { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.calls[m] && m == "GET": return &http.Response{StatusCode: test.status, Body: objBody(codec, test.input)}, nil @@ -287,9 +287,9 @@ func TestRunExposeServiceFromFile(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.calls[m] && m == "GET": return &http.Response{StatusCode: test.status, Body: objBody(codec, test.input)}, nil diff --git a/pkg/kubectl/cmd/get_test.go b/pkg/kubectl/cmd/get_test.go index b15d6ec67e3..c0f613f5ede 100644 --- a/pkg/kubectl/cmd/get_test.go +++ b/pkg/kubectl/cmd/get_test.go @@ -28,9 +28,9 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/watch" @@ -123,12 +123,12 @@ func testComponentStatusData() *api.ComponentStatusList { func TestGetUnknownSchemaObject(t *testing.T) { f, tf, codec := NewTestFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, } tf.Namespace = "test" - tf.ClientConfig = &client.Config{Version: latest.Version} + tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} buf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf) @@ -153,9 +153,9 @@ func TestGetUnknownSchemaObject(t *testing.T) { // // The expected behavior of the `kubectl get` command is: // 1. objects using unrecognized schemes will always be returned using that scheme/version, "unlikelyversion" in this test; -// 2. if the specified output-version is a recognized, valid Scheme, then the list should use that scheme, and otherwise it will default to the client version, latest.Version in this test; +// 2. if the specified output-version is a recognized, valid Scheme, then the list should use that scheme, and otherwise it will default to the client version, testapi.Default.Version() in this test; // 3a. if the specified output-version is a recognized, valid Scheme, in which the requested object (replicationcontroller) can be represented, then the object should be returned using that version; -// 3b. otherwise if the specified output-version is unrecognized, but the requested object (replicationcontroller) is recognized by the client's codec, then it will be converted to the client version, latest.Version in this test. +// 3b. otherwise if the specified output-version is unrecognized, but the requested object (replicationcontroller) is recognized by the client's codec, then it will be converted to the client version, testapi.Default.Version() in this test. func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { testCases := map[string]struct { outputVersion string @@ -164,16 +164,16 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { rcVersion string }{ "handles specific version": { - outputVersion: latest.Version, - listVersion: latest.Version, + outputVersion: testapi.Default.Version(), + listVersion: testapi.Default.Version(), testtypeVersion: "unlikelyversion", - rcVersion: latest.Version, + rcVersion: testapi.Default.Version(), }, "handles second specific version": { outputVersion: "unlikelyversion", - listVersion: latest.Version, + listVersion: testapi.Default.Version(), testtypeVersion: "unlikelyversion", - rcVersion: latest.Version, // see expected behavior 3b + rcVersion: testapi.Default.Version(), // see expected behavior 3b }, "handles common version": { outputVersion: testapi.Default.Version(), @@ -184,23 +184,23 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { } for k, test := range testCases { apiCodec := runtime.CodecFor(api.Scheme, testapi.Default.Version()) - regularClient := &client.FakeRESTClient{ + regularClient := &fake.RESTClient{ Codec: apiCodec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{StatusCode: 200, Body: objBody(apiCodec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})}, nil }), } f, tf, codec := NewMixedFactory(regularClient) tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, nil }), } tf.Namespace = "test" - tf.ClientConfig = &client.Config{Version: latest.Version} + tf.ClientConfig = &client.Config{Version: testapi.Default.Version()} buf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf) cmd.SetOutput(buf) @@ -232,11 +232,11 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { // Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. func TestGetSchemaObject(t *testing.T) { f, tf, _ := NewTestFactory() - tf.Mapper = latest.RESTMapper + tf.Mapper = testapi.Default.RESTMapper() tf.Typer = api.Scheme - codec := latest.Codec + codec := testapi.Default.Codec() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})}, } @@ -257,7 +257,7 @@ func TestGetObjects(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, } @@ -283,7 +283,7 @@ func TestGetObjectsIdentifiedByFile(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, } @@ -310,7 +310,7 @@ func TestGetListObjects(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, } @@ -336,7 +336,7 @@ func TestGetAllListObjects(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, } @@ -363,7 +363,7 @@ func TestGetListComponentStatus(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, Resp: &http.Response{StatusCode: 200, Body: objBody(codec, statuses)}, } @@ -389,9 +389,9 @@ func TestGetMultipleTypeObjects(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil @@ -425,9 +425,9 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil @@ -485,9 +485,9 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { if req.URL.Query().Get(api.LabelSelectorQueryParam(testapi.Default.Version())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } @@ -534,9 +534,9 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/nodes/foo": return &http.Response{StatusCode: 200, Body: objBody(codec, node)}, nil @@ -621,9 +621,9 @@ func TestWatchSelector(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { if req.URL.Query().Get(api.LabelSelectorQueryParam(testapi.Default.Version())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } @@ -663,9 +663,9 @@ func TestWatchResource(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods/foo": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil @@ -701,9 +701,9 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods/cassandra": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil @@ -740,9 +740,9 @@ func TestWatchOnlyResource(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods/foo": return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil diff --git a/pkg/kubectl/cmd/label_test.go b/pkg/kubectl/cmd/label_test.go index 814aa605239..8e25cfeb51d 100644 --- a/pkg/kubectl/cmd/label_test.go +++ b/pkg/kubectl/cmd/label_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" ) @@ -326,9 +327,9 @@ func TestLabelErrors(t *testing.T) { func TestLabelForResourceFromFile(t *testing.T) { pods, _, _ := testData() f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.Method { case "GET": switch req.URL.Path { @@ -373,9 +374,9 @@ func TestLabelForResourceFromFile(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) { pods, _, _ := testData() f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.Method { case "GET": switch req.URL.Path { diff --git a/pkg/kubectl/cmd/log_test.go b/pkg/kubectl/cmd/log_test.go index 58ba2eecf23..16171223cc3 100644 --- a/pkg/kubectl/cmd/log_test.go +++ b/pkg/kubectl/cmd/log_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) func TestSelectContainer(t *testing.T) { @@ -165,9 +166,9 @@ func TestLog(t *testing.T) { for _, test := range tests { logContent := "test log content" f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.podPath && m == "GET": body := objBody(codec, test.pod) diff --git a/pkg/kubectl/cmd/patch_test.go b/pkg/kubectl/cmd/patch_test.go index 21efbb443f5..2819bb372d2 100644 --- a/pkg/kubectl/cmd/patch_test.go +++ b/pkg/kubectl/cmd/patch_test.go @@ -21,7 +21,7 @@ import ( "net/http" "testing" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) func TestPatchObject(t *testing.T) { @@ -29,9 +29,9 @@ func TestPatchObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil @@ -61,9 +61,9 @@ func TestPatchObjectFromFile(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil diff --git a/pkg/kubectl/cmd/portforward_test.go b/pkg/kubectl/cmd/portforward_test.go index 05923191081..231f123f37e 100644 --- a/pkg/kubectl/cmd/portforward_test.go +++ b/pkg/kubectl/cmd/portforward_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) type fakePortForwarder struct { @@ -64,9 +65,9 @@ func TestPortForward(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.podPath && m == "GET": body := objBody(codec, test.pod) @@ -126,9 +127,9 @@ func TestPortForwardWithPFlag(t *testing.T) { } for _, test := range tests { f, tf, codec := NewAPIFactory() - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == test.podPath && m == "GET": body := objBody(codec, test.pod) diff --git a/pkg/kubectl/cmd/replace_test.go b/pkg/kubectl/cmd/replace_test.go index 03c1e27e42f..6b7e98dcf92 100644 --- a/pkg/kubectl/cmd/replace_test.go +++ b/pkg/kubectl/cmd/replace_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" ) func TestReplaceObject(t *testing.T) { @@ -30,9 +30,9 @@ func TestReplaceObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == "GET" || m == "PUT" || m == "DELETE"): return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -73,9 +73,9 @@ func TestReplaceMultipleObject(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == "GET" || m == "PUT" || m == "DELETE"): return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil @@ -120,9 +120,9 @@ func TestReplaceDirectory(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case strings.HasPrefix(p, "/namespaces/test/services/") && (m == "GET" || m == "PUT" || m == "DELETE"): return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil @@ -167,9 +167,9 @@ func TestForceReplaceObjectNotFound(t *testing.T) { f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} - tf.Client = &client.FakeRESTClient{ + tf.Client = &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": return &http.Response{StatusCode: 404, Body: stringBody("")}, nil diff --git a/pkg/kubectl/cmd/util/factory_test.go b/pkg/kubectl/cmd/util/factory_test.go index c4b5c917994..a6dd840418b 100644 --- a/pkg/kubectl/cmd/util/factory_test.go +++ b/pkg/kubectl/cmd/util/factory_test.go @@ -30,9 +30,9 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/validation" - client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" @@ -199,9 +199,9 @@ func TestValidateCachesSchema(t *testing.T) { } requests := map[string]int{} - c := &client.FakeRESTClient{ + c := &fake.RESTClient{ Codec: testapi.Default.Codec(), - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case strings.HasPrefix(p, "/swaggerapi") && m == "GET": requests[p] = requests[p] + 1 diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index 3a2b07a42ee..290a8dff9cc 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -345,7 +345,7 @@ func Merge(dst runtime.Object, fragment, kind string) (runtime.Object, error) { if !ok { return nil, fmt.Errorf("apiVersion must be a string") } - i, err := latest.InterfacesFor(versionString) + i, err := latest.GroupOrDie("").InterfacesFor(versionString) if err != nil { return nil, err } diff --git a/pkg/kubectl/resource/builder_test.go b/pkg/kubectl/resource/builder_test.go index 97322f3d5d1..b3644c122ab 100644 --- a/pkg/kubectl/resource/builder_test.go +++ b/pkg/kubectl/resource/builder_test.go @@ -29,11 +29,10 @@ import ( "github.com/ghodss/yaml" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/testapi" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/errors" "k8s.io/kubernetes/pkg/watch" @@ -46,7 +45,7 @@ func stringBody(body string) io.ReadCloser { func watchBody(events ...watch.Event) string { buf := &bytes.Buffer{} - enc := watchjson.NewEncoder(buf, latest.Codec) + enc := watchjson.NewEncoder(buf, testapi.Default.Codec()) for _, e := range events { enc.Encode(&e) } @@ -55,15 +54,15 @@ func watchBody(events ...watch.Event) string { func fakeClient() ClientMapper { return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { - return &client.FakeRESTClient{}, nil + return &fake.RESTClient{}, nil }) } func fakeClientWith(testName string, t *testing.T, data map[string]string) ClientMapper { return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { - return &client.FakeRESTClient{ - Codec: latest.Codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + return &fake.RESTClient{ + Codec: testapi.Default.Codec(), + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { p := req.URL.Path q := req.URL.RawQuery if len(q) != 0 { @@ -129,8 +128,8 @@ func streamTestData() (io.Reader, *api.PodList, *api.ServiceList) { r, w := io.Pipe() go func() { defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, pods))) - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, svc))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), pods))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), svc))) }() return r, pods, svc } @@ -148,9 +147,9 @@ func streamYAMLTestData() (io.Reader, *api.PodList, *api.ServiceList) { r, w := io.Pipe() go func() { defer w.Close() - w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(latest.Codec, pods)))) + w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), pods)))) w.Write([]byte("\n---\n")) - w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(latest.Codec, svc)))) + w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), svc)))) }() return r, pods, svc } @@ -159,7 +158,7 @@ func streamTestObject(obj runtime.Object) io.Reader { r, w := io.Pipe() go func() { defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, obj))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), obj))) }() return r } @@ -186,7 +185,7 @@ func (v *testVisitor) Objects() []runtime.Object { } func TestPathBuilder(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml") test := &testVisitor{} @@ -217,10 +216,10 @@ func TestNodeBuilder(t *testing.T) { r, w := io.Pipe() go func() { defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, node))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), node))) }() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").Stream(r, "STDIN") test := &testVisitor{} @@ -236,7 +235,7 @@ func TestNodeBuilder(t *testing.T) { } func TestPathBuilderWithMultiple(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml"). FilenameParam(false, "../../../examples/pod"). NamespaceParam("test").DefaultNamespace() @@ -260,7 +259,7 @@ func TestPathBuilderWithMultiple(t *testing.T) { } func TestDirectoryBuilder(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, "../../../examples/guestbook"). NamespaceParam("test").DefaultNamespace() @@ -286,11 +285,11 @@ func TestDirectoryBuilder(t *testing.T) { func TestNamespaceOverride(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) })) defer s.Close() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, s.URL). NamespaceParam("test") @@ -301,7 +300,7 @@ func TestNamespaceOverride(t *testing.T) { t.Fatalf("unexpected response: %v %#v", err, test.Infos) } - b = NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(true, s.URL). NamespaceParam("test") @@ -316,11 +315,11 @@ func TestNamespaceOverride(t *testing.T) { func TestURLBuilder(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) })) defer s.Close() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, s.URL). NamespaceParam("test") @@ -340,11 +339,11 @@ func TestURLBuilder(t *testing.T) { func TestURLBuilderRequireNamespace(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) })) defer s.Close() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). FilenameParam(false, s.URL). NamespaceParam("test").RequireNamespace() @@ -359,8 +358,8 @@ func TestURLBuilderRequireNamespace(t *testing.T) { func TestResourceByName(t *testing.T) { pods, _ := testData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), })). NamespaceParam("test") @@ -392,11 +391,11 @@ func TestResourceByName(t *testing.T) { func TestMultipleResourceByTheSameName(t *testing.T) { pods, svcs := testData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), - "/namespaces/test/pods/baz": runtime.EncodeOrDie(latest.Codec, &pods.Items[1]), - "/namespaces/test/services/foo": runtime.EncodeOrDie(latest.Codec, &svcs.Items[0]), - "/namespaces/test/services/baz": runtime.EncodeOrDie(latest.Codec, &svcs.Items[0]), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), + "/namespaces/test/pods/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[1]), + "/namespaces/test/services/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), + "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), })). NamespaceParam("test") @@ -424,9 +423,9 @@ func TestMultipleResourceByTheSameName(t *testing.T) { func TestResourceNames(t *testing.T) { pods, svc := testData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), - "/namespaces/test/services/baz": runtime.EncodeOrDie(latest.Codec, &svc.Items[0]), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), + "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]), })). NamespaceParam("test") @@ -451,7 +450,7 @@ func TestResourceNames(t *testing.T) { } func TestResourceByNameWithoutRequireObject(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{})). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{})). NamespaceParam("test") test := &testVisitor{} @@ -485,8 +484,8 @@ func TestResourceByNameWithoutRequireObject(t *testing.T) { func TestResourceByNameAndEmptySelector(t *testing.T) { pods, _ := testData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), })). NamespaceParam("test"). SelectorParam(""). @@ -513,9 +512,9 @@ func TestResourceByNameAndEmptySelector(t *testing.T) { func TestSelector(t *testing.T) { pods, svc := testData() labelKey := api.LabelSelectorQueryParam(testapi.Default.Version()) - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(latest.Codec, pods), - "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(latest.Codec, svc), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), + "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), })). SelectorParam("a=b"). NamespaceParam("test"). @@ -544,7 +543,7 @@ func TestSelector(t *testing.T) { } func TestSelectorRequiresKnownTypes(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). SelectorParam("a=b"). NamespaceParam("test"). ResourceTypes("unknown") @@ -555,7 +554,7 @@ func TestSelectorRequiresKnownTypes(t *testing.T) { } func TestSingleResourceType(t *testing.T) { - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). SelectorParam("a=b"). SingleResourceType(). ResourceTypeOrNameArgs(true, "pods,services") @@ -619,14 +618,14 @@ func TestResourceTuple(t *testing.T) { if requireObject { pods, _ := testData() expectedRequests = map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), - "/namespaces/test/pods/bar": runtime.EncodeOrDie(latest.Codec, &pods.Items[0]), - "/nodes/foo": runtime.EncodeOrDie(latest.Codec, &api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}), - "/minions/foo": runtime.EncodeOrDie(latest.Codec, &api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}), + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), + "/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), + "/nodes/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}), + "/minions/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}), } } - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith(k, t, expectedRequests)). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith(k, t, expectedRequests)). NamespaceParam("test").DefaultNamespace(). ResourceTypeOrNameArgs(true, testCase.args...).RequireObject(requireObject) @@ -657,7 +656,7 @@ func TestResourceTuple(t *testing.T) { func TestStream(t *testing.T) { r, pods, rc := streamTestData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").Stream(r, "STDIN").Flatten() test := &testVisitor{} @@ -674,7 +673,7 @@ func TestStream(t *testing.T) { func TestYAMLStream(t *testing.T) { r, pods, rc := streamYAMLTestData() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").Stream(r, "STDIN").Flatten() test := &testVisitor{} @@ -691,7 +690,7 @@ func TestYAMLStream(t *testing.T) { func TestMultipleObject(t *testing.T) { r, pods, svc := streamTestData() - obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").Stream(r, "STDIN").Flatten(). Do().Object() @@ -713,7 +712,7 @@ func TestMultipleObject(t *testing.T) { func TestContinueOnErrorVisitor(t *testing.T) { r, _, _ := streamTestData() - req := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + req := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). ContinueOnError(). NamespaceParam("test").Stream(r, "STDIN").Flatten(). Do() @@ -742,7 +741,7 @@ func TestContinueOnErrorVisitor(t *testing.T) { } func TestSingularObject(t *testing.T) { - obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml"). Flatten(). @@ -762,7 +761,7 @@ func TestSingularObject(t *testing.T) { } func TestSingularObjectNoExtension(t *testing.T) { - obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). FilenameParam(false, "../../../examples/pod"). Flatten(). @@ -784,7 +783,7 @@ func TestSingularObjectNoExtension(t *testing.T) { func TestSingularRootScopedObject(t *testing.T) { node := &api.Node{ObjectMeta: api.ObjectMeta{Name: "test"}, Spec: api.NodeSpec{ExternalID: "test"}} r := streamTestObject(node) - infos, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + infos, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). Stream(r, "STDIN"). Flatten(). @@ -809,8 +808,8 @@ func TestSingularRootScopedObject(t *testing.T) { func TestListObject(t *testing.T) { pods, _ := testData() labelKey := api.LabelSelectorQueryParam(testapi.Default.Version()) - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(latest.Codec, pods), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), })). SelectorParam("a=b"). NamespaceParam("test"). @@ -842,9 +841,9 @@ func TestListObject(t *testing.T) { func TestListObjectWithDifferentVersions(t *testing.T) { pods, svc := testData() labelKey := api.LabelSelectorQueryParam(testapi.Default.Version()) - obj, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(latest.Codec, pods), - "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(latest.Codec, svc), + obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), + "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), })). SelectorParam("a=b"). NamespaceParam("test"). @@ -868,7 +867,7 @@ func TestListObjectWithDifferentVersions(t *testing.T) { func TestWatch(t *testing.T) { _, svc := testData() - w, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ + w, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/watch/namespaces/test/services/redis-master?resourceVersion=12": watchBody(watch.Event{ Type: watch.Added, Object: &svc.Items[0], @@ -900,7 +899,7 @@ func TestWatch(t *testing.T) { } func TestWatchMultipleError(t *testing.T) { - _, err := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + _, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). NamespaceParam("test").DefaultNamespace(). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten(). FilenameParam(false, "../../../examples/guestbook/redis-master-controller.yaml").Flatten(). @@ -923,10 +922,10 @@ func TestLatest(t *testing.T) { ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "15"}, } - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(latest.Codec, newPod), - "/namespaces/test/pods/bar": runtime.EncodeOrDie(latest.Codec, newPod2), - "/namespaces/test/services/baz": runtime.EncodeOrDie(latest.Codec, newSvc), + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ + "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), newPod), + "/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), newPod2), + "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), newSvc), })). NamespaceParam("other").Stream(r, "STDIN").Flatten().Latest() @@ -949,17 +948,17 @@ func TestReceiveMultipleErrors(t *testing.T) { go func() { defer w.Close() w.Write([]byte(`{}`)) - w.Write([]byte(runtime.EncodeOrDie(latest.Codec, &pods.Items[0]))) + w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]))) }() r2, w2 := io.Pipe() go func() { defer w2.Close() w2.Write([]byte(`{}`)) - w2.Write([]byte(runtime.EncodeOrDie(latest.Codec, &svc.Items[0]))) + w2.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]))) }() - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()). + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()). Stream(r, "1").Stream(r2, "2"). ContinueOnError() @@ -1003,7 +1002,7 @@ func TestReplaceAliases(t *testing.T) { }, } - b := NewBuilder(latest.RESTMapper, api.Scheme, fakeClient()) + b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient()) for _, test := range tests { replaced := b.replaceAliases(test.arg) diff --git a/pkg/kubectl/resource/helper_test.go b/pkg/kubectl/resource/helper_test.go index dcc1ede0160..a9d87a8433e 100644 --- a/pkg/kubectl/resource/helper_test.go +++ b/pkg/kubectl/resource/helper_test.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" - client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" ) @@ -92,7 +92,7 @@ func TestHelperDelete(t *testing.T) { }, } for _, test := range tests { - client := &client.FakeRESTClient{ + client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, @@ -131,7 +131,7 @@ func TestHelperCreate(t *testing.T) { grace := int64(30) tests := []struct { Resp *http.Response - RespFunc client.HTTPClientFunc + RespFunc fake.HTTPClientFunc HttpErr error Modify bool Object runtime.Object @@ -183,7 +183,7 @@ func TestHelperCreate(t *testing.T) { }, } for i, test := range tests { - client := &client.FakeRESTClient{ + client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, @@ -269,7 +269,7 @@ func TestHelperGet(t *testing.T) { }, } for _, test := range tests { - client := &client.FakeRESTClient{ + client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, @@ -340,7 +340,7 @@ func TestHelperList(t *testing.T) { }, } for _, test := range tests { - client := &client.FakeRESTClient{ + client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, @@ -386,7 +386,7 @@ func TestHelperReplace(t *testing.T) { grace := int64(30) tests := []struct { Resp *http.Response - RespFunc client.HTTPClientFunc + RespFunc fake.HTTPClientFunc HttpErr error Overwrite bool Object runtime.Object @@ -443,7 +443,7 @@ func TestHelperReplace(t *testing.T) { }, } for i, test := range tests { - client := &client.FakeRESTClient{ + client := &fake.RESTClient{ Codec: testapi.Default.Codec(), Resp: test.Resp, Err: test.HttpErr, diff --git a/pkg/kubectl/resource/result.go b/pkg/kubectl/resource/result.go index 3ac6d720157..6931fe4b136 100644 --- a/pkg/kubectl/resource/result.go +++ b/pkg/kubectl/resource/result.go @@ -220,7 +220,7 @@ func AsVersionedObject(infos []*Info, forceList bool, version string) (runtime.O object = objects[0] } else { object = &api.List{Items: objects} - converted, err := tryConvert(api.Scheme, object, version, latest.Version) + converted, err := tryConvert(api.Scheme, object, version, latest.GroupOrDie("").Version) if err != nil { return nil, err } diff --git a/pkg/kubectl/rolling_updater_test.go b/pkg/kubectl/rolling_updater_test.go index 2ca9ab6ef58..fa30b567ae3 100644 --- a/pkg/kubectl/rolling_updater_test.go +++ b/pkg/kubectl/rolling_updater_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" @@ -1052,9 +1053,9 @@ func TestUpdateWithRetries(t *testing.T) { {StatusCode: 500, Body: objBody(codec, &api.ReplicationController{})}, {StatusCode: 200, Body: objBody(codec, rc)}, } - fakeClient := &client.FakeRESTClient{ + fakeClient := &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "PUT": update := updates[0] @@ -1143,9 +1144,9 @@ func TestAddDeploymentHash(t *testing.T) { seen := sets.String{} updatedRc := false - fakeClient := &client.FakeRESTClient{ + fakeClient := &fake.RESTClient{ Codec: codec, - Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { + Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == testapi.Default.ResourcePath("pods", "default", "") && m == "GET": if req.URL.RawQuery != "labelSelector=foo%3Dbar" { diff --git a/pkg/kubelet/config/common.go b/pkg/kubelet/config/common.go index b1f075b3bef..355d5d4c4ca 100644 --- a/pkg/kubelet/config/common.go +++ b/pkg/kubelet/config/common.go @@ -72,7 +72,7 @@ func getSelfLink(name, namespace string) string { if len(namespace) == 0 { namespace = api.NamespaceDefault } - selfLink = fmt.Sprintf("/api/"+latest.Version+"/pods/namespaces/%s/%s", name, namespace) + selfLink = fmt.Sprintf("/api/"+latest.GroupOrDie("").Version+"/pods/namespaces/%s/%s", name, namespace) return selfLink } diff --git a/pkg/kubelet/config/common_test.go b/pkg/kubelet/config/common_test.go index ccfb88effaa..baca88fed89 100644 --- a/pkg/kubelet/config/common_test.go +++ b/pkg/kubelet/config/common_test.go @@ -69,7 +69,7 @@ func TestDecodeSinglePod(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) } - for _, version := range registered.RegisteredVersions { + for _, version := range registered.GroupVersionsForGroup("") { externalPod, err := testapi.Default.Converter().ConvertToVersion(pod, version) if err != nil { t.Errorf("unexpected error: %v", err) @@ -134,7 +134,7 @@ func TestDecodePodList(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", podList, &podListOut, string(json)) } - for _, version := range registered.RegisteredVersions { + for _, version := range registered.GroupVersionsForGroup("") { externalPodList, err := testapi.Default.Converter().ConvertToVersion(podList, version) if err != nil { t.Errorf("unexpected error: %v", err) diff --git a/pkg/kubelet/dockertools/manager.go b/pkg/kubelet/dockertools/manager.go index ee609749102..e59a2474f87 100644 --- a/pkg/kubelet/dockertools/manager.go +++ b/pkg/kubelet/dockertools/manager.go @@ -633,7 +633,7 @@ func (dm *DockerManager) runContainer( } if container.Lifecycle != nil && container.Lifecycle.PreStop != nil { // TODO: This is kind of hacky, we should really just encode the bits we need. - data, err := latest.Codec.Encode(pod) + data, err := latest.GroupOrDie("").Codec.Encode(pod) if err != nil { glog.Errorf("Failed to encode pod: %s for prestop hook", pod.Name) } else { @@ -1337,7 +1337,7 @@ func containerAndPodFromLabels(inspect *docker.Container) (pod *api.Pod, contain // the pod data may not be set if body, found := labels[kubernetesPodLabel]; found { pod = &api.Pod{} - if err = latest.Codec.DecodeInto([]byte(body), pod); err == nil { + if err = latest.GroupOrDie("").Codec.DecodeInto([]byte(body), pod); err == nil { name := labels[kubernetesContainerLabel] for ix := range pod.Spec.Containers { if pod.Spec.Containers[ix].Name == name { diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index 41f7dd90ab8..f8075832f28 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -364,7 +364,7 @@ func encodePods(pods []*api.Pod) (data []byte, err error) { for _, pod := range pods { podList.Items = append(podList.Items, *pod) } - return latest.Codec.Encode(podList) + return latest.GroupOrDie("").Codec.Encode(podList) } // getPods returns a list of pods bound to the Kubelet and their spec. diff --git a/pkg/master/import_known_versions.go b/pkg/master/import_known_versions.go new file mode 100644 index 00000000000..af2c9052e21 --- /dev/null +++ b/pkg/master/import_known_versions.go @@ -0,0 +1,23 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package master + +// These imports are the API groups the API server will support. +import ( + _ "k8s.io/kubernetes/pkg/api/install" + _ "k8s.io/kubernetes/pkg/apis/experimental/install" +) diff --git a/pkg/master/master.go b/pkg/master/master.go index a90a2f3ade4..6e702fc8f38 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -38,7 +38,6 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/apis/experimental" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authorizer" @@ -617,7 +616,7 @@ func (m *Master) init(c *Config) { m.InsecureHandler = handler - attributeGetter := apiserver.NewRequestAttributeGetter(m.requestContextMapper, latest.RESTMapper, "api") + attributeGetter := apiserver.NewRequestAttributeGetter(m.requestContextMapper, latest.GroupOrDie("").RESTMapper, "api") handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, m.authorizer) // Install Authenticator @@ -747,12 +746,12 @@ func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion { return &apiserver.APIGroupVersion{ Root: m.apiPrefix, - Mapper: latest.RESTMapper, + Mapper: latest.GroupOrDie("").RESTMapper, Creater: api.Scheme, Convertor: api.Scheme, Typer: api.Scheme, - Linker: latest.SelfLinker, + Linker: latest.GroupOrDie("").SelfLinker, Admit: m.admissionControl, Context: m.requestContextMapper, @@ -807,9 +806,9 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV Convertor: api.Scheme, Typer: api.Scheme, - Mapper: thirdpartyresourcedata.NewMapper(explatest.RESTMapper, kind, version), - Codec: explatest.Codec, - Linker: explatest.SelfLinker, + Mapper: thirdpartyresourcedata.NewMapper(latest.GroupOrDie("experimental").RESTMapper, kind, version), + Codec: latest.GroupOrDie("experimental").Codec, + Linker: latest.GroupOrDie("experimental").SelfLinker, Storage: storage, Version: version, @@ -847,11 +846,11 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion { Convertor: api.Scheme, Typer: api.Scheme, - Mapper: explatest.RESTMapper, - Codec: explatest.Codec, - Linker: explatest.SelfLinker, + Mapper: latest.GroupOrDie("experimental").RESTMapper, + Codec: latest.GroupOrDie("experimental").Codec, + Linker: latest.GroupOrDie("experimental").SelfLinker, Storage: storage, - Version: explatest.Version, + Version: latest.GroupOrDie("experimental").Version, Admit: m.admissionControl, Context: m.requestContextMapper, diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index b8a0cc78bf7..2e2a1c340aa 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -36,9 +36,9 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/apis/experimental" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/apiserver" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/fields" @@ -58,8 +58,8 @@ func setUp(t *testing.T) (Master, Config, *assert.Assertions) { config := Config{} fakeClient := tools.NewFakeEtcdClient(t) fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} - config.DatabaseStorage = etcdstorage.NewEtcdStorage(fakeClient, latest.Codec, etcdtest.PathPrefix()) - config.ExpDatabaseStorage = etcdstorage.NewEtcdStorage(fakeClient, explatest.Codec, etcdtest.PathPrefix()) + config.DatabaseStorage = etcdstorage.NewEtcdStorage(fakeClient, testapi.Default.Codec(), etcdtest.PathPrefix()) + config.ExpDatabaseStorage = etcdstorage.NewEtcdStorage(fakeClient, testapi.Experimental.Codec(), etcdtest.PathPrefix()) master.nodeRegistry = registrytest.NewNodeRegistry([]string{"node1", "node2"}, api.NodeResources{}) @@ -104,12 +104,12 @@ func TestNewEtcdStorage(t *testing.T) { assert := assert.New(t) fakeClient := tools.NewFakeEtcdClient(t) // Pass case - _, err := NewEtcdStorage(fakeClient, latest.InterfacesFor, latest.Version, etcdtest.PathPrefix()) + _, err := NewEtcdStorage(fakeClient, latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) assert.NoError(err, "Unable to create etcdstorage: %s", err) // Fail case errorFunc := func(apiVersion string) (*meta.VersionInterfaces, error) { return nil, errors.New("ERROR") } - _, err = NewEtcdStorage(fakeClient, errorFunc, latest.Version, etcdtest.PathPrefix()) + _, err = NewEtcdStorage(fakeClient, errorFunc, testapi.Default.Version(), etcdtest.PathPrefix()) assert.Error(err, "NewEtcdStorage should have failed") } @@ -282,10 +282,10 @@ func TestExpapi(t *testing.T) { expAPIGroup := master.experimental(&config) assert.Equal(expAPIGroup.Root, master.expAPIPrefix) - assert.Equal(expAPIGroup.Mapper, explatest.RESTMapper) - assert.Equal(expAPIGroup.Codec, explatest.Codec) - assert.Equal(expAPIGroup.Linker, explatest.SelfLinker) - assert.Equal(expAPIGroup.Version, explatest.Version) + assert.Equal(expAPIGroup.Mapper, latest.GroupOrDie("experimental").RESTMapper) + assert.Equal(expAPIGroup.Codec, latest.GroupOrDie("experimental").Codec) + assert.Equal(expAPIGroup.Linker, latest.GroupOrDie("experimental").SelfLinker) + assert.Equal(expAPIGroup.Version, latest.GroupOrDie("experimental").Version) } // TestSecondsSinceSync verifies that proper results are returned @@ -457,7 +457,7 @@ func initThirdParty(t *testing.T, version string) (*tools.FakeEtcdClient, *httpt fakeClient := tools.NewFakeEtcdClient(t) fakeClient.Machines = []string{"http://machine1:4001", "http://machine2", "http://machine3:4003"} - master.thirdPartyStorage = etcdstorage.NewEtcdStorage(fakeClient, explatest.Codec, etcdtest.PathPrefix()) + master.thirdPartyStorage = etcdstorage.NewEtcdStorage(fakeClient, testapi.Experimental.Codec(), etcdtest.PathPrefix()) if !assert.NoError(master.InstallThirdPartyAPI(api)) { t.FailNow() @@ -506,7 +506,7 @@ func encodeToThirdParty(name string, obj interface{}) ([]byte, error) { ObjectMeta: api.ObjectMeta{Name: name}, Data: serial, } - return latest.Codec.Encode(&thirdPartyData) + return testapi.Default.Codec().Encode(&thirdPartyData) } func storeToEtcd(fakeClient *tools.FakeEtcdClient, path, name string, obj interface{}) error { @@ -628,11 +628,12 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { t.FailNow() } - obj, err := explatest.Codec.Decode([]byte(etcdResp.Node.Value)) - assert.NoError(err) - + obj, err := testapi.Experimental.Codec().Decode([]byte(etcdResp.Node.Value)) + if err != nil { + t.Errorf("unexpected error: %v", err) + } thirdPartyObj, ok := obj.(*experimental.ThirdPartyResourceData) - if !assert.True(ok) { + if !ok { t.Errorf("unexpected object: %v", obj) } item = Foo{} diff --git a/pkg/registry/thirdpartyresourcedata/codec.go b/pkg/registry/thirdpartyresourcedata/codec.go index 18c668cde0d..370f7a2df54 100644 --- a/pkg/registry/thirdpartyresourcedata/codec.go +++ b/pkg/registry/thirdpartyresourcedata/codec.go @@ -23,9 +23,9 @@ import ( "strings" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/apis/experimental" - "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/runtime" ) @@ -49,7 +49,7 @@ func (t *thirdPartyResourceDataMapper) RESTMapping(kind string, versions ...stri if kind != "ThirdPartyResourceData" { return nil, fmt.Errorf("unknown kind %s expected %s", kind, t.kind) } - mapping, err := t.mapper.RESTMapping("ThirdPartyResourceData", latest.Version) + mapping, err := t.mapper.RESTMapping("ThirdPartyResourceData", latest.GroupOrDie("experimental").Version) if err != nil { return nil, err } @@ -263,6 +263,6 @@ func (t *thirdPartyResourceDataCreator) New(version, kind string) (out runtime.O case "ThirdPartyResourceDataList": return &experimental.ThirdPartyResourceDataList{}, nil default: - return t.delegate.New(latest.Version, kind) + return t.delegate.New(latest.GroupOrDie("experimental").Version, kind) } } diff --git a/pkg/storage/etcd/etcd_watcher_test.go b/pkg/storage/etcd/etcd_watcher_test.go index 43e630df18b..a1e82ce533e 100644 --- a/pkg/storage/etcd/etcd_watcher_test.go +++ b/pkg/storage/etcd/etcd_watcher_test.go @@ -23,7 +23,7 @@ import ( "github.com/coreos/go-etcd/etcd" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/tools" @@ -46,7 +46,7 @@ func (f *fakeEtcdCache) addToCache(index uint64, obj runtime.Object) { var _ etcdCache = &fakeEtcdCache{} func TestWatchInterpretations(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() // Declare some pods to make the test cases compact. podFoo := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} podBar := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} @@ -215,7 +215,7 @@ func TestWatchInterpretation_ResponseBadData(t *testing.T) { } func TestWatchEtcdError(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() fakeClient := tools.NewFakeEtcdClient(t) fakeClient.ExpectNotFoundGet("/some/key") fakeClient.WatchImmediateError = fmt.Errorf("immediate error") @@ -244,7 +244,7 @@ func TestWatchEtcdError(t *testing.T) { } func TestWatch(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() fakeClient := tools.NewFakeEtcdClient(t) key := "/some/key" prefixedKey := etcdtest.AddPrefix(key) @@ -315,7 +315,7 @@ func makeSubsets(ip string, port int) []api.EndpointSubset { } func TestWatchEtcdState(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() baseKey := "/somekey/foo" prefixedKey := etcdtest.AddPrefix(baseKey) type T struct { @@ -453,7 +453,7 @@ func TestWatchEtcdState(t *testing.T) { } func TestWatchFromZeroIndex(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} testCases := map[string]struct { @@ -531,7 +531,7 @@ func TestWatchFromZeroIndex(t *testing.T) { } func TestWatchListFromZeroIndex(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} key := "/some/key" prefixedKey := etcdtest.AddPrefix(key) @@ -593,7 +593,7 @@ func TestWatchListFromZeroIndex(t *testing.T) { } func TestWatchListIgnoresRootKey(t *testing.T) { - codec := latest.Codec + codec := testapi.Default.Codec() pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} key := "/some/key" prefixedKey := etcdtest.AddPrefix(key) diff --git a/pkg/volume/aws_ebs/aws_ebs_test.go b/pkg/volume/aws_ebs/aws_ebs_test.go index 517934b8fc4..be3948093d5 100644 --- a/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/pkg/volume/aws_ebs/aws_ebs_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" @@ -192,7 +192,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/gce_pd/gce_pd_test.go b/pkg/volume/gce_pd/gce_pd_test.go index 2ced180a36d..fa7ad892a1d 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" @@ -206,7 +206,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/glusterfs/glusterfs_test.go b/pkg/volume/glusterfs/glusterfs_test.go index 6b42c839f4e..f603159bd1e 100644 --- a/pkg/volume/glusterfs/glusterfs_test.go +++ b/pkg/volume/glusterfs/glusterfs_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/exec" @@ -201,7 +201,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(claim) o.Add(ep) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index 9e7fe52c642..5c5be1ea649 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -20,7 +20,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/volume" @@ -158,7 +158,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/iscsi/iscsi_test.go b/pkg/volume/iscsi/iscsi_test.go index 053279e9d88..b2d05cdf8fe 100644 --- a/pkg/volume/iscsi/iscsi_test.go +++ b/pkg/volume/iscsi/iscsi_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" @@ -235,7 +235,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index 588aa765aff..3cb92e7740a 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" @@ -236,7 +236,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(volume.VolumeConfig{}), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/rbd/rbd_test.go b/pkg/volume/rbd/rbd_test.go index 10060ff1958..1c007ed0abb 100644 --- a/pkg/volume/rbd/rbd_test.go +++ b/pkg/volume/rbd/rbd_test.go @@ -21,7 +21,7 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util/mount" @@ -192,7 +192,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) client := &testclient.Fake{} - client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) + client.AddReactor("*", "*", testclient.ObjectReaction(o, testapi.Default.RESTMapper())) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/plugin/pkg/scheduler/factory/factory_test.go b/plugin/pkg/scheduler/factory/factory_test.go index 1f27a07c302..a4ba4498cb9 100644 --- a/plugin/pkg/scheduler/factory/factory_test.go +++ b/plugin/pkg/scheduler/factory/factory_test.go @@ -24,7 +24,6 @@ import ( "time" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/client/cache" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -143,7 +142,7 @@ func TestDefaultErrorFunc(t *testing.T) { } handler := util.FakeHandler{ StatusCode: 200, - ResponseBody: runtime.EncodeOrDie(latest.Codec, testPod), + ResponseBody: runtime.EncodeOrDie(testapi.Default.Codec(), testPod), T: t, } mux := http.NewServeMux() diff --git a/test/e2e/dns.go b/test/e2e/dns.go index 33fb9b55d18..2335e247575 100644 --- a/test/e2e/dns.go +++ b/test/e2e/dns.go @@ -42,7 +42,7 @@ func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *api.Pod { pod := &api.Pod{ TypeMeta: api.TypeMeta{ Kind: "Pod", - APIVersion: latest.Version, + APIVersion: latest.GroupOrDie("").Version, }, ObjectMeta: api.ObjectMeta{ Name: "dns-test-" + string(util.NewUUID()), diff --git a/test/e2e/empty_dir.go b/test/e2e/empty_dir.go index a8724cab931..e3d5517f70e 100644 --- a/test/e2e/empty_dir.go +++ b/test/e2e/empty_dir.go @@ -207,7 +207,7 @@ func testPodWithVolume(image, path string, source *api.EmptyDirVolumeSource) *ap return &api.Pod{ TypeMeta: api.TypeMeta{ Kind: "Pod", - APIVersion: latest.Version, + APIVersion: latest.GroupOrDie("").Version, }, ObjectMeta: api.ObjectMeta{ Name: podName, diff --git a/test/e2e/host_path.go b/test/e2e/host_path.go index 6e55c62bd5a..a596631aecf 100644 --- a/test/e2e/host_path.go +++ b/test/e2e/host_path.go @@ -123,7 +123,7 @@ func testPodWithHostVol(path string, source *api.HostPathVolumeSource) *api.Pod return &api.Pod{ TypeMeta: api.TypeMeta{ Kind: "Pod", - APIVersion: latest.Version, + APIVersion: latest.GroupOrDie("").Version, }, ObjectMeta: api.ObjectMeta{ Name: podName, diff --git a/test/e2e/pd.go b/test/e2e/pd.go index f7ec6def9a5..9ce9ea5306a 100644 --- a/test/e2e/pd.go +++ b/test/e2e/pd.go @@ -342,7 +342,7 @@ func testPDPod(diskName, targetHost string, readOnly bool, numContainers int) *a pod := &api.Pod{ TypeMeta: api.TypeMeta{ Kind: "Pod", - APIVersion: latest.Version, + APIVersion: latest.GroupOrDie("").Version, }, ObjectMeta: api.ObjectMeta{ Name: "pd-test-" + string(util.NewUUID()), diff --git a/test/e2e/resize_nodes.go b/test/e2e/resize_nodes.go index c3674726a01..74473a7f0ec 100644 --- a/test/e2e/resize_nodes.go +++ b/test/e2e/resize_nodes.go @@ -185,7 +185,7 @@ func rcByNameContainer(name string, replicas int, image string, labels map[strin return &api.ReplicationController{ TypeMeta: api.TypeMeta{ Kind: "ReplicationController", - APIVersion: latest.Version, + APIVersion: latest.GroupOrDie("").Version, }, ObjectMeta: api.ObjectMeta{ Name: name, diff --git a/test/integration/framework/etcd_utils.go b/test/integration/framework/etcd_utils.go index e4f09ecad1f..3cf7b9b47db 100644 --- a/test/integration/framework/etcd_utils.go +++ b/test/integration/framework/etcd_utils.go @@ -41,7 +41,7 @@ func NewEtcdClient() *etcd.Client { } func NewEtcdStorage() (storage.Interface, error) { - return master.NewEtcdStorage(NewEtcdClient(), latest.InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) + return master.NewEtcdStorage(NewEtcdClient(), latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) } func RequireEtcd() { diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index 60683243b7c..7824a724896 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -29,7 +29,6 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/testapi" - explatest "k8s.io/kubernetes/pkg/apis/experimental/latest" "k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/client/record" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -131,11 +130,11 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se var err error if masterConfig == nil { etcdClient := NewEtcdClient() - etcdStorage, err = master.NewEtcdStorage(etcdClient, latest.InterfacesFor, latest.Version, etcdtest.PathPrefix()) + etcdStorage, err = master.NewEtcdStorage(etcdClient, latest.GroupOrDie("").InterfacesFor, latest.GroupOrDie("").Version, etcdtest.PathPrefix()) if err != nil { glog.Fatalf("Failed to create etcd storage for master %v", err) } - expEtcdStorage, err := master.NewEtcdStorage(etcdClient, explatest.InterfacesFor, explatest.Version, etcdtest.PathPrefix()) + expEtcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("experimental").InterfacesFor, latest.GroupOrDie("experimental").Version, etcdtest.PathPrefix()) if err != nil { glog.Fatalf("Failed to create etcd storage for master %v", err) } @@ -269,11 +268,11 @@ func StartPods(numPods int, host string, restClient *client.Client) error { // TODO: Merge this into startMasterOrDie. func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) { etcdClient := NewEtcdClient() - etcdStorage, err := master.NewEtcdStorage(etcdClient, latest.InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) + etcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) if err != nil { t.Fatalf("unexpected error: %v", err) } - expEtcdStorage, err := master.NewEtcdStorage(etcdClient, explatest.InterfacesFor, explatest.Version, etcdtest.PathPrefix()) + expEtcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("experimental").InterfacesFor, latest.GroupOrDie("experimental").Version, etcdtest.PathPrefix()) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/test/integration/service_account_test.go b/test/integration/service_account_test.go index fe3ae4fd2db..05886332a8d 100644 --- a/test/integration/service_account_test.go +++ b/test/integration/service_account_test.go @@ -341,7 +341,7 @@ func startServiceAccountTestServer(t *testing.T) (*client.Client, client.Config, deleteAllEtcdKeys() // Etcd - etcdStorage, err := master.NewEtcdStorage(newEtcdClient(), latest.InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) + etcdStorage, err := master.NewEtcdStorage(newEtcdClient(), latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/test/integration/utils.go b/test/integration/utils.go index fb8c4cac838..e2e86721171 100644 --- a/test/integration/utils.go +++ b/test/integration/utils.go @@ -66,7 +66,7 @@ func deleteAllEtcdKeys() { } func runAMaster(t *testing.T) (*master.Master, *httptest.Server) { - etcdStorage, err := master.NewEtcdStorage(newEtcdClient(), latest.InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) + etcdStorage, err := master.NewEtcdStorage(newEtcdClient(), latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix()) if err != nil { t.Fatalf("unexpected error: %v", err) }