func TestRESTMapperVersionAndKindForResource(t *testing.T) { testGroup := "test.group" testVersion := "test" testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: testVersion} testCases := []struct { Resource string GroupVersionToRegister unversioned.GroupVersion ExpectedGVK unversioned.GroupVersionKind MixedCase bool Err bool }{ {Resource: "internalobjec", Err: true}, {Resource: "internalObjec", Err: true}, {Resource: "internalobject", ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: "internalobjects", ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: "internalobject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: "internalobjects", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: "internalObject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: "internalObjects", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, } for i, testCase := range testCases { 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 if hasErr != testCase.Err { t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err) continue } if err != nil { continue } actualGV, err := unversioned.ParseGroupVersion(v) if err != nil { t.Errorf("%d: unexpected error: %v", i, err) continue } actualGVK := unversioned.NewGroupVersionKind(actualGV, k) if actualGVK != testCase.ExpectedGVK { t.Errorf("%d: unexpected version and kind: e=%s a=%s", i, testCase.ExpectedGVK, actualGVK) } } }
// RESTMapping returns a struct representing the resource path and conversion interfaces a // RESTClient should use to operate on the provided kind in order of versions. If a version search // order is not provided, the search order provided to DefaultRESTMapper will be used to resolve which // APIVersion should be used to access the named kind. // TODO version here in this RESTMapper means just APIVersion, but the RESTMapper API is intended to handle multiple groups // So this API is broken. The RESTMapper test made it clear that versions here were API versions, but the code tries to use // them with group/version tuples. // TODO this should probably become RESTMapping(GroupKind, versions ...string) func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTMapping, error) { // Pick an appropriate version var groupVersion *unversioned.GroupVersion hadVersion := false for _, v := range versions { if len(v) == 0 { continue } currGroupVersion, err := unversioned.ParseGroupVersion(v) if err != nil { return nil, err } hadVersion = true if _, ok := m.reverse[typeMeta{APIVersion: currGroupVersion.String(), Kind: kind}]; 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 { groupVersion = &currGroupVersion break } } } if groupVersion == nil { return nil, fmt.Errorf("no kind named %q is registered in versions %q", kind, versions) } gvk := unversioned.NewGroupVersionKind(*groupVersion, kind) // Ensure we have a REST mapping resource, ok := m.reverse[typeMeta{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind}] if !ok { found := []unversioned.GroupVersion{} for _, gv := range m.groupVersions { if _, ok := m.reverse[typeMeta{APIVersion: gv.String(), Kind: kind}]; ok { found = append(found, gv) } } if len(found) > 0 { return nil, fmt.Errorf("object with kind %q exists in versions %v, not %v", kind, found, *groupVersion) } return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported object", groupVersion, kind) } // Ensure we have a REST scope scope, ok := m.scopes[typeMeta{APIVersion: gvk.GroupVersion().String(), Kind: gvk.Kind}] 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) } interfaces, err := m.interfacesFunc(gvk.GroupVersion().String()) if err != nil { return nil, fmt.Errorf("the provided version %q has no relevant versions", gvk.GroupVersion().String()) } retVal := &RESTMapping{ Resource: resource, GroupVersionKind: gvk, Scope: scope, Codec: interfaces.Codec, ObjectConvertor: interfaces.ObjectConvertor, MetadataAccessor: interfaces.MetadataAccessor, } return retVal, nil }