diff --git a/pkg/api/install/install.go b/pkg/api/install/install.go index 49b68407685..3354c70da94 100644 --- a/pkg/api/install/install.go +++ b/pkg/api/install/install.go @@ -30,7 +30,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" - apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/runtime" ) @@ -48,20 +48,24 @@ func init() { glog.V(4).Infof("%v", err) return } + + worstToBestGroupVersions := []unversioned.GroupVersion{} + // Use the first API version in the list of registered versions as the latest. registeredGroupVersions := registered.GroupVersionsForGroup("") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ - GroupVersion: groupVersion, - Group: apiutil.GetGroup(groupVersion), - Version: apiutil.GetVersion(groupVersion), - Codec: runtime.CodecFor(api.Scheme, groupVersion), + GroupVersion: groupVersion.String(), + Group: groupVersion.Group, + Version: groupVersion.Version, + Codec: runtime.CodecFor(api.Scheme, groupVersion.String()), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { - versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) - groupVersions = append(groupVersions, registeredGroupVersions[i]) + versions = append(versions, registeredGroupVersions[i].Version) + groupVersions = append(groupVersions, registeredGroupVersions[i].String()) + worstToBestGroupVersions = append(worstToBestGroupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions @@ -90,7 +94,7 @@ func init() { "ThirdPartyResourceData", "ThirdPartyResourceList") - mapper := api.NewDefaultRESTMapper("", versions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + mapper := api.NewDefaultRESTMapper(worstToBestGroupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) // setup aliases for groups of resources mapper.AddResourceAlias("all", userResources...) groupMeta.RESTMapper = mapper diff --git a/pkg/api/mapper.go b/pkg/api/mapper.go index d657adf49fd..50df8893cd2 100644 --- a/pkg/api/mapper.go +++ b/pkg/api/mapper.go @@ -17,7 +17,6 @@ limitations under the License. package api import ( - "fmt" "strings" "k8s.io/kubernetes/pkg/api/meta" @@ -35,23 +34,16 @@ func RegisterRESTMapper(m meta.RESTMapper) { RESTMapper = append(RESTMapper.(meta.MultiRESTMapper), m) } -func NewDefaultRESTMapper(group string, groupVersionStrings []string, interfacesFunc meta.VersionInterfacesFunc, +func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc, importPathPrefix string, ignoredKinds, rootScoped sets.String) *meta.DefaultRESTMapper { - mapper := meta.NewDefaultRESTMapper(group, groupVersionStrings, interfacesFunc) + mapper := meta.NewDefaultRESTMapper(defaultGroupVersions, interfacesFunc) // enumerate all supported versions, get the kinds, and register with the mapper how to address // our resources. - for _, gvString := range groupVersionStrings { - gv, err := unversioned.ParseGroupVersion(gvString) - // TODO stop panicing when the types are fixed - if err != nil { - panic(err) - } - if gv.Group != group { - panic(fmt.Sprintf("%q does not match the expect %q", gv.Group, group)) - } - + for _, gv := range defaultGroupVersions { for kind, oType := range Scheme.KnownTypes(gv.String()) { + gvk := gv.WithKind(kind) + // TODO: Remove import path prefix check. // We check the import path prefix because we currently stuff both "api" and "extensions" objects // into the same group within Scheme since Scheme has no notion of groups yet. @@ -62,7 +54,7 @@ func NewDefaultRESTMapper(group string, groupVersionStrings []string, interfaces if rootScoped.Has(kind) { scope = meta.RESTScopeRoot } - mapper.Add(scope, kind, gv.String(), false) + mapper.Add(gvk, scope, false) } } return mapper diff --git a/pkg/api/meta/restmapper.go b/pkg/api/meta/restmapper.go index 27ec213665f..bb1d817a2fe 100644 --- a/pkg/api/meta/restmapper.go +++ b/pkg/api/meta/restmapper.go @@ -56,13 +56,6 @@ var RESTScopeRoot = &restScope{ name: RESTScopeNameRoot, } -// typeMeta is used as a key for lookup in the mapping between REST path and -// API object. -type typeMeta struct { - APIVersion string - Kind string -} - // DefaultRESTMapper exposes mappings between the types defined in a // runtime.Scheme. It assumes that all types defined the provided scheme // can be mapped with the provided MetadataAccessor and Codec interfaces. @@ -76,12 +69,14 @@ type typeMeta struct { // (`get pod bar` vs `get pods bar`) // TODO these maps should be keyed based on GroupVersionKinds type DefaultRESTMapper struct { - mapping map[string]typeMeta - reverse map[typeMeta]string - scopes map[typeMeta]RESTScope - groupVersions []unversioned.GroupVersion - plurals map[string]string - singulars map[string]string + defaultGroupVersions []unversioned.GroupVersion + + resourceToKind map[string]unversioned.GroupVersionKind + kindToPluralResource map[unversioned.GroupVersionKind]string + kindToScope map[unversioned.GroupVersionKind]RESTScope + singularToPlural map[string]string + pluralToSingular map[string]string + interfacesFunc VersionInterfacesFunc } @@ -94,54 +89,41 @@ type VersionInterfacesFunc func(apiVersion string) (*VersionInterfaces, error) // and the Kubernetes API conventions. Takes a group name, a priority list of the versions // to search when an object has no default version (set empty to return an error), // and a function that retrieves the correct codec and metadata for a given version. -// TODO remove group when this API is fixed. It is no longer used. -// The external API for a RESTMapper is cross-version and this is currently called using -// group/version tuples. In the end, the structure may be easier to understand with -// a GroupRESTMapper and CrossGroupRESTMapper, but for now, this one is constructed and -// used a CrossGroupRESTMapper. -func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesFunc) *DefaultRESTMapper { - mapping := make(map[string]typeMeta) - reverse := make(map[typeMeta]string) - scopes := make(map[typeMeta]RESTScope) - plurals := make(map[string]string) - singulars := make(map[string]string) +func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper { + resourceToKind := make(map[string]unversioned.GroupVersionKind) + kindToPluralResource := make(map[unversioned.GroupVersionKind]string) + kindToScope := make(map[unversioned.GroupVersionKind]RESTScope) + singularToPlural := make(map[string]string) + pluralToSingular := make(map[string]string) // TODO: verify name mappings work correctly when versions differ - gvs := []unversioned.GroupVersion{} - for _, gvString := range gvStrings { - gvs = append(gvs, unversioned.ParseGroupVersionOrDie(gvString)) - } - return &DefaultRESTMapper{ - mapping: mapping, - reverse: reverse, - scopes: scopes, - groupVersions: gvs, - plurals: plurals, - singulars: singulars, - interfacesFunc: f, + resourceToKind: resourceToKind, + kindToPluralResource: kindToPluralResource, + kindToScope: kindToScope, + defaultGroupVersions: defaultGroupVersions, + singularToPlural: singularToPlural, + pluralToSingular: pluralToSingular, + interfacesFunc: f, } } -func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) { - gv := unversioned.ParseGroupVersionOrDie(gvString) - - plural, singular := KindToResource(kind, mixedCase) - m.plurals[singular] = plural - m.singulars[plural] = singular - meta := typeMeta{APIVersion: gv.String(), Kind: kind} - _, ok1 := m.mapping[plural] - _, ok2 := m.mapping[strings.ToLower(plural)] +func (m *DefaultRESTMapper) Add(gvk unversioned.GroupVersionKind, scope RESTScope, mixedCase bool) { + plural, singular := KindToResource(gvk.Kind, mixedCase) + m.singularToPlural[singular] = plural + m.pluralToSingular[plural] = singular + _, ok1 := m.resourceToKind[plural] + _, ok2 := m.resourceToKind[strings.ToLower(plural)] if !ok1 && !ok2 { - m.mapping[plural] = meta - m.mapping[singular] = meta + m.resourceToKind[plural] = gvk + m.resourceToKind[singular] = gvk if strings.ToLower(plural) != plural { - m.mapping[strings.ToLower(plural)] = meta - m.mapping[strings.ToLower(singular)] = meta + m.resourceToKind[strings.ToLower(plural)] = gvk + m.resourceToKind[strings.ToLower(singular)] = gvk } } - m.reverse[meta] = plural - m.scopes[meta] = scope + m.kindToPluralResource[gvk] = plural + m.kindToScope[gvk] = scope } // KindToResource converts Kind to a resource name. @@ -173,7 +155,7 @@ func KindToResource(kind string, mixedCase bool) (plural, singular string) { // ResourceSingularizer implements RESTMapper // It converts a resource name from plural to singular (e.g., from pods to pod) func (m *DefaultRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { - singular, ok := m.singulars[resource] + singular, ok := m.pluralToSingular[resource] if !ok { return resource, fmt.Errorf("no singular of resource %q has been defined", resource) } @@ -181,25 +163,21 @@ func (m *DefaultRESTMapper) ResourceSingularizer(resource string) (singular stri } // VersionAndKindForResource implements RESTMapper -func (m *DefaultRESTMapper) VersionAndKindForResource(resource string) (defaultVersion, kind string, err error) { - meta, ok := m.mapping[strings.ToLower(resource)] +func (m *DefaultRESTMapper) VersionAndKindForResource(resource string) (gvString, kind string, err error) { + gvk, ok := m.resourceToKind[strings.ToLower(resource)] if !ok { return "", "", fmt.Errorf("in version and kind for resource, no resource %q has been defined", resource) } - return meta.APIVersion, meta.Kind, nil + return gvk.GroupVersion().String(), gvk.Kind, nil } func (m *DefaultRESTMapper) GroupForResource(resource string) (string, error) { - typemeta, exists := m.mapping[strings.ToLower(resource)] + gvk, exists := m.resourceToKind[strings.ToLower(resource)] if !exists { return "", fmt.Errorf("in group for resource, no resource %q has been defined", resource) } - gv, err := unversioned.ParseGroupVersion(typemeta.APIVersion) - if err != nil { - return "", err - } - return gv.Group, nil + return gvk.Group, nil } // RESTMapping returns a struct representing the resource path and conversion interfaces a @@ -223,16 +201,18 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM return nil, err } + currGVK := currGroupVersion.WithKind(kind) hadVersion = true - if _, ok := m.reverse[typeMeta{APIVersion: currGroupVersion.String(), Kind: kind}]; ok { + if _, ok := m.kindToPluralResource[currGVK]; ok { groupVersion = &currGroupVersion break } } // Use the default preferred versions if !hadVersion && (groupVersion == nil) { - for _, currGroupVersion := range m.groupVersions { - if _, ok := m.reverse[typeMeta{APIVersion: currGroupVersion.String(), Kind: kind}]; ok { + for _, currGroupVersion := range m.defaultGroupVersions { + currGVK := currGroupVersion.WithKind(kind) + if _, ok := m.kindToPluralResource[currGVK]; ok { groupVersion = &currGroupVersion break } @@ -242,14 +222,14 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM return nil, fmt.Errorf("no kind named %q is registered in versions %q", kind, versions) } - gvk := unversioned.NewGroupVersionKind(*groupVersion, kind) + gvk := groupVersion.WithKind(kind) // Ensure we have a REST mapping - resource, ok := m.reverse[typeMeta{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind}] + resource, ok := m.kindToPluralResource[gvk] if !ok { found := []unversioned.GroupVersion{} - for _, gv := range m.groupVersions { - if _, ok := m.reverse[typeMeta{APIVersion: gv.String(), Kind: kind}]; ok { + for _, gv := range m.defaultGroupVersions { + if _, ok := m.kindToPluralResource[gvk]; ok { found = append(found, gv) } } @@ -260,7 +240,7 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM } // Ensure we have a REST scope - scope, ok := m.scopes[typeMeta{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind}] + scope, ok := m.kindToScope[gvk] if !ok { return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion().String(), gvk.Kind) } diff --git a/pkg/api/meta/restmapper_test.go b/pkg/api/meta/restmapper_test.go index 477db07abef..450d3cc20fd 100644 --- a/pkg/api/meta/restmapper_test.go +++ b/pkg/api/meta/restmapper_test.go @@ -96,21 +96,23 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { MixedCase bool Err bool }{ - {Resource: "internalobjec", Err: true, GroupVersionToRegister: testGroupVersion}, - {Resource: "internalObjec", Err: true, GroupVersionToRegister: testGroupVersion}, + {Resource: "internalobjec", Err: true}, + {Resource: "internalObjec", Err: true}, - {Resource: "internalobject", GroupVersionToRegister: testGroupVersion, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, - {Resource: "internalobjects", GroupVersionToRegister: testGroupVersion, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, + {Resource: "internalobject", ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, + {Resource: "internalobjects", ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - {Resource: "internalobject", GroupVersionToRegister: testGroupVersion, MixedCase: true, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, - {Resource: "internalobjects", GroupVersionToRegister: testGroupVersion, MixedCase: true, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, + {Resource: "internalobject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, + {Resource: "internalobjects", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - {Resource: "internalObject", GroupVersionToRegister: testGroupVersion, MixedCase: true, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, - {Resource: "internalObjects", GroupVersionToRegister: testGroupVersion, MixedCase: true, ExpectedGVK: unversioned.NewGroupVersionKind(testGroupVersion, "InternalObject")}, + {Resource: "internalObject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, + {Resource: "internalObjects", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testGroup, []string{testGroupVersion.String()}, fakeInterfaces) - mapper.Add(RESTScopeNamespace, testCase.ExpectedGVK.Kind, testCase.GroupVersionToRegister.String(), testCase.MixedCase) + mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces) + if len(testCase.ExpectedGVK.Kind) != 0 { + mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace, testCase.MixedCase) + } v, k, err := mapper.VersionAndKindForResource(testCase.Resource) hasErr := err != nil @@ -137,19 +139,18 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { func TestRESTMapperGroupForResource(t *testing.T) { testCases := []struct { - Resource string - Kind string - GroupVersion unversioned.GroupVersion - Err bool + Resource string + GroupVersionKind unversioned.GroupVersionKind + Err bool }{ - {Resource: "myObject", Kind: "MyObject", GroupVersion: unversioned.GroupVersion{Group: "testapi", Version: "test"}}, - {Resource: "myobject", Kind: "MyObject", GroupVersion: unversioned.GroupVersion{Group: "testapi2", Version: "test"}}, - {Resource: "myObje", Err: true, Kind: "MyObject", GroupVersion: unversioned.GroupVersion{Group: "testapi", Version: "test"}}, - {Resource: "myobje", Err: true, Kind: "MyObject", GroupVersion: unversioned.GroupVersion{Group: "testapi", Version: "test"}}, + {Resource: "myObject", GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, + {Resource: "myobject", GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}}, + {Resource: "myObje", Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, + {Resource: "myobje", Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, } for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.GroupVersion.Group, []string{testCase.GroupVersion.String()}, fakeInterfaces) - mapper.Add(RESTScopeNamespace, testCase.Kind, testCase.GroupVersion.String(), false) + mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces) + mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace, false) g, err := mapper.GroupForResource(testCase.Resource) if testCase.Err { if err == nil { @@ -157,8 +158,8 @@ func TestRESTMapperGroupForResource(t *testing.T) { } } else if err != nil { t.Errorf("%d: unexpected error: %v", i, err) - } else if g != testCase.GroupVersion.Group { - t.Errorf("%d: expected group %q, got %q", i, testCase.GroupVersion.Group, g) + } else if g != testCase.GroupVersionKind.Group { + t.Errorf("%d: expected group %q, got %q", i, testCase.GroupVersionKind.Group, g) } } } @@ -193,6 +194,8 @@ func TestKindToResource(t *testing.T) { } func TestRESTMapperResourceSingularizer(t *testing.T) { + testGroupVersion := unversioned.GroupVersion{Group: "tgroup", Version: "test"} + testCases := []struct { Kind string MixedCase bool @@ -216,11 +219,9 @@ func TestRESTMapperResourceSingularizer(t *testing.T) { {Kind: "lowercases", MixedCase: false, Plural: "lowercases", Singular: "lowercases"}, } for i, testCase := range testCases { - testGroupVersion := unversioned.GroupVersion{Group: "tgroup", Version: "test"} - - mapper := NewDefaultRESTMapper(testGroupVersion.Group, []string{testGroupVersion.String()}, fakeInterfaces) + mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces) // create singular/plural mapping - mapper.Add(RESTScopeNamespace, testCase.Kind, testGroupVersion.String(), testCase.MixedCase) + mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace, testCase.MixedCase) singular, _ := mapper.ResourceSingularizer(testCase.Plural) if singular != testCase.Singular { @@ -232,12 +233,13 @@ func TestRESTMapperResourceSingularizer(t *testing.T) { func TestRESTMapperRESTMapping(t *testing.T) { testGroup := "tgroup" testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"} + internalGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"} testCases := []struct { Kind string APIGroupVersions []unversioned.GroupVersion MixedCase bool - DefaultVersions []string + DefaultVersions []unversioned.GroupVersion Resource string ExpectedGroupVersion *unversioned.GroupVersion @@ -246,25 +248,23 @@ func TestRESTMapperRESTMapping(t *testing.T) { {Kind: "Unknown", Err: true}, {Kind: "InternalObject", Err: true}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "Unknown", Err: true}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &unversioned.GroupVersion{Group: testGroup, Version: "test"}}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &unversioned.GroupVersion{Group: testGroup, Version: "test"}}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []string{testGroupVersion.String()}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, MixedCase: true, Resource: "internalObjects"}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, + {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, MixedCase: true, Resource: "internalObjects"}, // TODO: add test for a resource that exists in one version but not another } for i, testCase := range testCases { - internalGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"} - - mapper := NewDefaultRESTMapper(testGroup, testCase.DefaultVersions, fakeInterfaces) - mapper.Add(RESTScopeNamespace, "InternalObject", internalGroupVersion.String(), testCase.MixedCase) + mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) + mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace, testCase.MixedCase) deprecatedGroupVersionStrings := []string{} for _, gv := range testCase.APIGroupVersions { @@ -303,9 +303,9 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"} expectedGroupVersion3 := unversioned.GroupVersion{Group: "tgroup", Version: "test3"} - mapper := NewDefaultRESTMapper("tgroup", []string{expectedGroupVersion1.String(), expectedGroupVersion2.String()}, fakeInterfaces) - mapper.Add(RESTScopeNamespace, "InternalObject", expectedGroupVersion1.String(), false) - mapper.Add(RESTScopeNamespace, "OtherObject", expectedGroupVersion2.String(), false) + mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces) + mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace, false) + mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace, false) // pick default matching object kind based on search order mapping, err := mapper.RESTMapping("OtherObject") @@ -359,8 +359,8 @@ func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) { expectedGroupVersion1 := unversioned.GroupVersion{Group: "tgroup", Version: "test1"} expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"} - mapper := NewDefaultRESTMapper("tgroup", []string{expectedGroupVersion1.String(), expectedGroupVersion2.String()}, unmatchedVersionInterfaces) - mapper.Add(RESTScopeNamespace, "InternalObject", expectedGroupVersion1.String(), false) + mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces) + mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace, false) _, err := mapper.RESTMapping("InternalObject", expectedGroupVersion1.String()) if err == nil { t.Errorf("unexpected non-error") diff --git a/pkg/api/registered/registered.go b/pkg/api/registered/registered.go index 06dc4166346..6040c542e5c 100644 --- a/pkg/api/registered/registered.go +++ b/pkg/api/registered/registered.go @@ -22,46 +22,60 @@ import ( "strings" "github.com/golang/glog" - apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/unversioned" ) // List of registered API versions. // The list is in the order of most preferred to the least. -var RegisteredVersions []string +var RegisteredGroupVersions []unversioned.GroupVersion func init() { - validGroupVersions := map[string]bool{ - "v1": true, - "extensions/v1beta1": true, - "componentconfig/v1alpha1": true, - "metrics/v1alpha1": true, + validGroupVersions := map[unversioned.GroupVersion]bool{ + unversioned.GroupVersion{Group: "", Version: "v1"}: true, + unversioned.GroupVersion{Group: "extensions", Version: "v1beta1"}: true, + unversioned.GroupVersion{Group: "componentconfig", Version: "v1alpha1"}: true, + unversioned.GroupVersion{Group: "metrics", Version: "v1alpha1"}: true, } // The default list of supported api versions, in order of most preferred to the least. - defaultSupportedVersions := "v1,extensions/v1beta1,componentconfig/v1alpha1" + supportedVersions := []unversioned.GroupVersion{ + {Group: "", Version: "v1"}, + {Group: "extensions", Version: "v1beta1"}, + {Group: "componentconfig", Version: "v1alpha1"}, + } + // Env var KUBE_API_VERSIONS is a comma separated list of API versions that should be registered in the scheme. // The versions should be in the order of most preferred to the least. - supportedVersions := os.Getenv("KUBE_API_VERSIONS") - if supportedVersions == "" { - supportedVersions = defaultSupportedVersions - } - versions := strings.Split(supportedVersions, ",") - for _, version := range versions { - // Verify that the version is valid. - valid, ok := validGroupVersions[version] - if !ok || !valid { - // Not a valid API version. - glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s. List of valid API versions: %v", - version, os.Getenv("KUBE_API_VERSIONS"), validGroupVersions) + userRequestedVersions := os.Getenv("KUBE_API_VERSIONS") + if len(userRequestedVersions) != 0 { + // reset the supported versions + supportedVersions = []unversioned.GroupVersion{} + for _, version := range strings.Split(userRequestedVersions, ",") { + gv, err := unversioned.ParseGroupVersion(version) + if err != nil { + glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s. List of valid API versions: %v", + version, os.Getenv("KUBE_API_VERSIONS"), validGroupVersions) + } + + // Verify that the version is valid. + valid, ok := validGroupVersions[gv] + if !ok || !valid { + // Not a valid API version. + glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s. List of valid API versions: %v", + version, os.Getenv("KUBE_API_VERSIONS"), validGroupVersions) + } + + supportedVersions = append(supportedVersions, gv) } - RegisteredVersions = append(RegisteredVersions, version) } + + RegisteredGroupVersions = supportedVersions } // Returns true if the given api version is one of the registered api versions. -func IsRegisteredAPIVersion(version string) bool { - for _, apiVersion := range RegisteredVersions { - if apiVersion == version { +func IsRegisteredAPIGroupVersion(gv unversioned.GroupVersion) bool { + for _, currGV := range RegisteredGroupVersions { + if currGV == gv { return true } } @@ -70,10 +84,10 @@ func IsRegisteredAPIVersion(version string) bool { // GroupVersionsForGroup returns the registered versions of a group in the form // of "group/version". -func GroupVersionsForGroup(group string) []string { - ret := []string{} - for _, v := range RegisteredVersions { - if apiutil.GetGroup(v) == group { +func GroupVersionsForGroup(group string) []unversioned.GroupVersion { + ret := []unversioned.GroupVersion{} + for _, v := range RegisteredGroupVersions { + if v.Group == group { ret = append(ret, v) } } diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index b6d7a86fcfb..d2026c5f969 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -291,9 +291,9 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer { ev.ValueFrom = &api.EnvVarSource{} ev.ValueFrom.FieldRef = &api.ObjectFieldSelector{} - versions := registered.RegisteredVersions + versions := registered.RegisteredGroupVersions - ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))] + ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))].String() ev.ValueFrom.FieldRef.FieldPath = c.RandString() } }, diff --git a/pkg/api/unversioned/group_version.go b/pkg/api/unversioned/group_version.go index 1b925156620..82826b4ba22 100644 --- a/pkg/api/unversioned/group_version.go +++ b/pkg/api/unversioned/group_version.go @@ -30,6 +30,7 @@ type GroupVersionKind struct { Kind string } +// TODO remove this func NewGroupVersionKind(gv GroupVersion, kind string) GroupVersionKind { return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} } @@ -84,6 +85,10 @@ func ParseGroupVersionOrDie(gv string) GroupVersion { return ret } +func (gv GroupVersion) WithKind(kind string) GroupVersionKind { + return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} +} + // MarshalJSON implements the json.Marshaller interface. func (gv GroupVersion) MarshalJSON() ([]byte, error) { s := gv.String() diff --git a/pkg/api/v1/register.go b/pkg/api/v1/register.go index 9957c98bf73..6b8ab7172eb 100644 --- a/pkg/api/v1/register.go +++ b/pkg/api/v1/register.go @@ -28,7 +28,7 @@ var Codec = runtime.CodecFor(api.Scheme, "v1") func init() { // Check if v1 is in the list of supported API versions. - if !registered.IsRegisteredAPIVersion("v1") { + if !registered.IsRegisteredAPIGroupVersion(unversioned.GroupVersion{Group: "", Version: "v1"}) { return } diff --git a/pkg/apis/componentconfig/install/install.go b/pkg/apis/componentconfig/install/install.go index 6fe691e86d5..9ae7d3a477d 100644 --- a/pkg/apis/componentconfig/install/install.go +++ b/pkg/apis/componentconfig/install/install.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" - apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" "k8s.io/kubernetes/pkg/runtime" @@ -45,19 +45,23 @@ func init() { glog.V(4).Infof("%v", err) return } + + worstToBestGroupVersions := []unversioned.GroupVersion{} + registeredGroupVersions := registered.GroupVersionsForGroup("componentconfig") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ - GroupVersion: groupVersion, - Group: apiutil.GetGroup(groupVersion), - Version: apiutil.GetVersion(groupVersion), - Codec: runtime.CodecFor(api.Scheme, groupVersion), + GroupVersion: groupVersion.String(), + Group: groupVersion.Group, + Version: groupVersion.Version, + Codec: runtime.CodecFor(api.Scheme, groupVersion.String()), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { - versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) - groupVersions = append(groupVersions, registeredGroupVersions[i]) + versions = append(versions, registeredGroupVersions[i].Version) + groupVersions = append(groupVersions, registeredGroupVersions[i].String()) + worstToBestGroupVersions = append(worstToBestGroupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions @@ -70,7 +74,7 @@ func init() { ignoredKinds := sets.NewString() - groupMeta.RESTMapper = api.NewDefaultRESTMapper("componentconfig", groupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + groupMeta.RESTMapper = api.NewDefaultRESTMapper(worstToBestGroupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) api.RegisterRESTMapper(groupMeta.RESTMapper) groupMeta.InterfacesFor = interfacesFor } diff --git a/pkg/apis/extensions/install/install.go b/pkg/apis/extensions/install/install.go index 100dcfdbf92..f16343340f7 100644 --- a/pkg/apis/extensions/install/install.go +++ b/pkg/apis/extensions/install/install.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" - apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" "k8s.io/kubernetes/pkg/runtime" @@ -45,19 +45,23 @@ func init() { glog.V(4).Infof("%v", err) return } + + worstToBestGroupVersions := []unversioned.GroupVersion{} + registeredGroupVersions := registered.GroupVersionsForGroup("extensions") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ - GroupVersion: groupVersion, - Group: apiutil.GetGroup(groupVersion), - Version: apiutil.GetVersion(groupVersion), - Codec: runtime.CodecFor(api.Scheme, groupVersion), + GroupVersion: groupVersion.String(), + Group: groupVersion.Group, + Version: groupVersion.Version, + Codec: runtime.CodecFor(api.Scheme, groupVersion.String()), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { - versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) - groupVersions = append(groupVersions, registeredGroupVersions[i]) + versions = append(versions, registeredGroupVersions[i].Version) + groupVersions = append(groupVersions, registeredGroupVersions[i].String()) + worstToBestGroupVersions = append(worstToBestGroupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions @@ -70,7 +74,7 @@ func init() { ignoredKinds := sets.NewString() - groupMeta.RESTMapper = api.NewDefaultRESTMapper("extensions", groupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + groupMeta.RESTMapper = api.NewDefaultRESTMapper(worstToBestGroupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) api.RegisterRESTMapper(groupMeta.RESTMapper) groupMeta.InterfacesFor = interfacesFor } diff --git a/pkg/apis/metrics/install/install.go b/pkg/apis/metrics/install/install.go index 1c847164c56..ae7baf2a718 100644 --- a/pkg/apis/metrics/install/install.go +++ b/pkg/apis/metrics/install/install.go @@ -28,7 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" - apiutil "k8s.io/kubernetes/pkg/api/util" + "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/apis/metrics" "k8s.io/kubernetes/pkg/apis/metrics/v1alpha1" "k8s.io/kubernetes/pkg/runtime" @@ -45,19 +45,23 @@ func init() { glog.V(4).Infof("%v", err) return } + + worstToBestGroupVersions := []unversioned.GroupVersion{} + registeredGroupVersions := registered.GroupVersionsForGroup("metrics") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ - GroupVersion: groupVersion, - Group: apiutil.GetGroup(groupVersion), - Version: apiutil.GetVersion(groupVersion), - Codec: runtime.CodecFor(api.Scheme, groupVersion), + GroupVersion: groupVersion.String(), + Group: groupVersion.Group, + Version: groupVersion.Version, + Codec: runtime.CodecFor(api.Scheme, groupVersion.String()), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { - versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) - groupVersions = append(groupVersions, registeredGroupVersions[i]) + versions = append(versions, registeredGroupVersions[i].Version) + groupVersions = append(groupVersions, registeredGroupVersions[i].String()) + worstToBestGroupVersions = append(worstToBestGroupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions @@ -70,7 +74,7 @@ func init() { ignoredKinds := sets.NewString() - groupMeta.RESTMapper = api.NewDefaultRESTMapper("metrics", groupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) + groupMeta.RESTMapper = api.NewDefaultRESTMapper(worstToBestGroupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) api.RegisterRESTMapper(groupMeta.RESTMapper) groupMeta.InterfacesFor = interfacesFor } diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 07f90ed758d..be8d56e4d26 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -107,8 +107,7 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) { } func newMapper() *meta.DefaultRESTMapper { - gvStrings := []string{testGroupVersion.String(), newGroupVersion.String()} - return meta.NewDefaultRESTMapper(testAPIGroup, gvStrings, interfacesFor) + return meta.NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion, newGroupVersion}, interfacesFor) } func addGrouplessTypes() { @@ -149,11 +148,13 @@ func init() { // the mapper how to address our resources for _, gv := range groupVersions { for kind := range api.Scheme.KnownTypes(gv.String()) { + gvk := gv.WithKind(kind) + root := bool(kind == "SimpleRoot") if root { - nsMapper.Add(meta.RESTScopeRoot, kind, gv.String(), false) + nsMapper.Add(gvk, meta.RESTScopeRoot, false) } else { - nsMapper.Add(meta.RESTScopeNamespace, kind, gv.String(), false) + nsMapper.Add(gvk, meta.RESTScopeNamespace, false) } } } diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index 296dca5c196..3fd3995a1f7 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -294,7 +294,11 @@ func (c *Fake) ServerAPIVersions() (*unversioned.APIVersions, error) { action.Resource = "apiversions" c.Invokes(action, nil) - return &unversioned.APIVersions{Versions: registered.RegisteredVersions}, nil + gvStrings := []string{} + for _, gv := range registered.RegisteredGroupVersions { + gvStrings = append(gvStrings, gv.String()) + } + return &unversioned.APIVersions{Versions: gvStrings}, nil } func (c *Fake) ComponentStatuses() client.ComponentStatusInterface { diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index ff8aa9f405c..f99c946f7fd 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -90,18 +90,20 @@ func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme.AddKnownTypeWithName(validVersionGV.String(), "Type", &ExternalType2{}) codec := runtime.CodecFor(scheme, unlikelyGV.String()) - mapper := meta.NewDefaultRESTMapper("apitest", []string{unlikelyGV.String(), validVersionGV.String()}, func(version string) (*meta.VersionInterfaces, error) { + mapper := meta.NewDefaultRESTMapper([]unversioned.GroupVersion{unlikelyGV, validVersionGV}, func(version string) (*meta.VersionInterfaces, error) { return &meta.VersionInterfaces{ Codec: runtime.CodecFor(scheme, version), ObjectConvertor: scheme, MetadataAccessor: meta.NewAccessor(), }, versionErrIfFalse(version == validVersionGV.String() || version == unlikelyGV.String()) }) - for _, version := range []string{unlikelyGV.String(), validVersionGV.String()} { - for kind := range scheme.KnownTypes(version) { + for _, gv := range []unversioned.GroupVersion{unlikelyGV, validVersionGV} { + for kind := range scheme.KnownTypes(gv.String()) { + gvk := gv.WithKind(kind) + mixedCase := false scope := meta.RESTScopeNamespace - mapper.Add(scope, kind, version, mixedCase) + mapper.Add(gvk, scope, mixedCase) } } diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index 8421b46c559..19b4c77834d 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -22,6 +22,7 @@ import ( "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/registered" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" @@ -95,7 +96,11 @@ type ConvertOptions struct { // Complete collects information required to run Convert command from command line. func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { o.outputVersion = cmdutil.OutputVersion(cmd, latest.GroupOrDie("").Version) - if !registered.IsRegisteredAPIVersion(o.outputVersion) { + outputGV, err := unversioned.ParseGroupVersion(o.outputVersion) + if err != nil { + return fmt.Errorf("unable to parse group/version from %q: %v", o.outputVersion, err) + } + if !registered.IsRegisteredAPIGroupVersion(outputGV) { cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion) } diff --git a/pkg/kubectl/cmd/util/clientcache.go b/pkg/kubectl/cmd/util/clientcache.go index ed74b5ddb6a..d73564af888 100644 --- a/pkg/kubectl/cmd/util/clientcache.go +++ b/pkg/kubectl/cmd/util/clientcache.go @@ -71,16 +71,8 @@ func (c *ClientCache) ClientConfigForVersion(version string) (*client.Config, er } preferredGV = &gv } - registeredGVs := []unversioned.GroupVersion{} - for _, gvString := range registered.RegisteredVersions { - gv, err := unversioned.ParseGroupVersion(gvString) - if err != nil { - return nil, err - } - registeredGVs = append(registeredGVs, gv) - } - negotiatedVersion, err := client.NegotiateVersion(c.defaultClient, &config, preferredGV, registeredGVs) + negotiatedVersion, err := client.NegotiateVersion(c.defaultClient, &config, preferredGV, registered.RegisteredGroupVersions) if err != nil { return nil, err } diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index ca826c9b3e6..47df35c20a4 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -35,6 +35,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/apis/extensions" client "k8s.io/kubernetes/pkg/client/unversioned" @@ -488,8 +489,12 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error { if err != nil { return err } - if ok := registered.IsRegisteredAPIVersion(version); !ok { - return fmt.Errorf("API version %q isn't supported, only supports API versions %q", version, registered.RegisteredVersions) + gv, err := unversioned.ParseGroupVersion(version) + if err != nil { + return fmt.Errorf("unable to parse group/version from %q: %v", version, err) + } + if ok := registered.IsRegisteredAPIGroupVersion(gv); !ok { + return fmt.Errorf("API version %q isn't supported, only supports API versions %q", version, registered.RegisteredGroupVersions) } resource, _ := meta.KindToResource(kind, false) group, err := c.mapper.GroupForResource(resource) diff --git a/pkg/kubectl/resource/mapper.go b/pkg/kubectl/resource/mapper.go index a3fc32845e7..7007dd67d03 100644 --- a/pkg/kubectl/resource/mapper.go +++ b/pkg/kubectl/resource/mapper.go @@ -23,6 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/registered" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/yaml" ) @@ -48,8 +49,12 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) { if err != nil { return nil, fmt.Errorf("unable to get type info from %q: %v", source, err) } - if ok := registered.IsRegisteredAPIVersion(version); !ok { - return nil, fmt.Errorf("API version %q in %q isn't supported, only supports API versions %q", version, source, registered.RegisteredVersions) + gv, err := unversioned.ParseGroupVersion(version) + if err != nil { + return nil, fmt.Errorf("unable to parse group/version from %q: %v", version, err) + } + if ok := registered.IsRegisteredAPIGroupVersion(gv); !ok { + return nil, fmt.Errorf("API version %q in %q isn't supported, only supports API versions %q", version, source, registered.RegisteredGroupVersions) } if kind == "" { return nil, fmt.Errorf("kind not set in %q", source) diff --git a/pkg/kubelet/config/common_test.go b/pkg/kubelet/config/common_test.go index 65f4a17b6bf..93563f1e42c 100644 --- a/pkg/kubelet/config/common_test.go +++ b/pkg/kubelet/config/common_test.go @@ -71,8 +71,8 @@ func TestDecodeSinglePod(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) } - for _, version := range registered.GroupVersionsForGroup("") { - externalPod, err := testapi.Default.Converter().ConvertToVersion(pod, version) + for _, gv := range registered.GroupVersionsForGroup("") { + externalPod, err := testapi.Default.Converter().ConvertToVersion(pod, gv.String()) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -137,8 +137,8 @@ func TestDecodePodList(t *testing.T) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", podList, &podListOut, string(json)) } - for _, version := range registered.GroupVersionsForGroup("") { - externalPodList, err := testapi.Default.Converter().ConvertToVersion(podList, version) + for _, gv := range registered.GroupVersionsForGroup("") { + externalPodList, err := testapi.Default.Converter().ConvertToVersion(podList, gv.String()) if err != nil { t.Errorf("unexpected error: %v", err) }