From 03c2a2bd451577b319977ebfa8d93d686d475628 Mon Sep 17 00:00:00 2001 From: Maciej Szulik Date: Tue, 26 Jan 2016 05:44:07 -0500 Subject: [PATCH] API Group Version changes Addresses comments on dc94f8dca4b2381c3a143a85af147811f746cfa5 Addresses comments on 4eba7602fea40c79c298567fd01e4493771ea3fc --- cmd/origin-version-change/main.go | 6 +- pkg/api/latest/latest.go | 57 +++++++------ pkg/api/latest/latest_test.go | 28 ++++++- pkg/api/latest/tags_test.go | 6 +- pkg/api/register.go | 5 ++ pkg/api/serialization_test.go | 36 ++++---- pkg/api/validation/coverage_test.go | 3 +- pkg/api/validation/validation.go | 4 +- pkg/build/admission/admission.go | 6 +- pkg/build/admission/admission_test.go | 27 +++--- pkg/build/controller/strategy/sti.go | 2 +- pkg/client/client.go | 11 +-- pkg/client/scale.go | 9 +- pkg/cmd/admin/node/node_options.go | 13 +-- pkg/cmd/cli/cmd/edit.go | 22 ++--- pkg/cmd/cli/cmd/env.go | 15 ++-- pkg/cmd/cli/cmd/export.go | 11 ++- pkg/cmd/cli/cmd/expose.go | 6 +- pkg/cmd/cli/cmd/loginoptions.go | 6 +- pkg/cmd/cli/cmd/logs.go | 2 +- pkg/cmd/cli/cmd/newapp.go | 2 +- pkg/cmd/cli/cmd/process.go | 11 ++- pkg/cmd/cli/cmd/startbuild.go | 2 +- pkg/cmd/cli/cmd/tag.go | 4 +- pkg/cmd/cli/cmd/volume.go | 12 ++- pkg/cmd/cli/config/smart_merge.go | 4 +- pkg/cmd/cli/describe/describer.go | 61 +++++++------- pkg/cmd/cli/describe/describer_test.go | 5 +- pkg/cmd/cli/describe/printer_test.go | 13 +-- pkg/cmd/infra/deployer/deployer.go | 2 +- .../admin/create_bootstrappolicy_file.go | 2 +- pkg/cmd/server/admin/create_nodeconfig.go | 2 +- .../server/admin/overwrite_bootstrappolicy.go | 4 +- pkg/cmd/server/api/types.go | 6 +- pkg/cmd/server/api/v1/types_test.go | 4 +- pkg/cmd/server/origin/auth_config.go | 6 +- pkg/cmd/server/origin/handlers.go | 12 +-- pkg/cmd/server/origin/master.go | 16 ++-- pkg/cmd/server/origin/master_config.go | 13 ++- pkg/cmd/server/origin/run_components.go | 4 +- pkg/cmd/util/clientcmd/factory.go | 84 +++++++++++-------- pkg/cmd/util/clientcmd/factory_test.go | 29 ++++--- pkg/cmd/util/cmd.go | 4 +- pkg/cmd/util/pluginconfig/config_test.go | 6 +- pkg/deploy/strategy/recreate/recreate.go | 2 +- pkg/generate/app/pipeline.go | 9 +- pkg/image/api/v1/conversion.go | 3 +- pkg/image/api/v1beta3/conversion.go | 3 +- pkg/project/admission/lifecycle/admission.go | 21 +++-- .../admission/lifecycle/admission_test.go | 14 ++-- pkg/project/admission/nodeenv/admission.go | 6 +- .../admission/nodeenv/admission_test.go | 2 +- .../projectrequest/delegated/delegated.go | 2 +- pkg/security/admission/admission.go | 2 +- pkg/security/admission/admission_test.go | 15 ++-- pkg/security/admission/scc_exec.go | 5 +- pkg/security/admission/scc_exec_test.go | 2 +- pkg/template/registry/rest_test.go | 2 +- test/integration/admissionconfig_test.go | 6 +- test/integration/template_test.go | 5 +- test/templates/templates_test.go | 6 +- test/util/helpers.go | 10 +-- tools/genconversion/conversion.go | 7 +- tools/gendeepcopy/deep_copy.go | 10 ++- 64 files changed, 419 insertions(+), 296 deletions(-) diff --git a/cmd/origin-version-change/main.go b/cmd/origin-version-change/main.go index 921b26f08a2e..b379d3b24a2f 100644 --- a/cmd/origin-version-change/main.go +++ b/cmd/origin-version-change/main.go @@ -29,7 +29,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.Version.Version, "Version to convert input to") ) // isYAML determines whether data is JSON or YAML formatted by seeing @@ -47,12 +47,12 @@ func changeObjectsVersion(items []kruntime.Object) { log.Fatalf("Unable to decode Template objects: %v", errs) } for i, obj := range items { - _, kind, err := api.Scheme.ObjectVersionAndKind(obj) + groupVersionKind, err := api.Scheme.ObjectKind(obj) if err != nil { glog.Infof("Template.Objects[%d]: Unable to determine version and kind: %v", i, err) continue } - mapping, err := latest.RESTMapper.RESTMapping(kind, *outputVersion) + mapping, err := latest.RESTMapper.RESTMapping(groupVersionKind.GroupKind(), *outputVersion) if err != nil { glog.Infof("Template.Objects[%d]: Unable to get REST mappings: %v", err) continue diff --git a/pkg/api/latest/latest.go b/pkg/api/latest/latest.go index 973e46b66406..2bd9dc21699d 100644 --- a/pkg/api/latest/latest.go +++ b/pkg/api/latest/latest.go @@ -6,8 +6,8 @@ import ( "k8s.io/kubernetes/pkg/api" kmeta "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/sets" "github.com/golang/glog" @@ -17,17 +17,17 @@ import ( ) // Version is the string that represents the current external default version. -const Version = "v1" +var Version = v1.SchemeGroupVersion // OldestVersion is the string that represents the oldest server version supported, // for client code that wants to hardcode the lowest common denominator. -const OldestVersion = "v1beta3" +var OldestVersion = v1beta3.SchemeGroupVersion // 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 +// may be assumed to be most preferred to least preferred, and clients may +// choose to prefer the earlier items in the list over the latter items when presented // with a set of versions to choose. -var Versions = []string{"v1", "v1beta3"} +var Versions = []unversioned.GroupVersion{v1.SchemeGroupVersion, v1beta3.SchemeGroupVersion} // Codec is the default codec for serializing output that should use // the latest supported version. Use this Codec when writing to @@ -55,27 +55,27 @@ var RESTMapper kmeta.RESTMapper // 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) (*kmeta.VersionInterfaces, error) { +func InterfacesFor(version unversioned.GroupVersion) (*kmeta.VersionInterfaces, error) { switch version { - case "v1beta3": + case v1beta3.SchemeGroupVersion: return &kmeta.VersionInterfaces{ Codec: v1beta3.Codec, ObjectConvertor: api.Scheme, MetadataAccessor: accessor, }, nil - case "v1": + case v1.SchemeGroupVersion: return &kmeta.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, ", ")) + return nil, fmt.Errorf("unsupported storage version: %q (valid: %v)", version, Versions) } } // originTypes are the hardcoded types defined by the OpenShift API. -var originTypes = sets.String{} +var originTypes = make(map[unversioned.GroupVersionKind]bool) // UserResources are the resource names that apply to the primary, user facing resources used by // client tools. They are in deletion-first order - dependent resources should be last. @@ -87,9 +87,21 @@ var UserResources = []string{ "pods", } -// OriginKind returns true if OpenShift owns the kind described in a given apiVersion. -func OriginKind(kind, apiVersion string) bool { - return originTypes.Has(kind) +// OriginKind returns true if OpenShift owns the GroupVersionKind. +func OriginKind(gvk unversioned.GroupVersionKind) bool { + return originTypes[gvk] +} + +// IsKindInAnyOriginGroup returns true if OpenShift owns the kind described in any apiVersion. +// TODO: this may not work once we divide builds/deployments/images into their own API groups +func IsKindInAnyOriginGroup(kind string) bool { + for _, version := range Versions { + if OriginKind(version.WithKind(kind)) { + return true + } + } + + return false } func init() { @@ -97,13 +109,9 @@ func init() { // api.RESTMapper, which is different than what you'd get from latest. kubeMapper := api.RESTMapper - // list of versions we support on the server, in preferred order - versions := []string{"v1", "v1beta3"} - originMapper := kmeta.NewDefaultRESTMapper( - "", - versions, - func(version string) (*kmeta.VersionInterfaces, error) { + Versions, + func(version unversioned.GroupVersion) (*kmeta.VersionInterfaces, error) { interfaces, err := InterfacesFor(version) if err != nil { return nil, err @@ -143,21 +151,22 @@ func init() { } // enumerate all supported versions, get the kinds, and register with the mapper how to address our resources - for _, version := range versions { + for _, version := range Versions { for kind, t := range api.Scheme.KnownTypes(version) { if !strings.Contains(t.PkgPath(), "openshift/origin") { if _, ok := kindToRootScope[kind]; !ok { continue } } - originTypes.Insert(kind) scope := kmeta.RESTScopeNamespace _, found := kindToRootScope[kind] if found || (strings.HasSuffix(kind, "List") && kindToRootScope[strings.TrimSuffix(kind, "List")]) { scope = kmeta.RESTScopeRoot } - glog.V(6).Infof("Registering %s %s %s", kind, version, scope.Name()) - originMapper.Add(scope, kind, version, false) + gvk := version.WithKind(kind) + originTypes[gvk] = true + glog.V(6).Infof("Registering %s %s", gvk.String(), scope.Name()) + originMapper.Add(gvk, scope, false) } } diff --git a/pkg/api/latest/latest_test.go b/pkg/api/latest/latest_test.go index 044c4a6c396c..bc23d56834ef 100644 --- a/pkg/api/latest/latest_test.go +++ b/pkg/api/latest/latest_test.go @@ -3,12 +3,14 @@ package latest import ( "testing" + kapi "k8s.io/kubernetes/pkg/api" + klatest "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" ) func TestRESTRootScope(t *testing.T) { for _, v := range [][]string{{"v1beta3"}, {"v1"}} { - mapping, err := RESTMapper.RESTMapping("Node", v...) + mapping, err := RESTMapper.RESTMapping(kapi.Kind("Node"), v...) if err != nil { t.Fatal(err) } @@ -17,3 +19,27 @@ func TestRESTRootScope(t *testing.T) { } } } + +func TestResourceToKind(t *testing.T) { + // Ensure we resolve to latest.Version + expectedGVK := Version.WithKind("User") + gvk, err := RESTMapper.KindFor("user") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if gvk != expectedGVK { + t.Fatalf("Expected RESTMapper.KindFor('user') to be %#v, got %#v", expectedGVK, gvk) + } +} + +func TestUpstreamResourceToKind(t *testing.T) { + // Ensure we resolve to klatest.ExternalVersions[0] + expectedGVK := klatest.ExternalVersions[0].WithKind("Pod") + gvk, err := klatest.GroupOrDie(kapi.SchemeGroupVersion.Group).RESTMapper.KindFor("pod") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if gvk != expectedGVK { + t.Fatalf("Expected RESTMapper.KindFor('pod') to be %#v, got %#v", expectedGVK, gvk) + } +} diff --git a/pkg/api/latest/tags_test.go b/pkg/api/latest/tags_test.go index 4cdc2beddabc..858546826638 100644 --- a/pkg/api/latest/tags_test.go +++ b/pkg/api/latest/tags_test.go @@ -10,11 +10,13 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/sets" + + "github.com/openshift/origin/pkg/api" ) func TestDescriptions(t *testing.T) { for _, version := range Versions { - if version == "v1beta3" { + if version == OldestVersion { // we don't care about descriptions here continue } @@ -63,7 +65,7 @@ func checkDescriptions(objType reflect.Type, seen *map[reflect.Type]bool, t *tes func TestInternalJsonTags(t *testing.T) { seen := map[reflect.Type]bool{} - for _, apiType := range kapi.Scheme.KnownTypes("") { + for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) { checkJsonTags(apiType, &seen, t) } } diff --git a/pkg/api/register.go b/pkg/api/register.go index 4c4c5e86403c..a852922af6c9 100644 --- a/pkg/api/register.go +++ b/pkg/api/register.go @@ -3,6 +3,7 @@ package api import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/runtime" _ "github.com/openshift/origin/pkg/authorization/api" _ "github.com/openshift/origin/pkg/build/api" @@ -19,6 +20,10 @@ import ( // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""} +// Codec is the identity codec for this package - it can only convert itself +// to itself. +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) + // Kind takes an unqualified kind and returns back a Group qualified GroupKind func Kind(kind string) unversioned.GroupKind { return SchemeGroupVersion.WithKind(kind).GroupKind() diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index 7ac1635183f0..159c95bbfb46 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/google/gofuzz" - "k8s.io/kubernetes/pkg/api" + kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/api/validation" @@ -147,7 +147,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se c.FuzzNoCustom(j) if j.To == nil { // To is defaulted to be not nil - j.To = &api.LocalObjectReference{} + j.To = &kapi.LocalObjectReference{} } }, func(j *image.ImageStreamImage, c fuzz.Continue) { @@ -221,7 +221,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se }, func(j *route.RouteSpec, c fuzz.Continue) { c.FuzzNoCustom(j) - j.To = api.ObjectReference{ + j.To = kapi.ObjectReference{ Kind: "Service", Name: j.To.Name, } @@ -299,7 +299,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se j.From.Kind = "DockerImage" j.From.Name = specs[c.Intn(len(specs))] }, - func(j *api.PodSecurityContext, c fuzz.Continue) { + func(j *kapi.PodSecurityContext, c fuzz.Continue) { c.FuzzNoCustom(j) if forVersion == "v1beta3" { // v1beta3 does not contain the PodSecurityContext type. For this API version, only fuzz @@ -312,7 +312,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se j.FSGroup = nil } }, - func(j *api.GitRepoVolumeSource, c fuzz.Continue) { + func(j *kapi.GitRepoVolumeSource, c fuzz.Continue) { c.FuzzNoCustom(j) if forVersion == "v1beta3" { // these fields are set to their empty state when testing v1beta3 @@ -320,7 +320,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se j.Directory = "" } }, - func(j *api.ISCSIVolumeSource, c fuzz.Continue) { + func(j *kapi.ISCSIVolumeSource, c fuzz.Continue) { c.FuzzNoCustom(j) if forVersion == "v1beta3" { // these fields are set to their empty state when testing v1beta3 @@ -331,7 +331,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se j.ISCSIInterface = "default" } }, - func(j *api.Event, c fuzz.Continue) { + func(j *kapi.Event, c fuzz.Continue) { c.FuzzNoCustom(j) if forVersion == "v1beta3" { // these fields are set to their empty state when testing v1beta3 @@ -339,7 +339,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se j.Type = "" } }, - func(j *api.Probe, c fuzz.Continue) { + func(j *kapi.Probe, c fuzz.Continue) { c.FuzzNoCustom(j) if forVersion == "v1beta3" { // these fields are set to their empty state when testing v1beta3 @@ -381,7 +381,7 @@ func fuzzInternalObject(t *testing.T, forVersion string, item runtime.Object, se func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) { // Make a copy of the originalItem to give to conversion functions // This lets us know if conversion messed with the input object - deepCopy, err := api.Scheme.DeepCopy(originalItem) + deepCopy, err := kapi.Scheme.DeepCopy(originalItem) if err != nil { t.Errorf("Could not copy object: %v", err) return @@ -406,13 +406,13 @@ func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) { } if reflect.TypeOf(item) != reflect.TypeOf(obj2) { obj2conv := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) - if err := api.Scheme.Convert(obj2, obj2conv); err != nil { + if err := kapi.Scheme.Convert(obj2, obj2conv); err != nil { t.Errorf("0X: no conversion from %v to %v: %v", reflect.TypeOf(item), reflect.TypeOf(obj2), err) return } obj2 = obj2conv } - if !api.Semantic.DeepEqual(originalItem, obj2) { + if !kapi.Semantic.DeepEqual(originalItem, obj2) { t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %s", name, util.ObjectDiff(originalItem, obj2), codec, string(data), util.ObjectGoPrintSideBySide(originalItem, obj2)) return } @@ -423,7 +423,7 @@ func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) { t.Errorf("2: %v: %v", name, err) return } - if !api.Semantic.DeepEqual(originalItem, obj3) { + if !kapi.Semantic.DeepEqual(originalItem, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(originalItem, obj3), codec) return } @@ -440,11 +440,11 @@ const fuzzIters = 20 // For debugging problems func TestSpecificKind(t *testing.T) { - api.Scheme.Log(t) - defer api.Scheme.Log(nil) + kapi.Scheme.Log(t) + defer kapi.Scheme.Log(nil) kind := "DeploymentConfig" - item, err := api.Scheme.New("", kind) + item, err := kapi.Scheme.New(osapi.SchemeGroupVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) return @@ -468,7 +468,7 @@ var nonInternalRoundTrippableTypes = sets.NewString("List", "ListOptions", "PodE // TestTypes will try to roundtrip all OpenShift and Kubernetes stable api types func TestTypes(t *testing.T) { - for kind, reflectType := range api.Scheme.KnownTypes("") { + for kind, reflectType := range kapi.Scheme.KnownTypes(osapi.SchemeGroupVersion) { if !strings.Contains(reflectType.PkgPath(), "/origin/") && reflectType.PkgPath() != "k8s.io/kubernetes/pkg/api" { continue } @@ -477,7 +477,7 @@ func TestTypes(t *testing.T) { } // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { - item, err := api.Scheme.New("", kind) + item, err := kapi.Scheme.New(osapi.SchemeGroupVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue @@ -491,7 +491,7 @@ func TestTypes(t *testing.T) { for _, v := range versions { t.Logf("About to test %v with %q", kind, v) fuzzInternalObject(t, v, item, seed) - roundTrip(t, runtime.CodecFor(api.Scheme, v), item) + roundTrip(t, runtime.CodecFor(kapi.Scheme, v), item) } continue } diff --git a/pkg/api/validation/coverage_test.go b/pkg/api/validation/coverage_test.go index d3b9a161f28b..5629861a105a 100644 --- a/pkg/api/validation/coverage_test.go +++ b/pkg/api/validation/coverage_test.go @@ -7,6 +7,7 @@ import ( kapi "k8s.io/kubernetes/pkg/api" + "github.com/openshift/origin/pkg/api" authorizationapi "github.com/openshift/origin/pkg/authorization/api" buildapi "github.com/openshift/origin/pkg/build/api" deployapi "github.com/openshift/origin/pkg/deploy/api" @@ -35,7 +36,7 @@ var MissingValidationExceptions = []reflect.Type{ } func TestCoverage(t *testing.T) { - for kind, apiType := range kapi.Scheme.KnownTypes("") { + for kind, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) { if !strings.Contains(apiType.PkgPath(), "openshift/origin") { continue } diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index f3321db3d66f..5c6fc771d9bb 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -118,12 +118,12 @@ func (v *RuntimeObjectsValidator) getSpecificValidationInfo(obj runtime.Object) } func GetRequiresNamespace(obj runtime.Object) (bool, error) { - version, kind, err := kapi.Scheme.ObjectVersionAndKind(obj) + groupVersionKind, err := kapi.Scheme.ObjectKind(obj) if err != nil { return false, err } - restMapping, err := latest.RESTMapper.RESTMapping(kind, version) + restMapping, err := latest.RESTMapper.RESTMapping(groupVersionKind.GroupKind()) if err != nil { return false, err } diff --git a/pkg/build/admission/admission.go b/pkg/build/admission/admission.go index 5c42ce0b5364..5827cf0097eb 100644 --- a/pkg/build/admission/admission.go +++ b/pkg/build/admission/admission.go @@ -38,9 +38,9 @@ func NewBuildByStrategy() admission.Interface { } } -const ( - buildsResource = "builds" - buildConfigsResource = "buildconfigs" +var ( + buildsResource = buildapi.Resource("builds") + buildConfigsResource = buildapi.Resource("buildconfigs") ) func (a *buildByStrategy) Admit(attr admission.Attributes) error { diff --git a/pkg/build/admission/admission_test.go b/pkg/build/admission/admission_test.go index 982ac7e30e25..cc0e4950b7f6 100644 --- a/pkg/build/admission/admission_test.go +++ b/pkg/build/admission/admission_test.go @@ -7,6 +7,7 @@ import ( "k8s.io/kubernetes/pkg/admission" kapi "k8s.io/kubernetes/pkg/api" apierrors "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/auth/user" ktestclient "k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/runtime" @@ -21,8 +22,8 @@ import ( func TestBuildAdmission(t *testing.T) { tests := []struct { name string - kind string - resource string + kind unversioned.GroupKind + resource unversioned.GroupResource subResource string object runtime.Object responseObject runtime.Object @@ -34,7 +35,7 @@ func TestBuildAdmission(t *testing.T) { { name: "allowed source build", object: testBuild(buildapi.BuildStrategy{SourceStrategy: &buildapi.SourceBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, reviewResponse: reviewResponse(true, ""), expectedResource: authorizationapi.SourceBuildResource, @@ -44,7 +45,7 @@ func TestBuildAdmission(t *testing.T) { name: "allowed source build clone", object: testBuildRequest("buildname"), responseObject: testBuild(buildapi.BuildStrategy{SourceStrategy: &buildapi.SourceBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, subResource: "clone", reviewResponse: reviewResponse(true, ""), @@ -54,7 +55,7 @@ func TestBuildAdmission(t *testing.T) { { name: "denied docker build", object: testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, reviewResponse: reviewResponse(false, "cannot create build of type docker build"), expectAccept: false, @@ -64,7 +65,7 @@ func TestBuildAdmission(t *testing.T) { name: "denied docker build clone", object: testBuildRequest("buildname"), responseObject: testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, subResource: "clone", reviewResponse: reviewResponse(false, "cannot create build of type docker build"), @@ -74,7 +75,7 @@ func TestBuildAdmission(t *testing.T) { { name: "allowed custom build", object: testBuild(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, reviewResponse: reviewResponse(true, ""), expectedResource: authorizationapi.CustomBuildResource, @@ -83,7 +84,7 @@ func TestBuildAdmission(t *testing.T) { { name: "allowed build config", object: testBuildConfig(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}), - kind: "BuildConfig", + kind: buildapi.Kind("BuildConfig"), resource: buildConfigsResource, reviewResponse: reviewResponse(true, ""), expectAccept: true, @@ -93,7 +94,7 @@ func TestBuildAdmission(t *testing.T) { name: "allowed build config instantiate", responseObject: testBuildConfig(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}), object: testBuildRequest("buildname"), - kind: "BuildConfig", + kind: buildapi.Kind("Build"), resource: buildConfigsResource, subResource: "instantiate", reviewResponse: reviewResponse(true, ""), @@ -103,7 +104,7 @@ func TestBuildAdmission(t *testing.T) { { name: "forbidden build config", object: testBuildConfig(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}), - kind: "BuildConfig", + kind: buildapi.Kind("Build"), resource: buildConfigsResource, reviewResponse: reviewResponse(false, ""), expectAccept: false, @@ -113,7 +114,7 @@ func TestBuildAdmission(t *testing.T) { name: "forbidden build config instantiate", responseObject: testBuildConfig(buildapi.BuildStrategy{CustomStrategy: &buildapi.CustomBuildStrategy{}}), object: testBuildRequest("buildname"), - kind: "BuildConfig", + kind: buildapi.Kind("Build"), resource: buildConfigsResource, subResource: "instantiate", reviewResponse: reviewResponse(false, ""), @@ -123,7 +124,7 @@ func TestBuildAdmission(t *testing.T) { { name: "unrecognized request object", object: &fakeObject{}, - kind: "BuildConfig", + kind: buildapi.Kind("BuildConfig"), resource: buildConfigsResource, reviewResponse: reviewResponse(true, ""), expectAccept: false, @@ -132,7 +133,7 @@ func TestBuildAdmission(t *testing.T) { { name: "details on forbidden docker build", object: testBuild(buildapi.BuildStrategy{DockerStrategy: &buildapi.DockerBuildStrategy{}}), - kind: "Build", + kind: buildapi.Kind("Build"), resource: buildsResource, subResource: "details", reviewResponse: reviewResponse(false, "cannot create build of type docker build"), diff --git a/pkg/build/controller/strategy/sti.go b/pkg/build/controller/strategy/sti.go index eba59d158c1d..59f847640918 100644 --- a/pkg/build/controller/strategy/sti.go +++ b/pkg/build/controller/strategy/sti.go @@ -128,7 +128,7 @@ func (bs *SourceBuildStrategy) canRunAsRoot(build *buildapi.Build) bool { }, } userInfo := serviceaccount.UserInfo(build.Namespace, build.Spec.ServiceAccount, "") - attrs := admission.NewAttributesRecord(pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, userInfo) + attrs := admission.NewAttributesRecord(pod, kapi.Kind("Pod"), pod.Namespace, pod.Name, kapi.Resource("pods"), "", admission.Create, userInfo) err := bs.AdmissionControl.Admit(attrs) if err != nil { glog.V(2).Infof("Admit for root user returned error: %v", err) diff --git a/pkg/client/client.go b/pkg/client/client.go index 22ff0ff28aed..6c7658087d13 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -268,17 +268,18 @@ func SetOpenShiftDefaults(config *kclient.Config) error { if len(config.UserAgent) == 0 { config.UserAgent = DefaultOpenShiftUserAgent() } - if config.Version == "" { + if config.GroupVersion == nil { // Clients default to the preferred code API version - config.Version = latest.Version + groupVersionCopy := latest.Version + config.GroupVersion = &groupVersionCopy } if config.Prefix == "" { config.Prefix = "/oapi" } - version := config.Version - versionInterfaces, err := latest.InterfacesFor(version) + version := config.GroupVersion + versionInterfaces, err := latest.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 %q is not recognized (valid values: %v)", version, latest.Versions) } if config.Codec == nil { config.Codec = versionInterfaces.Codec diff --git a/pkg/client/scale.go b/pkg/client/scale.go index 41e1a145dadd..6952566e9df4 100644 --- a/pkg/client/scale.go +++ b/pkg/client/scale.go @@ -3,10 +3,11 @@ package client import ( "fmt" - "github.com/openshift/origin/pkg/api/latest" "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/apis/extensions" kclient "k8s.io/kubernetes/pkg/client/unversioned" + + "github.com/openshift/origin/pkg/api/latest" ) type delegatingScaleInterface struct { @@ -38,7 +39,8 @@ func (c *delegatingScaleInterface) Get(kind string, name string) (result *extens switch { case kind == "DeploymentConfig": return c.dcs.GetScale(name) - case latest.OriginKind(kind, ""): + // TODO: This is borked because the interface for Get is broken. Kind is insufficient. + case latest.IsKindInAnyOriginGroup(kind): return nil, errors.NewBadRequest(fmt.Sprintf("Kind %s has no Scale subresource", kind)) default: return c.scales.Get(kind, name) @@ -51,7 +53,8 @@ func (c *delegatingScaleInterface) Update(kind string, scale *extensions.Scale) switch { case kind == "DeploymentConfig": return c.dcs.UpdateScale(scale) - case latest.OriginKind(kind, ""): + // TODO: This is borked because the interface for Update is broken. Kind is insufficient. + case latest.IsKindInAnyOriginGroup(kind): return nil, errors.NewBadRequest(fmt.Sprintf("Kind %s has no Scale subresource", kind)) default: return c.scales.Update(kind, scale) diff --git a/pkg/cmd/admin/node/node_options.go b/pkg/cmd/admin/node/node_options.go index 2e65ace17a89..e1f2ac772a9e 100644 --- a/pkg/cmd/admin/node/node_options.go +++ b/pkg/cmd/admin/node/node_options.go @@ -11,6 +11,7 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/kubectl" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -155,23 +156,23 @@ func (n *NodeOptions) GetNodes() ([]*kapi.Node, error) { } func (n *NodeOptions) GetPrintersByObject(obj runtime.Object) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) { - version, kind, err := kapi.Scheme.ObjectVersionAndKind(obj) + gvk, err := kapi.Scheme.ObjectKind(obj) if err != nil { return nil, nil, err } - return n.GetPrinters(kind, version) + return n.GetPrinters(gvk) } func (n *NodeOptions) GetPrintersByResource(resource string) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) { - version, kind, err := n.Mapper.VersionAndKindForResource(resource) + gvk, err := n.Mapper.KindFor(resource) if err != nil { return nil, nil, err } - return n.GetPrinters(kind, version) + return n.GetPrinters(gvk) } -func (n *NodeOptions) GetPrinters(kind, version string) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) { - mapping, err := n.Mapper.RESTMapping(kind, version) +func (n *NodeOptions) GetPrinters(gvk unversioned.GroupVersionKind) (kubectl.ResourcePrinter, kubectl.ResourcePrinter, error) { + mapping, err := n.Mapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { return nil, nil, err } diff --git a/pkg/cmd/cli/cmd/edit.go b/pkg/cmd/cli/cmd/edit.go index 0ee43c103816..6e8789f43298 100644 --- a/pkg/cmd/cli/cmd/edit.go +++ b/pkg/cmd/cli/cmd/edit.go @@ -37,7 +37,7 @@ type EditOptions struct { ext string filenames []string - version string + version unversioned.GroupVersion fullName string } @@ -145,8 +145,8 @@ func (o *EditOptions) Complete(fullName string, f *clientcmd.Factory, out io.Wri return err } - o.version = cmdutil.OutputVersion(cmd, clientConfig.Version) - return nil + o.version, err = cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + return err } // RunEdit contains all the necessary functionality for the OpenShift cli edit command. @@ -158,7 +158,7 @@ func (o *EditOptions) RunEdit() error { return err } for { - obj, err := resource.AsVersionedObject(infos, false, o.version) + obj, err := resource.AsVersionedObject(infos, false, o.version.String()) if err != nil { return preservedFile(err, results.file, o.out) } @@ -332,7 +332,7 @@ type editResults struct { file string delta *jsonmerge.Delta - version string + version unversioned.GroupVersion } func (r *editResults) AddError(err error, info *resource.Info) string { @@ -340,7 +340,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string { case errors.IsInvalid(err): r.edit = append(r.edit, info) reason := editReason{ - head: fmt.Sprintf("%s %s was not valid", info.Mapping.Kind, info.Name), + head: fmt.Sprintf("%s %s was not valid", info.Mapping.GroupVersionKind.Kind, info.Name), } if err, ok := err.(errors.APIStatus); ok { if details := err.Status().Details; details != nil { @@ -350,15 +350,15 @@ func (r *editResults) AddError(err error, info *resource.Info) string { } } r.header.reasons = append(r.header.reasons, reason) - return fmt.Sprintf("Error: the %s %s is invalid", info.Mapping.Kind, info.Name) + return fmt.Sprintf("Error: the %s %s is invalid", info.Mapping.GroupVersionKind.Kind, info.Name) case errors.IsNotFound(err): r.notfound++ - return fmt.Sprintf("Error: the %s %s has been deleted on the server", info.Mapping.Kind, info.Name) + return fmt.Sprintf("Error: the %s %s has been deleted on the server", info.Mapping.GroupVersionKind.Kind, info.Name) case errors.IsConflict(err): if r.delta != nil { v1 := info.ResourceVersion - if perr := applyPatch(r.delta, info, r.version); perr != nil { + if perr := applyPatch(r.delta, info, r.version.String()); perr != nil { // the error was related to the patching process if nerr, ok := perr.(patchError); ok { r.conflict++ @@ -368,7 +368,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string { // the patch is in conflict, report to user and exit if jsonmerge.IsConflicting(nerr.error) { // TODO: read message - return fmt.Sprintf("Error: a conflicting change was made to the %s %s on the server", info.Mapping.Kind, info.Name) + return fmt.Sprintf("Error: a conflicting change was made to the %s %s on the server", info.Mapping.GroupVersionKind.Kind, info.Name) } glog.V(4).Infof("Attempted to patch the resource, but failed: %v", perr) return fmt.Sprintf("Error: %v", err) @@ -384,7 +384,7 @@ func (r *editResults) AddError(err error, info *resource.Info) string { return fmt.Sprintf("Error: %v", err) default: r.retryable++ - return fmt.Sprintf("Error: the %s %s could not be updated: %v", info.Mapping.Kind, info.Name, err) + return fmt.Sprintf("Error: the %s %s could not be updated: %v", info.Mapping.GroupVersionKind.Kind, info.Name, err) } } diff --git a/pkg/cmd/cli/cmd/env.go b/pkg/cmd/cli/cmd/env.go index 279aca874edc..a298ad4d70fe 100644 --- a/pkg/cmd/cli/cmd/env.go +++ b/pkg/cmd/cli/cmd/env.go @@ -235,12 +235,12 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman } // Keep a copy of the original objects prior to updating their environment. // Used in constructing the patch(es) that will be applied in the server. - oldObjects, err := resource.AsVersionedObjects(infos, clientConfig.Version) + oldObjects, err := resource.AsVersionedObjects(infos, clientConfig.GroupVersion.String()) if err != nil { return err } if len(oldObjects) != len(infos) { - return fmt.Errorf("could not convert all objects to API version %q", clientConfig.Version) + return fmt.Errorf("could not convert all objects to API version %q", clientConfig.GroupVersion) } oldData := make([][]byte, len(infos)) for i := range oldObjects { @@ -294,8 +294,11 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman } if len(outputFormat) != 0 { - outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version) - objects, err := resource.AsVersionedObjects(infos, outputVersion) + outputVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return err + } + objects, err := resource.AsVersionedObjects(infos, outputVersion.String()) if err != nil { return err } @@ -314,12 +317,12 @@ func RunEnv(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Comman return nil } - objects, err := resource.AsVersionedObjects(infos, clientConfig.Version) + objects, err := resource.AsVersionedObjects(infos, clientConfig.GroupVersion.String()) if err != nil { return err } if len(objects) != len(infos) { - return fmt.Errorf("could not convert all objects to API version %q", clientConfig.Version) + return fmt.Errorf("could not convert all objects to API version %q", clientConfig.GroupVersion) } failed := false diff --git a/pkg/cmd/cli/cmd/export.go b/pkg/cmd/cli/cmd/export.go index fa4f216541f8..ee21f895b5f2 100644 --- a/pkg/cmd/cli/cmd/export.go +++ b/pkg/cmd/cli/cmd/export.go @@ -92,7 +92,10 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri if err != nil { return err } - outputVersion := cmdutil.OutputVersion(cmd, clientConfig.Version) + outputVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return err + } cmdNamespace, explicit, err := f.DefaultNamespace() if err != nil { @@ -137,7 +140,7 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri var result runtime.Object if len(asTemplate) > 0 { - objects, err := resource.AsVersionedObjects(infos, outputVersion) + objects, err := resource.AsVersionedObjects(infos, outputVersion.String()) if err != nil { return err } @@ -145,12 +148,12 @@ func RunExport(f *clientcmd.Factory, exporter Exporter, in io.Reader, out io.Wri Objects: objects, } template.Name = asTemplate - result, err = kapi.Scheme.ConvertToVersion(template, outputVersion) + result, err = kapi.Scheme.ConvertToVersion(template, outputVersion.String()) if err != nil { return err } } else { - object, err := resource.AsVersionedObject(infos, !one, outputVersion) + object, err := resource.AsVersionedObject(infos, !one, outputVersion.String()) if err != nil { return err } diff --git a/pkg/cmd/cli/cmd/expose.go b/pkg/cmd/cli/cmd/expose.go index 3baa71f1b321..1a9021d8c176 100644 --- a/pkg/cmd/cli/cmd/expose.go +++ b/pkg/cmd/cli/cmd/expose.go @@ -92,8 +92,8 @@ func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error { mapping := info.ResourceMapping() generator := cmdutil.GetFlagString(cmd, "generator") - switch mapping.Kind { - case "Service": + switch mapping.GroupVersionKind.GroupKind() { + case kapi.Kind("Service"): switch generator { case "service/v1", "service/v2": // Set default protocol back for generating services @@ -135,7 +135,7 @@ func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error { default: switch generator { case "route/v1": - return fmt.Errorf("cannot expose a %s as a route", mapping.Kind) + return fmt.Errorf("cannot expose a %s as a route", mapping.GroupVersionKind.Kind) case "": // Default exposing everything except services as a service generator = "service/v2" diff --git a/pkg/cmd/cli/cmd/loginoptions.go b/pkg/cmd/cli/cmd/loginoptions.go index ce2c1036c6ab..0f45f52c699d 100644 --- a/pkg/cmd/cli/cmd/loginoptions.go +++ b/pkg/cmd/cli/cmd/loginoptions.go @@ -38,7 +38,7 @@ type LoginOptions struct { Server string CAFile string InsecureTLS bool - APIVersion string + APIVersion unversioned.GroupVersion // flags and printing helpers Username string @@ -166,8 +166,8 @@ func (o *LoginOptions) getClientConfig() (*kclient.Config, error) { } // check for matching api version - if len(o.APIVersion) > 0 { - clientConfig.Version = o.APIVersion + if !o.APIVersion.IsEmpty() { + clientConfig.GroupVersion = &o.APIVersion } o.Config = clientConfig diff --git a/pkg/cmd/cli/cmd/logs.go b/pkg/cmd/cli/cmd/logs.go index 88d916de21fb..8ee1b40a4c6a 100644 --- a/pkg/cmd/cli/cmd/logs.go +++ b/pkg/cmd/cli/cmd/logs.go @@ -109,7 +109,7 @@ func (o *OpenShiftLogsOptions) Complete(f *clientcmd.Factory, out io.Writer, cmd } version := cmdutil.GetFlagInt64(cmd, "version") - _, resource := meta.KindToResource(infos[0].Mapping.Kind, false) + _, resource := meta.KindToResource(infos[0].Mapping.GroupVersionKind.Kind, false) // TODO: podLogOptions should be included in our own logOptions objects. switch resource { diff --git a/pkg/cmd/cli/cmd/newapp.go b/pkg/cmd/cli/cmd/newapp.go index 18a72dab5f4a..93f1273a7b1c 100644 --- a/pkg/cmd/cli/cmd/newapp.go +++ b/pkg/cmd/cli/cmd/newapp.go @@ -510,7 +510,7 @@ func retryBuildConfig(info *resource.Info, err error) runtime.Object { buildapi.GenericWebHookBuildTriggerType: {}, buildapi.ImageChangeBuildTriggerType: {}, } - if info.Mapping.Kind == "BuildConfig" && isInvalidTriggerError(err) { + if info.Mapping.GroupVersionKind.GroupKind() == buildapi.Kind("BuildConfig") && isInvalidTriggerError(err) { bc, ok := info.Object.(*buildapi.BuildConfig) if !ok { return nil diff --git a/pkg/cmd/cli/cmd/process.go b/pkg/cmd/cli/cmd/process.go index 7383ae6f1695..751e7e8fc532 100644 --- a/pkg/cmd/cli/cmd/process.go +++ b/pkg/cmd/cli/cmd/process.go @@ -117,8 +117,8 @@ func RunProcess(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args [] mapping *meta.RESTMapping ) - version, kind, err := mapper.VersionAndKindForResource("template") - if mapping, err = mapper.RESTMapping(kind, version); err != nil { + gvk, err := mapper.KindFor("template") + if mapping, err = mapper.RESTMapping(gvk.GroupKind(), gvk.Version); err != nil { return err } @@ -238,7 +238,12 @@ func RunProcess(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args [] if err != nil { return err } - p = kubectl.NewVersionedPrinter(p, kapi.Scheme, kcmdutil.OutputVersion(cmd, mapping.APIVersion)) + gv := mapping.GroupVersionKind.GroupVersion() + version, err := kcmdutil.OutputVersion(cmd, &gv) + if err != nil { + return err + } + p = kubectl.NewVersionedPrinter(p, kapi.Scheme, version) // use generic output if kcmdutil.GetFlagBool(cmd, "raw") { diff --git a/pkg/cmd/cli/cmd/startbuild.go b/pkg/cmd/cli/cmd/startbuild.go index 3f649d751fbf..dbc1c4a1f530 100644 --- a/pkg/cmd/cli/cmd/startbuild.go +++ b/pkg/cmd/cli/cmd/startbuild.go @@ -540,7 +540,7 @@ func RunStartBuildWebHook(f *clientcmd.Factory, out io.Writer, webhook string, p if hook.Scheme == "https" { config, err := f.OpenShiftClientConfig.ClientConfig() if err == nil { - if url, err := client.DefaultServerURL(config.Host, "", "test", true); err == nil { + if url, err := client.DefaultServerURL(config.Host, "", unversioned.GroupVersion{}, true); err == nil { if url.Host == hook.Host && url.Scheme == hook.Scheme { if rt, err := client.TransportFor(config); err == nil { httpClient = &http.Client{Transport: rt} diff --git a/pkg/cmd/cli/cmd/tag.go b/pkg/cmd/cli/cmd/tag.go index c958d2c856a7..fef2714656e4 100644 --- a/pkg/cmd/cli/cmd/tag.go +++ b/pkg/cmd/cli/cmd/tag.go @@ -104,9 +104,9 @@ func parseStreamName(defaultNamespace, name string) (string, string, error) { func determineSourceKind(f *clientcmd.Factory, input string) string { mapper, _ := f.Object() - _, kind, err := mapper.VersionAndKindForResource(input) + gvk, err := mapper.KindFor(input) if err == nil { - return kind + return gvk.Kind } // DockerImage isn't in RESTMapper diff --git a/pkg/cmd/cli/cmd/volume.go b/pkg/cmd/cli/cmd/volume.go index 5b46b5c32b27..daeddfd8a25c 100644 --- a/pkg/cmd/cli/cmd/volume.go +++ b/pkg/cmd/cli/cmd/volume.go @@ -15,6 +15,7 @@ import ( apierrs "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/meta" kresource "k8s.io/kubernetes/pkg/api/resource" + "k8s.io/kubernetes/pkg/api/unversioned" kclient "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/kubectl" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -111,7 +112,7 @@ type VolumeOptions struct { Containers string Confirm bool Output string - OutputVersion string + OutputVersion unversioned.GroupVersion // Add op params AddOpts *AddVolumeOptions @@ -299,7 +300,10 @@ func (v *VolumeOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, out, if err != nil { return err } - v.OutputVersion = kcmdutil.OutputVersion(cmd, clientConfig.Version) + v.OutputVersion, err = kcmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return err + } _, kc, err := f.Clients() if err != nil { return err @@ -370,7 +374,7 @@ func (v *VolumeOptions) RunVolume(args []string) error { // if a claim should be created, generate the info we'll add to the flow if v.Add && v.AddOpts.CreateClaim { claim := v.AddOpts.createClaim() - m, err := v.Mapper.RESTMapping("PersistentVolumeClaim") + m, err := v.Mapper.RESTMapping(kapi.Kind("PersistentVolumeClaim")) if err != nil { return err } @@ -424,7 +428,7 @@ func (v *VolumeOptions) RunVolume(args []string) error { return nil } - objects, err := resource.AsVersionedObject(infos, false, v.OutputVersion) + objects, err := resource.AsVersionedObject(infos, false, v.OutputVersion.String()) if err != nil { return err } diff --git a/pkg/cmd/cli/config/smart_merge.go b/pkg/cmd/cli/config/smart_merge.go index c22a369ab483..0eaf790488ff 100644 --- a/pkg/cmd/cli/config/smart_merge.go +++ b/pkg/cmd/cli/config/smart_merge.go @@ -124,7 +124,9 @@ func CreateConfig(namespace string, clientCfg *client.Config) (*clientcmdapi.Con cluster.CertificateAuthorityData = clientCfg.CAData } cluster.InsecureSkipTLSVerify = clientCfg.Insecure - cluster.APIVersion = clientCfg.Version + if clientCfg.GroupVersion != nil { + cluster.APIVersion = clientCfg.GroupVersion.String() + } config.Clusters[clusterNick] = cluster context := clientcmdapi.NewContext() diff --git a/pkg/cmd/cli/describe/describer.go b/pkg/cmd/cli/describe/describer.go index 803161013b2d..8b5281fdc2a8 100644 --- a/pkg/cmd/cli/describe/describer.go +++ b/pkg/cmd/cli/describe/describer.go @@ -26,35 +26,38 @@ import ( buildapi "github.com/openshift/origin/pkg/build/api" buildutil "github.com/openshift/origin/pkg/build/util" "github.com/openshift/origin/pkg/client" + deployapi "github.com/openshift/origin/pkg/deploy/api" imageapi "github.com/openshift/origin/pkg/image/api" projectapi "github.com/openshift/origin/pkg/project/api" + routeapi "github.com/openshift/origin/pkg/route/api" templateapi "github.com/openshift/origin/pkg/template/api" + userapi "github.com/openshift/origin/pkg/user/api" ) -func describerMap(c *client.Client, kclient kclient.Interface, host string) map[string]kctl.Describer { - m := map[string]kctl.Describer{ - "Build": &BuildDescriber{c, kclient}, - "BuildConfig": &BuildConfigDescriber{c, host}, - "DeploymentConfig": NewDeploymentConfigDescriber(c, kclient), - "Identity": &IdentityDescriber{c}, - "Image": &ImageDescriber{c}, - "ImageStream": &ImageStreamDescriber{c}, - "ImageStreamTag": &ImageStreamTagDescriber{c}, - "ImageStreamImage": &ImageStreamImageDescriber{c}, - "Route": &RouteDescriber{c, kclient}, - "Project": &ProjectDescriber{c, kclient}, - "Template": &TemplateDescriber{c, meta.NewAccessor(), kapi.Scheme, nil}, - "Policy": &PolicyDescriber{c}, - "PolicyBinding": &PolicyBindingDescriber{c}, - "RoleBinding": &RoleBindingDescriber{c}, - "Role": &RoleDescriber{c}, - "ClusterPolicy": &ClusterPolicyDescriber{c}, - "ClusterPolicyBinding": &ClusterPolicyBindingDescriber{c}, - "ClusterRoleBinding": &ClusterRoleBindingDescriber{c}, - "ClusterRole": &ClusterRoleDescriber{c}, - "User": &UserDescriber{c}, - "Group": &GroupDescriber{c.Groups()}, - "UserIdentityMapping": &UserIdentityMappingDescriber{c}, +func describerMap(c *client.Client, kclient kclient.Interface, host string) map[unversioned.GroupKind]kctl.Describer { + m := map[unversioned.GroupKind]kctl.Describer{ + buildapi.Kind("Build"): &BuildDescriber{c, kclient}, + buildapi.Kind("BuildConfig"): &BuildConfigDescriber{c, host}, + deployapi.Kind("DeploymentConfig"): NewDeploymentConfigDescriber(c, kclient), + authorizationapi.Kind("Identity"): &IdentityDescriber{c}, + imageapi.Kind("Image"): &ImageDescriber{c}, + imageapi.Kind("ImageStream"): &ImageStreamDescriber{c}, + imageapi.Kind("ImageStreamTag"): &ImageStreamTagDescriber{c}, + imageapi.Kind("ImageStreamImage"): &ImageStreamImageDescriber{c}, + routeapi.Kind("Route"): &RouteDescriber{c, kclient}, + projectapi.Kind("Project"): &ProjectDescriber{c, kclient}, + templateapi.Kind("Template"): &TemplateDescriber{c, meta.NewAccessor(), kapi.Scheme, nil}, + authorizationapi.Kind("Policy"): &PolicyDescriber{c}, + authorizationapi.Kind("PolicyBinding"): &PolicyBindingDescriber{c}, + authorizationapi.Kind("RoleBinding"): &RoleBindingDescriber{c}, + authorizationapi.Kind("Role"): &RoleDescriber{c}, + authorizationapi.Kind("ClusterPolicy"): &ClusterPolicyDescriber{c}, + authorizationapi.Kind("ClusterPolicyBinding"): &ClusterPolicyBindingDescriber{c}, + authorizationapi.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{c}, + authorizationapi.Kind("ClusterRole"): &ClusterRoleDescriber{c}, + userapi.Kind("User"): &UserDescriber{c}, + userapi.Kind("Group"): &GroupDescriber{c.Groups()}, + userapi.Kind("UserIdentityMapping"): &UserIdentityMappingDescriber{c}, } return m } @@ -65,14 +68,14 @@ func DescribableResources() []string { keys := kctl.DescribableResources() for k := range describerMap(nil, nil, "") { - resource := strings.ToLower(k) + resource := strings.ToLower(k.Kind) keys = append(keys, resource) } return keys } // DescriberFor returns a describer for a given kind of resource -func DescriberFor(kind string, c *client.Client, kclient kclient.Interface, host string) (kctl.Describer, bool) { +func DescriberFor(kind unversioned.GroupKind, c *client.Client, kclient kclient.Interface, host string) (kctl.Describer, bool) { f, ok := describerMap(c, kclient, host)[kind] if ok { return f, true @@ -807,10 +810,10 @@ func (d *TemplateDescriber) describeObjects(objects []runtime.Object, out *tabwr continue } - _, kind, _ := d.ObjectTyper.ObjectVersionAndKind(obj) + gvk, _ := d.ObjectTyper.ObjectKind(obj) meta := kapi.ObjectMeta{} meta.Name, _ = d.MetadataAccessor.Name(obj) - fmt.Fprintf(out, fmt.Sprintf("%s%s\t%s\n", indent, kind, meta.Name)) + fmt.Fprintf(out, fmt.Sprintf("%s%s\t%s\n", indent, gvk.Kind, meta.Name)) //meta.Annotations, _ = d.MetadataAccessor.Annotations(obj) //meta.Labels, _ = d.MetadataAccessor.Labels(obj) /*if len(meta.Labels) > 0 { @@ -1043,7 +1046,7 @@ func describePolicyRule(out *tabwriter.Writer, rule authorizationapi.PolicyRule, extensionString = fmt.Sprintf("%#v", rule.AttributeRestrictions.Object) buffer := new(bytes.Buffer) - printer := NewHumanReadablePrinter(true, false, false, false, []string{}) + printer := NewHumanReadablePrinter(true, false, false, false, false, []string{}) if err := printer.PrintObj(rule.AttributeRestrictions.Object, buffer); err == nil { extensionString = strings.TrimSpace(buffer.String()) } diff --git a/pkg/cmd/cli/describe/describer_test.go b/pkg/cmd/cli/describe/describer_test.go index ecf0f0fbe976..e9fee4d56379 100644 --- a/pkg/cmd/cli/describe/describer_test.go +++ b/pkg/cmd/cli/describe/describer_test.go @@ -12,6 +12,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/labels" + api "github.com/openshift/origin/pkg/api" authorizationapi "github.com/openshift/origin/pkg/authorization/api" buildapi "github.com/openshift/origin/pkg/build/api" "github.com/openshift/origin/pkg/client" @@ -75,7 +76,7 @@ func TestDescriberCoverage(t *testing.T) { c := &client.Client{} main: - for _, apiType := range kapi.Scheme.KnownTypes("") { + for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) { if !strings.Contains(apiType.PkgPath(), "openshift/origin") { continue } @@ -96,7 +97,7 @@ main: } } - _, ok := DescriberFor(apiType.Name(), c, &ktestclient.Fake{}, "") + _, ok := DescriberFor(api.SchemeGroupVersion.WithKind(apiType.Name()).GroupKind(), c, &ktestclient.Fake{}, "") if !ok { t.Errorf("missing printer for %v. Check pkg/cmd/cli/describe/describer.go", apiType) } diff --git a/pkg/cmd/cli/describe/printer_test.go b/pkg/cmd/cli/describe/printer_test.go index 1007c2fd3588..035dc0db4734 100644 --- a/pkg/cmd/cli/describe/printer_test.go +++ b/pkg/cmd/cli/describe/printer_test.go @@ -10,8 +10,10 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" + kctl "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/runtime" + "github.com/openshift/origin/pkg/api" authorizationapi "github.com/openshift/origin/pkg/authorization/api" buildapi "github.com/openshift/origin/pkg/build/api" deployapi "github.com/openshift/origin/pkg/deploy/api" @@ -57,7 +59,7 @@ func TestPrinterCoverage(t *testing.T) { printer := NewHumanReadablePrinter(false, false, false, false, false, []string{}) main: - for _, apiType := range kapi.Scheme.KnownTypes("") { + for _, apiType := range kapi.Scheme.KnownTypes(api.SchemeGroupVersion) { if !strings.Contains(apiType.PkgPath(), "openshift/origin") { continue } @@ -88,11 +90,10 @@ func TestPrintImageStream(t *testing.T) { streams := mockStreams() tests := []struct { - name string - stream *imageapi.ImageStream - withNamespace bool - expectedOut string - expectedErr error + name string + stream *imageapi.ImageStream + expectedOut string + expectedErr error }{ { name: "less than three tags", diff --git a/pkg/cmd/infra/deployer/deployer.go b/pkg/cmd/infra/deployer/deployer.go index 7248022f3bd1..cc741820ddfa 100644 --- a/pkg/cmd/infra/deployer/deployer.go +++ b/pkg/cmd/infra/deployer/deployer.go @@ -78,7 +78,7 @@ func NewCommandDeployer(name string) *cobra.Command { // NewDeployer makes a new Deployer from a kube client. func NewDeployer(client kclient.Interface) *Deployer { - scaler, _ := kubectl.ScalerFor("ReplicationController", client) + scaler, _ := kubectl.ScalerFor(kapi.Kind("ReplicationController"), client) return &Deployer{ getDeployment: func(namespace, name string) (*kapi.ReplicationController, error) { return client.ReplicationControllers(namespace).Get(name) diff --git a/pkg/cmd/server/admin/create_bootstrappolicy_file.go b/pkg/cmd/server/admin/create_bootstrappolicy_file.go index 788b7199cb8e..af48a7f8b2fb 100644 --- a/pkg/cmd/server/admin/create_bootstrappolicy_file.go +++ b/pkg/cmd/server/admin/create_bootstrappolicy_file.go @@ -100,7 +100,7 @@ func (o CreateBootstrapPolicyFileOptions) CreateBootstrapPolicyFile() error { policyTemplate.Objects = append(policyTemplate.Objects, &openshiftRoleBindings[i]) } - versionedPolicyTemplate, err := kapi.Scheme.ConvertToVersion(policyTemplate, latest.Version) + versionedPolicyTemplate, err := kapi.Scheme.ConvertToVersion(policyTemplate, latest.Version.String()) if err != nil { return err } diff --git a/pkg/cmd/server/admin/create_nodeconfig.go b/pkg/cmd/server/admin/create_nodeconfig.go index 528f795fffe4..c617339d8af4 100644 --- a/pkg/cmd/server/admin/create_nodeconfig.go +++ b/pkg/cmd/server/admin/create_nodeconfig.go @@ -431,7 +431,7 @@ func (o CreateNodeConfigOptions) MakeNodeJSON(nodeJSONFile string) error { node := &kapi.Node{} node.Name = o.NodeName - json, err := klatest.CodecForLegacyGroup().Encode(node) + json, err := klatest.GroupOrDie("").Codec.Encode(node) if err != nil { return err } diff --git a/pkg/cmd/server/admin/overwrite_bootstrappolicy.go b/pkg/cmd/server/admin/overwrite_bootstrappolicy.go index 5039d79c372e..d75ab3efea8d 100644 --- a/pkg/cmd/server/admin/overwrite_bootstrappolicy.go +++ b/pkg/cmd/server/admin/overwrite_bootstrappolicy.go @@ -10,6 +10,7 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/kubectl" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" @@ -228,7 +229,8 @@ func OverwriteBootstrapPolicy(storage storage.Interface, policyFile, createBoots // newStorage returns an EtcdHelper for the provided storage version. func newStorage(client *etcdclient.Client, version, prefix string) (oshelper storage.Interface, err error) { - interfaces, err := latest.InterfacesFor(version) + // TODO: this will need more care after the rebase + interfaces, err := latest.InterfacesFor(unversioned.GroupVersion{Group: "", Version: version}) if err != nil { return nil, err } diff --git a/pkg/cmd/server/api/types.go b/pkg/cmd/server/api/types.go index 39cf84143c98..d5c532dad5ad 100644 --- a/pkg/cmd/server/api/types.go +++ b/pkg/cmd/server/api/types.go @@ -4,8 +4,6 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/sets" - - "github.com/openshift/origin/pkg/api/latest" ) // A new entry shall be added to FeatureAliases for every change to following values. @@ -29,10 +27,10 @@ var ( KnownKubernetesStorageVersionLevels = []string{"v1", "v1beta3"} // KnownOpenShiftStorageVersionLevels are storage versions that can be dealt // with internally - KnownOpenShiftStorageVersionLevels = latest.Versions + KnownOpenShiftStorageVersionLevels = []string{"v1", "v1beta3"} // DefaultOpenShiftStorageVersionLevel is the default storage version for // resources. - DefaultOpenShiftStorageVersionLevel = latest.Versions[0] + DefaultOpenShiftStorageVersionLevel = "v1" // DeadKubernetesStorageVersionLevels are storage versions which shouldn't // be exposed externally. DeadKubernetesStorageVersionLevels = []string{"v1beta3"} diff --git a/pkg/cmd/server/api/v1/types_test.go b/pkg/cmd/server/api/v1/types_test.go index a4c526448bac..c0febd8479e8 100644 --- a/pkg/cmd/server/api/v1/types_test.go +++ b/pkg/cmd/server/api/v1/types_test.go @@ -354,8 +354,8 @@ type AdmissionPluginTestConfig struct { func (*AdmissionPluginTestConfig) IsAnAPIObject() {} func TestMasterConfig(t *testing.T) { - internal.Scheme.AddKnownTypes("v1", &AdmissionPluginTestConfig{}) - internal.Scheme.AddKnownTypes("", &AdmissionPluginTestConfig{}) + internal.Scheme.AddKnownTypes(SchemeGroupVersion, &AdmissionPluginTestConfig{}) + internal.Scheme.AddKnownTypes(internal.SchemeGroupVersion, &AdmissionPluginTestConfig{}) config := &internal.MasterConfig{ ServingInfo: internal.HTTPServingInfo{ ServingInfo: internal.ServingInfo{ diff --git a/pkg/cmd/server/origin/auth_config.go b/pkg/cmd/server/origin/auth_config.go index 58138911c794..3ae94cec172c 100644 --- a/pkg/cmd/server/origin/auth_config.go +++ b/pkg/cmd/server/origin/auth_config.go @@ -7,6 +7,7 @@ import ( "github.com/pborman/uuid" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/storage" "github.com/openshift/origin/pkg/auth/server/session" @@ -44,7 +45,8 @@ func BuildAuthConfig(options configapi.MasterConfig) (*AuthConfig, error) { if err != nil { return nil, err } - etcdHelper, err := NewEtcdStorage(client, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) + groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion} + etcdHelper, err := NewEtcdStorage(client, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } @@ -58,7 +60,7 @@ func BuildAuthConfig(options configapi.MasterConfig) (*AuthConfig, error) { if err != nil { return nil, err } - backendEtcdHelper, err := NewEtcdStorage(backendClient, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) + backendEtcdHelper, err := NewEtcdStorage(backendClient, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } diff --git a/pkg/cmd/server/origin/handlers.go b/pkg/cmd/server/origin/handlers.go index eb40495eb77e..0d4c524f6b4e 100644 --- a/pkg/cmd/server/origin/handlers.go +++ b/pkg/cmd/server/origin/handlers.go @@ -95,13 +95,13 @@ func (c *MasterConfig) authorizationFilter(handler http.Handler) http.Handler { func forbidden(reason string, attributes authorizer.AuthorizationAttributes, w http.ResponseWriter, req *http.Request) { kind := "" name := "" - apiVersion := klatest.DefaultVersionForLegacyGroup() + apiVersion := klatest.ExternalVersions[0] // the attributes can be empty for two basic reasons: // 1. malformed API request // 2. not an API request at all // In these cases, just assume default that will work better than nothing if attributes != nil { - apiVersion = attributes.GetAPIVersion() + apiVersion = unversioned.GroupVersion{Group: attributes.GetAPIGroup(), Version: attributes.GetAPIVersion()} kind = attributes.GetResource() if len(attributes.GetAPIGroup()) > 0 { kind = attributes.GetAPIGroup() + "." + kind @@ -118,9 +118,11 @@ func forbidden(reason string, attributes authorizer.AuthorizationAttributes, w h // Not all API versions in valid API requests will have a matching codec in kubernetes. If we can't find one, // just default to the latest kube codec. - codec := klatest.CodecForLegacyGroup() - if requestedCodec, err := klatest.InterfacesForLegacyGroup(apiVersion); err == nil { - codec = requestedCodec + codec := klatest.GroupOrDie(kapi.SchemeGroupVersion.Group).Codec + if requestedGroup, err := klatest.Group(apiVersion.Group); err == nil { + if requestedCodec, err := requestedGroup.InterfacesFor(apiVersion); err == nil { + codec = requestedCodec + } } formatted := &bytes.Buffer{} diff --git a/pkg/cmd/server/origin/master.go b/pkg/cmd/server/origin/master.go index a4eebb221996..56713840ae92 100644 --- a/pkg/cmd/server/origin/master.go +++ b/pkg/cmd/server/origin/master.go @@ -16,6 +16,8 @@ import ( kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/api/unversioned" + v1beta1extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" "k8s.io/kubernetes/pkg/apiserver" kclient "k8s.io/kubernetes/pkg/client/unversioned" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" @@ -579,9 +581,9 @@ func (c *MasterConfig) defaultAPIGroupVersion() *apiserver.APIGroupVersion { Convertor: kapi.Scheme, Linker: latest.SelfLinker, - Admit: c.AdmissionControl, - Context: c.getRequestContextMapper(), - NonDefaultGroupVersions: map[string]string{}, + Admit: c.AdmissionControl, + Context: c.getRequestContextMapper(), + NonDefaultGroupVersionKinds: map[string]unversioned.GroupVersionKind{}, } } @@ -597,9 +599,9 @@ func (c *MasterConfig) api_v1beta3(all map[string]rest.Storage) *apiserver.APIGr version := c.defaultAPIGroupVersion() version.Root = LegacyOpenShiftAPIPrefix version.Storage = storage - version.Version = OpenShiftAPIV1Beta3 + version.GroupVersion = v1beta3.SchemeGroupVersion version.Codec = v1beta3.Codec - version.NonDefaultGroupVersions["deploymentconfigs/scale"] = "extensions/v1beta1" + version.NonDefaultGroupVersionKinds["deploymentconfigs/scale"] = v1beta1extensions.SchemeGroupVersion.WithKind("Scale") return version } @@ -614,9 +616,9 @@ func (c *MasterConfig) api_v1(all map[string]rest.Storage) *apiserver.APIGroupVe } version := c.defaultAPIGroupVersion() version.Storage = storage - version.Version = OpenShiftAPIV1 + version.GroupVersion = v1.SchemeGroupVersion version.Codec = v1.Codec - version.NonDefaultGroupVersions["deploymentconfigs/scale"] = "extensions/v1beta1" + version.NonDefaultGroupVersionKinds["deploymentconfigs/scale"] = v1beta1extensions.SchemeGroupVersion.WithKind("Scale") return version } diff --git a/pkg/cmd/server/origin/master_config.go b/pkg/cmd/server/origin/master_config.go index e8085a85f1f7..1efd5abe9d30 100644 --- a/pkg/cmd/server/origin/master_config.go +++ b/pkg/cmd/server/origin/master_config.go @@ -13,6 +13,7 @@ import ( "k8s.io/kubernetes/pkg/admission" kapi "k8s.io/kubernetes/pkg/api" kapilatest "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apiserver" kclient "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/controller/serviceaccount" @@ -131,7 +132,8 @@ func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) { if err != nil { return nil, err } - etcdHelper, err := NewEtcdStorage(client, options.EtcdStorageConfig.OpenShiftStorageVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) + groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion} + etcdHelper, err := NewEtcdStorage(client, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } @@ -273,10 +275,15 @@ func newServiceAccountTokenGetter(options configapi.MasterConfig, client *etcdcl tokenGetter = serviceaccount.NewGetterFromClient(kubeClient) } else { // When we're running in-process, go straight to etcd (using the KubernetesStorageVersion/KubernetesStoragePrefix, since service accounts are kubernetes objects) - ketcdHelper, err := master.NewEtcdStorage(client, kapilatest.InterfacesForLegacyGroup, options.EtcdStorageConfig.KubernetesStorageVersion, options.EtcdStorageConfig.KubernetesStoragePrefix) + legacyGroup, err := kapilatest.Group(kapi.SchemeGroupVersion.Group) if err != nil { return nil, fmt.Errorf("Error setting up Kubernetes server storage: %v", err) } + versionedInterface, err := legacyGroup.InterfacesFor(unversioned.GroupVersion{Group: kapi.SchemeGroupVersion.Group, Version: options.EtcdStorageConfig.KubernetesStorageVersion}) + if err != nil { + return nil, fmt.Errorf("Error setting up Kubernetes server storage: %v", err) + } + ketcdHelper := etcdstorage.NewEtcdStorage(client, versionedInterface.Codec, options.EtcdStorageConfig.KubernetesStoragePrefix) tokenGetter = serviceaccount.NewGetterFromStorageInterface(ketcdHelper) } return tokenGetter, nil @@ -545,7 +552,7 @@ func (c *MasterConfig) OriginNamespaceControllerClients() (*osclient.Client, *kc } // NewEtcdHelper returns an EtcdHelper for the provided storage version. -func NewEtcdStorage(client *etcdclient.Client, version, prefix string) (oshelper storage.Interface, err error) { +func NewEtcdStorage(client *etcdclient.Client, version unversioned.GroupVersion, prefix string) (oshelper storage.Interface, err error) { interfaces, err := latest.InterfacesFor(version) if err != nil { return nil, err diff --git a/pkg/cmd/server/origin/run_components.go b/pkg/cmd/server/origin/run_components.go index bd79dc7089ff..9a7c610d06c9 100644 --- a/pkg/cmd/server/origin/run_components.go +++ b/pkg/cmd/server/origin/run_components.go @@ -10,6 +10,7 @@ import ( "k8s.io/kubernetes/pkg/admission" kapi "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/controller/serviceaccount" "k8s.io/kubernetes/pkg/registry/service/allocator" etcdallocator "k8s.io/kubernetes/pkg/registry/service/allocator/etcd" @@ -188,7 +189,8 @@ func (c *MasterConfig) RunBuildController() { stiImage := c.ImageFor("sti-builder") storageVersion := c.Options.EtcdStorageConfig.OpenShiftStorageVersion - interfaces, err := latest.InterfacesFor(storageVersion) + groupVersion := unversioned.GroupVersion{Group: "", Version: storageVersion} + interfaces, err := latest.InterfacesFor(groupVersion) if err != nil { glog.Fatalf("Unable to load storage version %s: %v", storageVersion, err) } diff --git a/pkg/cmd/util/clientcmd/factory.go b/pkg/cmd/util/clientcmd/factory.go index b15101d43b6a..59d501d8cfa7 100644 --- a/pkg/cmd/util/clientcmd/factory.go +++ b/pkg/cmd/util/clientcmd/factory.go @@ -25,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/runtime" "github.com/openshift/origin/pkg/api/latest" + authorizationapi "github.com/openshift/origin/pkg/authorization/api" authorizationreaper "github.com/openshift/origin/pkg/authorization/reaper" buildapi "github.com/openshift/origin/pkg/build/api" buildreaper "github.com/openshift/origin/pkg/build/reaper" @@ -37,6 +38,7 @@ import ( deployscaler "github.com/openshift/origin/pkg/deploy/scaler" deployutil "github.com/openshift/origin/pkg/deploy/util" routegen "github.com/openshift/origin/pkg/route/generator" + userapi "github.com/openshift/origin/pkg/user/api" authenticationreaper "github.com/openshift/origin/pkg/user/reaper" ) @@ -146,16 +148,21 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { w.Object = func() (meta.RESTMapper, runtime.ObjectTyper) { // Output using whatever version was negotiated in the client cache. The // version we decode with may not be the same as what the server requires. - if cfg, err := clients.ClientConfigForVersion(""); err == nil { - return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersion: cfg.Version}, api.Scheme + if cfg, err := clients.ClientConfigForVersion(nil); err == nil { + cmdApiVersion := unversioned.GroupVersion{} + if cfg.GroupVersion != nil { + cmdApiVersion = *cfg.GroupVersion + } + return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme } return mapper, api.Scheme } kRESTClient := w.Factory.RESTClient w.RESTClient = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - if latest.OriginKind(mapping.Kind, mapping.APIVersion) { - client, err := clients.ClientForVersion(mapping.APIVersion) + if latest.OriginKind(mapping.GroupVersionKind) { + mappingVersion := mapping.GroupVersionKind.GroupVersion() + client, err := clients.ClientForVersion(&mappingVersion) if err != nil { return nil, err } @@ -167,20 +174,21 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { // Save original Describer function kDescriberFunc := w.Factory.Describer w.Describer = func(mapping *meta.RESTMapping) (kubectl.Describer, error) { - if latest.OriginKind(mapping.Kind, mapping.APIVersion) { + if latest.OriginKind(mapping.GroupVersionKind) { oClient, kClient, err := w.Clients() if err != nil { - return nil, fmt.Errorf("unable to create client %s: %v", mapping.Kind, err) + return nil, fmt.Errorf("unable to create client %s: %v", mapping.GroupVersionKind.Kind, err) } - cfg, err := clients.ClientConfigForVersion(mapping.APIVersion) + mappingVersion := mapping.GroupVersionKind.GroupVersion() + cfg, err := clients.ClientConfigForVersion(&mappingVersion) if err != nil { - return nil, fmt.Errorf("unable to load a client %s: %v", mapping.Kind, err) + return nil, fmt.Errorf("unable to load a client %s: %v", mapping.GroupVersionKind.Kind, err) } - describer, ok := describe.DescriberFor(mapping.Kind, oClient, kClient, cfg.Host) + describer, ok := describe.DescriberFor(mapping.GroupVersionKind.GroupKind(), oClient, kClient, cfg.Host) if !ok { - return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind) + return nil, fmt.Errorf("no description has been implemented for %q", mapping.GroupVersionKind.Kind) } return describer, nil } @@ -193,7 +201,7 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { return nil, err } - if mapping.Kind == "DeploymentConfig" { + if mapping.GroupVersionKind.GroupKind() == deployapi.Kind("DeploymentConfig") { return deployscaler.NewDeploymentConfigScaler(oc, kc), nil } return kScalerFunc(mapping) @@ -205,14 +213,14 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { return nil, err } - switch mapping.Kind { - case "DeploymentConfig": + switch mapping.GroupVersionKind.GroupKind() { + case deployapi.Kind("DeploymentConfig"): return deployreaper.NewDeploymentConfigReaper(oc, kc), nil - case "Role": + case authorizationapi.Kind("Role"): return authorizationreaper.NewRoleReaper(oc, oc), nil - case "ClusterRole": + case authorizationapi.Kind("ClusterRole"): return authorizationreaper.NewClusterRoleReaper(oc, oc, oc), nil - case "User": + case userapi.Kind("User"): return authenticationreaper.NewUserReaper( client.UsersInterface(oc), client.GroupsInterface(oc), @@ -220,14 +228,14 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { client.RoleBindingsNamespacer(oc), kclient.SecurityContextConstraintsInterface(kc), ), nil - case "Group": + case userapi.Kind("Group"): return authenticationreaper.NewGroupReaper( client.GroupsInterface(oc), client.ClusterRoleBindingsInterface(oc), client.RoleBindingsNamespacer(oc), kclient.SecurityContextConstraintsInterface(kc), ), nil - case "BuildConfig": + case buildapi.Kind("BuildConfig"): return buildreaper.NewBuildConfigReaper(oc), nil } return kReaperFunc(mapping) @@ -305,12 +313,12 @@ func NewFactory(clientConfig kclientcmd.ClientConfig) *Factory { return kLogsForObjectFunc(object, options) } } - w.Printer = func(mapping *meta.RESTMapping, noHeaders, withNamespace, wide bool, showAll bool, columnLabels []string) (kubectl.ResourcePrinter, error) { - return describe.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, columnLabels), nil + w.Printer = func(mapping *meta.RESTMapping, noHeaders, withNamespace, wide bool, showAll bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) { + return describe.NewHumanReadablePrinter(noHeaders, withNamespace, wide, showAll, absoluteTimestamps, columnLabels), nil } kCanBeExposed := w.Factory.CanBeExposed - w.CanBeExposed = func(kind string) error { - if kind == "DeploymentConfig" { + w.CanBeExposed = func(kind unversioned.GroupKind) error { + if kind == deployapi.Kind("DeploymentConfig") { return nil } return kCanBeExposed(kind) @@ -404,7 +412,7 @@ func (f *Factory) Clients() (*client.Client, *kclient.Client, error) { if err != nil { return nil, nil, err } - osClient, err := f.clients.ClientForVersion("") + osClient, err := f.clients.ClientForVersion(nil) if err != nil { return nil, nil, err } @@ -416,11 +424,11 @@ type ShortcutExpander struct { meta.RESTMapper } -// VersionAndKindForResource implements meta.RESTMapper. It expands the resource first, then invokes the wrapped +// KindFor implements meta.RESTMapper. It expands the resource first, then invokes the wrapped // mapper. -func (e ShortcutExpander) VersionAndKindForResource(resource string) (defaultVersion, kind string, err error) { +func (e ShortcutExpander) KindFor(resource string) (unversioned.GroupVersionKind, error) { resource = expandResourceShortcut(resource) - return e.RESTMapper.VersionAndKindForResource(resource) + return e.RESTMapper.KindFor(resource) } // AliasesForResource returns whether a resource has an alias or not @@ -474,7 +482,7 @@ type clientCache struct { } // ClientConfigForVersion returns the correct config for a server -func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, error) { +func (c *clientCache) ClientConfigForVersion(version *unversioned.GroupVersion) (*kclient.Config, error) { if c.defaultConfig == nil { config, err := c.loader.ClientConfig() if err != nil { @@ -483,7 +491,11 @@ func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, e c.defaultConfig = config } // TODO: have a better config copy method - if config, ok := c.configs[version]; ok { + cacheKey := "" + if version != nil { + cacheKey = version.String() + } + if config, ok := c.configs[cacheKey]; ok { return config, nil } if c.negotiatingClient == nil { @@ -510,22 +522,26 @@ func (c *clientCache) ClientConfigForVersion(version string) (*kclient.Config, e if err != nil { return nil, err } - config.Version = negotiatedVersion + config.GroupVersion = negotiatedVersion client.SetOpenShiftDefaults(&config) - c.configs[version] = &config + c.configs[cacheKey] = &config // `version` does not necessarily equal `config.Version`. However, we know that we call this method again with // `config.Version`, we should get the the config we've just built. configCopy := config - c.configs[config.Version] = &configCopy + c.configs[config.GroupVersion.String()] = &configCopy return &config, nil } // ClientForVersion initializes or reuses a client for the specified version, or returns an // error if that is not possible -func (c *clientCache) ClientForVersion(version string) (*client.Client, error) { - if client, ok := c.clients[version]; ok { +func (c *clientCache) ClientForVersion(version *unversioned.GroupVersion) (*client.Client, error) { + cacheKey := "" + if version != nil { + cacheKey = version.String() + } + if client, ok := c.clients[cacheKey]; ok { return client, nil } config, err := c.ClientConfigForVersion(version) @@ -537,6 +553,6 @@ func (c *clientCache) ClientForVersion(version string) (*client.Client, error) { return nil, err } - c.clients[config.Version] = client + c.clients[config.GroupVersion.String()] = client return client, nil } diff --git a/pkg/cmd/util/clientcmd/factory_test.go b/pkg/cmd/util/clientcmd/factory_test.go index 4a89f3ec18a3..b8b78f111822 100644 --- a/pkg/cmd/util/clientcmd/factory_test.go +++ b/pkg/cmd/util/clientcmd/factory_test.go @@ -7,6 +7,8 @@ import ( kclient "k8s.io/kubernetes/pkg/client/unversioned" + "github.com/openshift/origin/pkg/api/v1" + "github.com/openshift/origin/pkg/api/v1beta3" "github.com/openshift/origin/pkg/client" ) @@ -14,7 +16,8 @@ func TestClientConfigForVersion(t *testing.T) { called := 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if req.URL.Path != "/oapi" { - t.Fatalf("Unexpected path called during negotiation: %s", req.URL.Path) + t.Errorf("Unexpected path called during negotiation: %s", req.URL.Path) + return } called++ w.Write([]byte(`{"versions":["v1"]}`)) @@ -32,12 +35,12 @@ func TestClientConfigForVersion(t *testing.T) { // First call, negotiate called = 0 - v1Config, err := clients.ClientConfigForVersion("") + v1Config, err := clients.ClientConfigForVersion(nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } - if v1Config.Version != "v1" { - t.Fatalf("Expected v1, got %v", v1Config.Version) + if v1Config.GroupVersion.String() != "v1" { + t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String()) } if called != 1 { t.Fatalf("Expected to be called 1 time during negotiation, was called %d times", called) @@ -45,12 +48,12 @@ func TestClientConfigForVersion(t *testing.T) { // Second call, cache called = 0 - v1Config, err = clients.ClientConfigForVersion("") + v1Config, err = clients.ClientConfigForVersion(nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } - if v1Config.Version != "v1" { - t.Fatalf("Expected v1, got %v", v1Config.Version) + if v1Config.GroupVersion.String() != "v1" { + t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String()) } if called != 0 { t.Fatalf("Expected not be called again getting a config from cache, was called %d additional times", called) @@ -58,12 +61,12 @@ func TestClientConfigForVersion(t *testing.T) { // Third call, cached under exactly matching version called = 0 - v1Config, err = clients.ClientConfigForVersion("v1") + v1Config, err = clients.ClientConfigForVersion(&v1.SchemeGroupVersion) if err != nil { t.Fatalf("Unexpected error: %v", err) } - if v1Config.Version != "v1" { - t.Fatalf("Expected v1, got %v", v1Config.Version) + if v1Config.GroupVersion.String() != "v1" { + t.Fatalf("Expected v1, got %v", v1Config.GroupVersion.String()) } if called != 0 { t.Fatalf("Expected not be called again getting a config from cache, was called %d additional times", called) @@ -71,12 +74,12 @@ func TestClientConfigForVersion(t *testing.T) { // Call for unsupported version, negotiate to supported version called = 0 - v1beta3Config, err := clients.ClientConfigForVersion("v1beta3") + v1beta3Config, err := clients.ClientConfigForVersion(&v1beta3.SchemeGroupVersion) if err != nil { t.Fatalf("Unexpected error: %v", err) } - if v1beta3Config.Version != "v1" { - t.Fatalf("Expected to negotiate v1 for v1beta3 config, got %v", v1beta3Config.Version) + if v1beta3Config.GroupVersion.String() != "v1" { + t.Fatalf("Expected to negotiate v1 for v1beta3 config, got %v", v1beta3Config.GroupVersion.String()) } if called != 1 { t.Fatalf("Expected to be called once getting a config for a new version, was called %d times", called) diff --git a/pkg/cmd/util/cmd.go b/pkg/cmd/util/cmd.go index 8c92ad137bdc..41bab8d4f86e 100644 --- a/pkg/cmd/util/cmd.go +++ b/pkg/cmd/util/cmd.go @@ -47,12 +47,12 @@ func ResolveResource(defaultResource, resourceString string, mapper meta.RESTMap case 1: name = parts[0] case 2: - _, kind, err := mapper.VersionAndKindForResource(parts[0]) + gvk, err := mapper.KindFor(parts[0]) if err != nil { return "", "", err } name = parts[1] - resource, _ := meta.KindToResource(kind, false) + resource, _ := meta.KindToResource(gvk.Kind, false) return resource, name, nil default: return "", "", fmt.Errorf("invalid resource format: %s", resourceString) diff --git a/pkg/cmd/util/pluginconfig/config_test.go b/pkg/cmd/util/pluginconfig/config_test.go index c19f8136eadf..ca4ffbd6ef14 100644 --- a/pkg/cmd/util/pluginconfig/config_test.go +++ b/pkg/cmd/util/pluginconfig/config_test.go @@ -7,6 +7,8 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" + oapi "github.com/openshift/origin/pkg/api" + "github.com/openshift/origin/pkg/api/v1" "github.com/openshift/origin/pkg/cmd/server/api" "github.com/openshift/origin/pkg/cmd/server/api/latest" ) @@ -20,8 +22,8 @@ type TestConfig struct { func (*TestConfig) IsAnAPIObject() {} func TestGetPluginConfig(t *testing.T) { - api.Scheme.AddKnownTypes("", &TestConfig{}) - api.Scheme.AddKnownTypes("v1", &TestConfig{}) + api.Scheme.AddKnownTypes(oapi.SchemeGroupVersion, &TestConfig{}) + api.Scheme.AddKnownTypes(v1.SchemeGroupVersion, &TestConfig{}) testConfig := &TestConfig{ Item1: "item1value", diff --git a/pkg/deploy/strategy/recreate/recreate.go b/pkg/deploy/strategy/recreate/recreate.go index f70955c0084a..aafcddc5852f 100644 --- a/pkg/deploy/strategy/recreate/recreate.go +++ b/pkg/deploy/strategy/recreate/recreate.go @@ -44,7 +44,7 @@ type RecreateDeploymentStrategy struct { // NewRecreateDeploymentStrategy makes a RecreateDeploymentStrategy backed by // a real HookExecutor and client. func NewRecreateDeploymentStrategy(client kclient.Interface, codec runtime.Codec) *RecreateDeploymentStrategy { - scaler, _ := kubectl.ScalerFor("ReplicationController", client) + scaler, _ := kubectl.ScalerFor(kapi.Kind("ReplicationController"), client) return &RecreateDeploymentStrategy{ getReplicationController: func(namespace, name string) (*kapi.ReplicationController, error) { return client.ReplicationControllers(namespace).Get(name) diff --git a/pkg/generate/app/pipeline.go b/pkg/generate/app/pipeline.go index e962cc90451c..32dd28caae58 100644 --- a/pkg/generate/app/pipeline.go +++ b/pkg/generate/app/pipeline.go @@ -13,6 +13,7 @@ import ( "k8s.io/kubernetes/pkg/util/intstr" kuval "k8s.io/kubernetes/pkg/util/validation" + build "github.com/openshift/origin/pkg/build/api" deploy "github.com/openshift/origin/pkg/deploy/api" image "github.com/openshift/origin/pkg/image/api" route "github.com/openshift/origin/pkg/route/api" @@ -428,11 +429,11 @@ func (a *acceptUnique) Accept(from interface{}) bool { if err != nil { return false } - _, kind, err := a.typer.ObjectVersionAndKind(obj) + gvk, err := a.typer.ObjectKind(obj) if err != nil { return false } - key := fmt.Sprintf("%s/%s/%s", kind, meta.Namespace, meta.Name) + key := fmt.Sprintf("%s/%s/%s", gvk.Kind, meta.Namespace, meta.Name) _, exists := a.objects[key] if exists { return false @@ -472,11 +473,11 @@ func (a *acceptBuildConfigs) Accept(from interface{}) bool { if err != nil { return false } - _, kind, err := a.typer.ObjectVersionAndKind(obj) + gvk, err := a.typer.ObjectKind(obj) if err != nil { return false } - return kind == "BuildConfig" || kind == "ImageStream" + return gvk.GroupKind() == build.Kind("BuildConfig") || gvk.GroupKind() == image.Kind("ImageStream") } // NewAcceptBuildConfigs creates an acceptor accepting BuildConfig objects diff --git a/pkg/image/api/v1/conversion.go b/pkg/image/api/v1/conversion.go index ed0b38c3369e..6003f414a517 100644 --- a/pkg/image/api/v1/conversion.go +++ b/pkg/image/api/v1/conversion.go @@ -4,6 +4,7 @@ import ( "sort" kapi "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" v1 "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/conversion" @@ -59,7 +60,7 @@ func convert_v1_Image_To_api_Image(in *Image, out *newer.Image, s conversion.Sco } if len(in.DockerImageMetadata.RawJSON) > 0 { // TODO: add a way to default the expected kind and version of an object if not set - obj, err := kapi.Scheme.New(version, "DockerImage") + obj, err := kapi.Scheme.New(unversioned.GroupVersionKind{Version: version, Kind: "DockerImage"}) if err != nil { return err } diff --git a/pkg/image/api/v1beta3/conversion.go b/pkg/image/api/v1beta3/conversion.go index 587785e9d24b..363a319d8510 100644 --- a/pkg/image/api/v1beta3/conversion.go +++ b/pkg/image/api/v1beta3/conversion.go @@ -5,6 +5,7 @@ import ( "sort" kapi "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/conversion" newer "github.com/openshift/origin/pkg/image/api" @@ -47,7 +48,7 @@ func convert_v1beta3_Image_To_api_Image(in *Image, out *newer.Image, s conversio } if len(in.DockerImageMetadata.RawJSON) > 0 { // TODO: add a way to default the expected kind and version of an object if not set - obj, err := kapi.Scheme.New(version, "DockerImage") + obj, err := kapi.Scheme.New(unversioned.GroupVersionKind{Version: version, Kind: "DockerImage"}) if err != nil { return err } diff --git a/pkg/project/admission/lifecycle/admission.go b/pkg/project/admission/lifecycle/admission.go index 9f3051fe75bc..7ed157c170ee 100644 --- a/pkg/project/admission/lifecycle/admission.go +++ b/pkg/project/admission/lifecycle/admission.go @@ -32,6 +32,7 @@ import ( client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/util/sets" + "github.com/openshift/origin/pkg/api" "github.com/openshift/origin/pkg/api/latest" oadmission "github.com/openshift/origin/pkg/cmd/server/admission" "github.com/openshift/origin/pkg/project/cache" @@ -69,15 +70,13 @@ func (e *lifecycle) Admit(a admission.Attributes) (err error) { if isSubjectAccessReview(a) { return nil } - defaultVersion, kind, err := latest.RESTMapper.VersionAndKindForResource(a.GetResource()) + fmt.Println(a.GetKind()) + mapping, err := latest.RESTMapper.RESTMapping(a.GetKind()) if err != nil { glog.V(4).Infof("Ignoring life-cycle enforcement for resource %v; no associated default version and kind could be found.", a.GetResource()) return nil } - mapping, err := latest.RESTMapper.RESTMapping(kind, defaultVersion) - if err != nil { - return admission.NewForbidden(a, err) - } + fmt.Println(mapping) if mapping.Scope.Name() != meta.RESTScopeNameNamespace { return nil } @@ -106,8 +105,8 @@ func (e *lifecycle) Admit(a admission.Attributes) (err error) { return nil } - if namespace.Status.Phase == kapi.NamespaceTerminating && !e.creatableResources.Has(strings.ToLower(a.GetResource())) { - return apierrors.NewForbidden(kind, name, fmt.Errorf("Namespace %s is terminating", a.GetNamespace())) + if namespace.Status.Phase == kapi.NamespaceTerminating && !e.creatableResources.Has(strings.ToLower(a.GetResource().Resource)) { + return apierrors.NewForbidden(a.GetKind().Kind, name, fmt.Errorf("Namespace %s is terminating", a.GetNamespace())) } // in case of concurrency issues, we will retry this logic @@ -160,7 +159,11 @@ func NewLifecycle(client client.Interface, creatableResources sets.String) (admi }, nil } +var ( + sar = api.Kind("SubjectAccessReview") + lsar = api.Kind("LocalSubjectAccessReview") +) + func isSubjectAccessReview(a admission.Attributes) bool { - return a.GetResource() == "subjectaccessreviews" || - a.GetResource() == "localsubjectaccessreviews" + return a.GetKind() == sar || a.GetKind() == lsar } diff --git a/pkg/project/admission/lifecycle/admission_test.go b/pkg/project/admission/lifecycle/admission_test.go index d8351d3db505..54c3e8e5d08b 100644 --- a/pkg/project/admission/lifecycle/admission_test.go +++ b/pkg/project/admission/lifecycle/admission_test.go @@ -28,7 +28,7 @@ func TestIgnoreThatWhichCannotBeKnown(t *testing.T) { handler := &lifecycle{} unknown := &UnknownObject{} - err := handler.Admit(admission.NewAttributesRecord(unknown, "kind", "namespace", "name", "resource", "subresource", "CREATE", nil)) + err := handler.Admit(admission.NewAttributesRecord(unknown, kapi.Kind("kind"), "namespace", "name", kapi.Resource("resource"), "subresource", "CREATE", nil)) if err != nil { t.Errorf("Admission control should not error if it finds an object it knows nothing about %v", err) } @@ -67,7 +67,7 @@ func TestAdmissionExists(t *testing.T) { Phase: buildapi.BuildPhaseNew, }, } - err := handler.Admit(admission.NewAttributesRecord(build, "Build", "namespace", "name", "builds", "", "CREATE", nil)) + err := handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), "namespace", "name", kapi.Resource("builds"), "", "CREATE", nil)) if err == nil { t.Errorf("Expected an error because namespace does not exist") } @@ -113,7 +113,7 @@ func TestAdmissionLifecycle(t *testing.T) { Phase: buildapi.BuildPhaseNew, }, } - err := handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "CREATE", nil)) + err := handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "CREATE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } @@ -123,19 +123,19 @@ func TestAdmissionLifecycle(t *testing.T) { store.Add(namespaceObj) // verify create operations in the namespace cause an error - err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "CREATE", nil)) + err = handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "CREATE", nil)) if err == nil { t.Errorf("Expected error rejecting creates in a namespace when it is terminating") } // verify update operations in the namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "name", "builds", "", "UPDATE", nil)) + err = handler.Admit(admission.NewAttributesRecord(build, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "UPDATE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete operations in the namespace can proceed - err = handler.Admit(admission.NewAttributesRecord(nil, "Build", build.Namespace, "name", "builds", "", "DELETE", nil)) + err = handler.Admit(admission.NewAttributesRecord(nil, kapi.Kind("Build"), build.Namespace, "name", kapi.Resource("builds"), "", "DELETE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } @@ -187,7 +187,7 @@ func TestSAR(t *testing.T) { } for k, v := range tests { - err := handler.Admit(admission.NewAttributesRecord(nil, v.kind, "foo", "name", v.resource, "", "CREATE", nil)) + err := handler.Admit(admission.NewAttributesRecord(nil, kapi.Kind(v.kind), "foo", "name", kapi.Resource(v.resource), "", "CREATE", nil)) if err != nil { t.Errorf("Unexpected error for %s returned from admission handler: %v", k, err) } diff --git a/pkg/project/admission/nodeenv/admission.go b/pkg/project/admission/nodeenv/admission.go index fb705ceb7fdc..8bd51d64a310 100644 --- a/pkg/project/admission/nodeenv/admission.go +++ b/pkg/project/admission/nodeenv/admission.go @@ -33,7 +33,7 @@ var _ = oadmission.Validator(&podNodeEnvironment{}) // Admit enforces that pod and its project node label selectors matches at least a node in the cluster. func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) { resource := a.GetResource() - if resource != "pods" { + if resource != kapi.Resource("pods") { return nil } if a.GetSubresource() != "" { @@ -54,7 +54,7 @@ func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) { } namespace, err := p.cache.GetNamespace(a.GetNamespace()) if err != nil { - return apierrors.NewForbidden(resource, name, err) + return apierrors.NewForbidden(resource.Resource, name, err) } projectNodeSelector, err := p.cache.GetNodeSelectorMap(namespace) if err != nil { @@ -62,7 +62,7 @@ func (p *podNodeEnvironment) Admit(a admission.Attributes) (err error) { } if labelselector.Conflicts(projectNodeSelector, pod.Spec.NodeSelector) { - return apierrors.NewForbidden(resource, name, fmt.Errorf("pod node label selector conflicts with its project node label selector")) + return apierrors.NewForbidden(resource.Resource, name, fmt.Errorf("pod node label selector conflicts with its project node label selector")) } // modify pod node selector = project node selector + current pod node selector diff --git a/pkg/project/admission/nodeenv/admission_test.go b/pkg/project/admission/nodeenv/admission_test.go index c8b813544454..47e8c8b4495b 100644 --- a/pkg/project/admission/nodeenv/admission_test.go +++ b/pkg/project/admission/nodeenv/admission_test.go @@ -111,7 +111,7 @@ func TestPodAdmission(t *testing.T) { } pod.Spec = kapi.PodSpec{NodeSelector: test.podNodeSelector} - err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", "namespace", project.ObjectMeta.Name, "pods", "", admission.Create, nil)) + err := handler.Admit(admission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", project.ObjectMeta.Name, kapi.Resource("pods"), "", admission.Create, nil)) if test.admit && err != nil { t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) } else if !test.admit && err == nil { diff --git a/pkg/project/registry/projectrequest/delegated/delegated.go b/pkg/project/registry/projectrequest/delegated/delegated.go index a9e9d74ca50d..e1a207ae20a9 100644 --- a/pkg/project/registry/projectrequest/delegated/delegated.go +++ b/pkg/project/registry/projectrequest/delegated/delegated.go @@ -129,7 +129,7 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err Mapper: latest.RESTMapper, Typer: kapi.Scheme, RESTClientFactory: func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - if latest.OriginKind(mapping.Kind, mapping.APIVersion) { + if latest.OriginKind(mapping.GroupVersionKind) { return r.openshiftClient, nil } return r.kubeClient, nil diff --git a/pkg/security/admission/admission.go b/pkg/security/admission/admission.go index f3756843f517..2c69e8c0c4f7 100644 --- a/pkg/security/admission/admission.go +++ b/pkg/security/admission/admission.go @@ -95,7 +95,7 @@ func (a *constraint) Stop() { // with the validated SCC. If we don't find any reject the pod and give all errors from the // failed attempts. func (c *constraint) Admit(a kadmission.Attributes) error { - if a.GetResource() != string(kapi.ResourcePods) { + if a.GetResource().Resource != string(kapi.ResourcePods) { return nil } diff --git a/pkg/security/admission/admission_test.go b/pkg/security/admission/admission_test.go index e583348e5a5c..a999340e254c 100644 --- a/pkg/security/admission/admission_test.go +++ b/pkg/security/admission/admission_test.go @@ -14,9 +14,10 @@ import ( kscc "k8s.io/kubernetes/pkg/securitycontextconstraints" "k8s.io/kubernetes/pkg/util" + "sort" + allocator "github.com/openshift/origin/pkg/security" "github.com/openshift/origin/pkg/security/uid" - "sort" ) func NewTestAdmission(store cache.Store, kclient client.Interface) kadmission.Interface { @@ -132,7 +133,7 @@ func testSCCAdmit(testCaseName string, sccs []*kapi.SecurityContextConstraints, plugin := NewTestAdmission(store, tc) - attrs := kadmission.NewAttributesRecord(pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{}) err := plugin.Admit(attrs) if shouldPass && err != nil { @@ -373,7 +374,7 @@ func TestAdmit(t *testing.T) { } for k, v := range testCases { - attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{}) err := p.Admit(attrs) if v.shouldAdmit && err != nil { @@ -447,7 +448,7 @@ func TestAdmit(t *testing.T) { for k, v := range testCases { if !v.shouldAdmit { - attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{}) err := p.Admit(attrs) if err != nil { t.Errorf("Expected %s to pass with escalated scc but got error %v", k, err) @@ -553,7 +554,7 @@ func TestAssignSecurityContext(t *testing.T) { } for k, v := range testCases { - errs := assignSecurityContext(provider, v.pod) + errs := assignSecurityContext(provider, v.pod, nil) if v.shouldValidate && len(errs) > 0 { t.Errorf("%s expected to validate but received errors %v", k, errs) continue @@ -822,7 +823,7 @@ func TestCreateProvidersFromConstraints(t *testing.T) { scc := v.scc() // create the providers, this method only needs the namespace - attributes := kadmission.NewAttributesRecord(nil, "", v.namespace.Name, "", "", "", kadmission.Create, nil) + attributes := kadmission.NewAttributesRecord(nil, kapi.Kind("Pod"), v.namespace.Name, "", kapi.Resource("pods"), "", kadmission.Create, nil) _, errs := admit.createProvidersFromConstraints(attributes.GetNamespace(), []*kapi.SecurityContextConstraints{scc}) if !reflect.DeepEqual(scc, v.scc()) { @@ -1464,7 +1465,7 @@ func TestAdmitWithPrioritizedSCC(t *testing.T) { // testSCCAdmission is a helper to admit the pod and ensure it was validated against the expected // SCC. func testSCCAdmission(pod *kapi.Pod, plugin kadmission.Interface, expectedSCC string, t *testing.T) { - attrs := kadmission.NewAttributesRecord(pod, "Pod", "namespace", "", string(kapi.ResourcePods), "", kadmission.Create, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(pod, kapi.Kind("Pod"), "namespace", "", kapi.Resource("pods"), "", kadmission.Create, &user.DefaultInfo{}) err := plugin.Admit(attrs) if err != nil { t.Errorf("error admitting pod: %v", err) diff --git a/pkg/security/admission/scc_exec.go b/pkg/security/admission/scc_exec.go index 9764519cb88f..be696508a880 100644 --- a/pkg/security/admission/scc_exec.go +++ b/pkg/security/admission/scc_exec.go @@ -20,6 +20,7 @@ import ( "io" "k8s.io/kubernetes/pkg/admission" + kapi "k8s.io/kubernetes/pkg/api" client "k8s.io/kubernetes/pkg/client/unversioned" ) @@ -43,7 +44,7 @@ func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) { if a.GetOperation() != admission.Connect { return nil } - if a.GetResource() != "pods" { + if a.GetResource() != kapi.Resource("pods") { return nil } if a.GetSubresource() != "attach" && a.GetSubresource() != "exec" { @@ -58,7 +59,7 @@ func (d *sccExecRestrictions) Admit(a admission.Attributes) (err error) { // create a synthentic admission attribute to check SCC admission status for this pod // clear the SA name, so that any permissions MUST be based on your user's power, not the SAs power. pod.Spec.ServiceAccountName = "" - createAttributes := admission.NewAttributesRecord(pod, "pods", a.GetNamespace(), a.GetName(), a.GetResource(), a.GetSubresource(), admission.Create, a.GetUserInfo()) + createAttributes := admission.NewAttributesRecord(pod, kapi.Kind("Pod"), a.GetNamespace(), a.GetName(), a.GetResource(), a.GetSubresource(), admission.Create, a.GetUserInfo()) if err := d.constraintAdmission.Admit(createAttributes); err != nil { return admission.NewForbidden(a, err) } diff --git a/pkg/security/admission/scc_exec_test.go b/pkg/security/admission/scc_exec_test.go index 542a14aa4eb7..9b945c110c83 100644 --- a/pkg/security/admission/scc_exec_test.go +++ b/pkg/security/admission/scc_exec_test.go @@ -89,7 +89,7 @@ func TestExecAdmit(t *testing.T) { // create the admission plugin p := NewSCCExecRestrictions(tc) - attrs := kadmission.NewAttributesRecord(v.pod, "Pod", "namespace", "pod-name", v.resource, v.subresource, v.operation, &user.DefaultInfo{}) + attrs := kadmission.NewAttributesRecord(v.pod, kapi.Kind("Pod"), "namespace", "pod-name", kapi.Resource(v.resource), v.subresource, v.operation, &user.DefaultInfo{}) err := p.Admit(attrs) if v.shouldAdmit && err != nil { diff --git a/pkg/template/registry/rest_test.go b/pkg/template/registry/rest_test.go index be166d90e366..f6adb17f4ca3 100644 --- a/pkg/template/registry/rest_test.go +++ b/pkg/template/registry/rest_test.go @@ -17,7 +17,7 @@ func TestNewRESTInvalidType(t *testing.T) { t.Errorf("Expected type error.") } - if _, _, err := latest.RESTMapper.VersionAndKindForResource("processedtemplates"); err != nil { + if _, err := latest.RESTMapper.KindFor("processedtemplates"); err != nil { t.Errorf("no processed templates: %v", err) } } diff --git a/test/integration/admissionconfig_test.go b/test/integration/admissionconfig_test.go index bc8665cb5ef9..c1af708797e1 100644 --- a/test/integration/admissionconfig_test.go +++ b/test/integration/admissionconfig_test.go @@ -17,6 +17,8 @@ import ( "k8s.io/kubernetes/pkg/runtime" kyaml "k8s.io/kubernetes/pkg/util/yaml" + "github.com/openshift/origin/pkg/api" + "github.com/openshift/origin/pkg/api/v1" buildapi "github.com/openshift/origin/pkg/build/api" "github.com/openshift/origin/pkg/client" configapi "github.com/openshift/origin/pkg/cmd/server/api" @@ -159,8 +161,8 @@ func checkAdmissionObjectLabelValues(labels, expected map[string]string) error { } func registerAdmissionPluginTestConfigType() { - configapi.Scheme.AddKnownTypes("", &TestPluginConfig{}) - configapi.Scheme.AddKnownTypes("v1", &TestPluginConfig{}) + configapi.Scheme.AddKnownTypes(api.SchemeGroupVersion, &TestPluginConfig{}) + configapi.Scheme.AddKnownTypes(v1.SchemeGroupVersion, &TestPluginConfig{}) } func setupAdmissionPluginTestConfig(t *testing.T, value string) string { diff --git a/test/integration/template_test.go b/test/integration/template_test.go index 710f11fc49e6..ba8a8b855fd4 100644 --- a/test/integration/template_test.go +++ b/test/integration/template_test.go @@ -5,6 +5,7 @@ package integration import ( "testing" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/runtime" @@ -22,12 +23,12 @@ func TestTemplate(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - for _, version := range []string{"v1"} { + for _, version := range []unversioned.GroupVersion{v1.SchemeGroupVersion} { config, err := testutil.GetClusterAdminClientConfig(path) if err != nil { t.Fatalf("unexpected error: %v", err) } - config.Version = version + config.GroupVersion = &version config.Prefix = "" c, err := client.New(config) if err != nil { diff --git a/test/templates/templates_test.go b/test/templates/templates_test.go index cbb3fee7f446..cc0523d3f76c 100644 --- a/test/templates/templates_test.go +++ b/test/templates/templates_test.go @@ -53,7 +53,7 @@ func TestTemplateTransformationFromConfig(t *testing.T) { server := httptest.NewServer(osMux) defer server.Close() - osClient := osclient.NewOrDie(&kclient.Config{Host: server.URL, Version: latest.Version}) + osClient := osclient.NewOrDie(&kclient.Config{Host: server.URL, GroupVersion: &latest.Version}) storage := map[string]rest.Storage{ "processedTemplates": templateregistry.NewREST(), @@ -66,8 +66,8 @@ func TestTemplateTransformationFromConfig(t *testing.T) { interfaces, _ := latest.InterfacesFor(latest.Version) handlerContainer := master.NewHandlerContainer(osMux) version := apiserver.APIGroupVersion{ - Root: "/oapi", - Version: latest.Version, + Root: "/oapi", + GroupVersion: latest.Version, Mapper: latest.RESTMapper, diff --git a/test/util/helpers.go b/test/util/helpers.go index 71cc51f52689..cd02cd9a539c 100644 --- a/test/util/helpers.go +++ b/test/util/helpers.go @@ -5,9 +5,9 @@ import ( "io/ioutil" kapi "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/latest" kyaml "k8s.io/kubernetes/pkg/util/yaml" + oapi "github.com/openshift/origin/pkg/api" buildapi "github.com/openshift/origin/pkg/build/api" imageapi "github.com/openshift/origin/pkg/image/api" templateapi "github.com/openshift/origin/pkg/template/api" @@ -21,7 +21,7 @@ func CreateSampleImageStream(namespace string) *imageapi.ImageStream { fmt.Printf("ERROR: Unable to read: %v", err) return nil } - latest.CodecForLegacyGroup().DecodeInto(jsonData, &stream) + oapi.Codec.DecodeInto(jsonData, &stream) client, _ := GetClusterAdminClient(KubeConfigPath()) result, err := client.ImageStreams(namespace).Create(&stream) @@ -47,7 +47,7 @@ func GetBuildFixture(filename string) *buildapi.Build { fmt.Printf("ERROR: Unable to read %s: %v", filename, err) return nil } - latest.CodecForLegacyGroup().DecodeInto(jsonData, &build) + oapi.Codec.DecodeInto(jsonData, &build) return &build } @@ -58,7 +58,7 @@ func GetSecretFixture(filename string) *kapi.Secret { fmt.Printf("ERROR: Unable to read %s: %v", filename, err) return nil } - latest.CodecForLegacyGroup().DecodeInto(jsonData, &secret) + kapi.Codec.DecodeInto(jsonData, &secret) return &secret } @@ -71,7 +71,7 @@ func GetTemplateFixture(filename string) (*templateapi.Template, error) { if err != nil { return nil, err } - obj, err := latest.CodecForLegacyGroup().Decode(jsonData) + obj, err := oapi.Codec.Decode(jsonData) if err != nil { return nil, err } diff --git a/tools/genconversion/conversion.go b/tools/genconversion/conversion.go index 2be7a73d9faf..6f223a6407d3 100644 --- a/tools/genconversion/conversion.go +++ b/tools/genconversion/conversion.go @@ -8,6 +8,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" pkg_runtime "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/sets" @@ -21,6 +22,7 @@ import ( var ( functionDest = flag.StringP("funcDest", "f", "-", "Output for conversion functions; '-' means stdout") + group = flag.StringP("group", "g", "", "Group for conversion.") version = flag.StringP("version", "v", "v1beta3", "Version for conversion.") ) @@ -46,11 +48,12 @@ func main() { generator.AssumePrivateConversions() // TODO(wojtek-t): Change the overwrites to a flag. generator.OverwritePackage(*version, "") - for _, knownType := range api.Scheme.KnownTypes(*version) { + gv := unversioned.GroupVersion{Group: *group, Version: *version} + for _, knownType := range api.Scheme.KnownTypes(gv) { if !strings.Contains(knownType.PkgPath(), "openshift/origin") { continue } - if err := generator.GenerateConversionsForType(*version, knownType); err != nil { + if err := generator.GenerateConversionsForType(gv, knownType); err != nil { glog.Errorf("error while generating conversion functions for %v: %v", knownType, err) } } diff --git a/tools/gendeepcopy/deep_copy.go b/tools/gendeepcopy/deep_copy.go index 839f7e53f042..c7c6b175a295 100644 --- a/tools/gendeepcopy/deep_copy.go +++ b/tools/gendeepcopy/deep_copy.go @@ -24,6 +24,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" pkg_runtime "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/sets" @@ -37,6 +38,7 @@ import ( var ( functionDest = flag.StringP("func-dest", "f", "-", "Output for deep copy functions; '-' means stdout") + group = flag.StringP("group", "g", "", "Group for deep copies.") version = flag.StringP("version", "v", "v1beta3", "Version for deep copies.") overwrites = flag.StringP("overwrites", "o", "", "Comma-separated overwrites for package names") ) @@ -57,9 +59,9 @@ func main() { funcOut = file } - knownVersion := *version - if knownVersion == "api" { - knownVersion = api.Scheme.Raw().InternalVersion + knownGroupVersion := unversioned.GroupVersion{Group: *group, Version: *version} + if knownGroupVersion.Version == "api" { + knownGroupVersion = api.Scheme.Raw().InternalVersions[knownGroupVersion.Group] } generator := pkg_runtime.NewDeepCopyGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api", sets.NewString("github.com/openshift/origin")) apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api") @@ -69,7 +71,7 @@ func main() { vals := strings.Split(overwrite, "=") generator.OverwritePackage(vals[0], vals[1]) } - for _, knownType := range api.Scheme.KnownTypes(knownVersion) { + for _, knownType := range api.Scheme.KnownTypes(knownGroupVersion) { if !strings.Contains(knownType.PkgPath(), "openshift/origin") { continue }