diff --git a/pkg/api/mapper.go b/pkg/api/mapper.go index e2468fdadf3..054f74d5e99 100644 --- a/pkg/api/mapper.go +++ b/pkg/api/mapper.go @@ -53,7 +53,7 @@ func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, inter if rootScoped.Has(kind) { scope = meta.RESTScopeRoot } - mapper.Add(gvk, scope, false) + mapper.Add(gvk, scope) } } return mapper diff --git a/pkg/api/meta/restmapper.go b/pkg/api/meta/restmapper.go index a9873e35eee..d6ad4360069 100644 --- a/pkg/api/meta/restmapper.go +++ b/pkg/api/meta/restmapper.go @@ -117,57 +117,50 @@ func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, f Ver } } -func (m *DefaultRESTMapper) Add(kind unversioned.GroupVersionKind, scope RESTScope, mixedCase bool) { - plural, singular := KindToResource(kind, mixedCase) - lowerPlural := plural.GroupVersion().WithResource(strings.ToLower(plural.Resource)) - lowerSingular := singular.GroupVersion().WithResource(strings.ToLower(singular.Resource)) +func (m *DefaultRESTMapper) Add(kind unversioned.GroupVersionKind, scope RESTScope) { + plural, singular := KindToResource(kind) m.singularToPlural[singular] = plural m.pluralToSingular[plural] = singular - m.singularToPlural[lowerSingular] = lowerPlural - m.pluralToSingular[lowerPlural] = lowerSingular - if _, mixedCaseExists := m.resourceToKind[plural]; !mixedCaseExists { - m.resourceToKind[plural] = kind - m.resourceToKind[singular] = kind - } - - if _, lowerCaseExists := m.resourceToKind[lowerPlural]; !lowerCaseExists && (lowerPlural != plural) { - m.resourceToKind[lowerPlural] = kind - m.resourceToKind[lowerSingular] = kind - } + m.resourceToKind[singular] = kind + m.resourceToKind[plural] = kind m.kindToPluralResource[kind] = plural m.kindToScope[kind] = scope } +// unpluralizedSuffixes is a list of resource suffixes that are the same plural and singular +// This is only is only necessary because some bits of code are lazy and don't actually use the RESTMapper like they should. +// TODO eliminate this so that different callers can correctly map to resources. This probably means updating all +// callers to use the RESTMapper they mean. +var unpluralizedSuffixes = []string{ + "endpoints", +} + // KindToResource converts Kind to a resource name. -func KindToResource(kind unversioned.GroupVersionKind, mixedCase bool) (plural, singular unversioned.GroupVersionResource) { +func KindToResource(kind unversioned.GroupVersionKind) ( /*plural*/ unversioned.GroupVersionResource /*singular*/, unversioned.GroupVersionResource) { kindName := kind.Kind if len(kindName) == 0 { - return - } - if mixedCase { - // Legacy support for mixed case names - singular = kind.GroupVersion().WithResource(strings.ToLower(kindName[:1]) + kindName[1:]) - } else { - singular = kind.GroupVersion().WithResource(strings.ToLower(kindName)) + return unversioned.GroupVersionResource{}, unversioned.GroupVersionResource{} } + singularName := strings.ToLower(kindName) + singular := kind.GroupVersion().WithResource(singularName) - singularName := singular.Resource - if strings.HasSuffix(singularName, "endpoints") { - plural = singular - } else { - switch string(singularName[len(singularName)-1]) { - case "s": - plural = kind.GroupVersion().WithResource(singularName + "es") - case "y": - plural = kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies") - default: - plural = kind.GroupVersion().WithResource(singularName + "s") + for _, skip := range unpluralizedSuffixes { + if strings.HasSuffix(singularName, skip) { + return singular, singular } } - return + + switch string(singularName[len(singularName)-1]) { + case "s": + return kind.GroupVersion().WithResource(singularName + "es"), singular + case "y": + return kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies"), singular + } + + return kind.GroupVersion().WithResource(singularName + "s"), singular } // ResourceSingularizer implements RESTMapper diff --git a/pkg/api/meta/restmapper_test.go b/pkg/api/meta/restmapper_test.go index 17525df502e..0f7b0fcd9d6 100644 --- a/pkg/api/meta/restmapper_test.go +++ b/pkg/api/meta/restmapper_test.go @@ -62,7 +62,6 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { Resource unversioned.GroupVersionResource GroupVersionToRegister unversioned.GroupVersion ExpectedGVK unversioned.GroupVersionKind - MixedCase bool Err bool }{ {Resource: unversioned.GroupVersionResource{Resource: "internalobjec"}, Err: true}, @@ -70,17 +69,11 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) { {Resource: unversioned.GroupVersionResource{Resource: "internalobject"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, {Resource: unversioned.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - - {Resource: unversioned.GroupVersionResource{Resource: "internalobject"}, MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - {Resource: unversioned.GroupVersionResource{Resource: "internalobjects"}, MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - - {Resource: unversioned.GroupVersionResource{Resource: "internalObject"}, MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - {Resource: unversioned.GroupVersionResource{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) + mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace) } actualGVK, err := mapper.KindFor(testCase.Resource) @@ -112,7 +105,7 @@ func TestRESTMapperGroupForResource(t *testing.T) { } for i, testCase := range testCases { mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces) - mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace, false) + mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace) actualGVK, err := mapper.KindFor(testCase.Resource) if testCase.Err { @@ -202,7 +195,7 @@ func TestRESTMapperKindsFor(t *testing.T) { tcName := testCase.Name mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) for _, kind := range testCase.KindsToRegister { - mapper.Add(kind, RESTScopeNamespace, false) + mapper.Add(kind, RESTScopeNamespace) } actualKinds, err := mapper.KindsFor(testCase.PartialResourceToRequest) @@ -314,7 +307,7 @@ func TestRESTMapperResourcesFor(t *testing.T) { tcName := testCase.Name mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) for _, kind := range testCase.KindsToRegister { - mapper.Add(kind, RESTScopeNamespace, false) + mapper.Add(kind, RESTScopeNamespace) } actualResources, err := mapper.ResourcesFor(testCase.PartialResourceToRequest) @@ -354,28 +347,23 @@ func TestRESTMapperResourcesFor(t *testing.T) { func TestKindToResource(t *testing.T) { testCases := []struct { Kind string - MixedCase bool Plural, Singular string }{ - {Kind: "Pod", MixedCase: true, Plural: "pods", Singular: "pod"}, - {Kind: "Pod", MixedCase: true, Plural: "pods", Singular: "pod"}, - {Kind: "Pod", MixedCase: false, Plural: "pods", Singular: "pod"}, + {Kind: "Pod", Plural: "pods", Singular: "pod"}, - {Kind: "ReplicationController", MixedCase: true, Plural: "replicationControllers", Singular: "replicationController"}, - {Kind: "ReplicationController", MixedCase: true, Plural: "replicationControllers", Singular: "replicationController"}, - {Kind: "ReplicationController", MixedCase: false, Plural: "replicationcontrollers", Singular: "replicationcontroller"}, + {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"}, // Add "ies" when ending with "y" - {Kind: "ImageRepository", MixedCase: true, Plural: "imageRepositories", Singular: "imageRepository"}, + {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"}, // Add "es" when ending with "s" - {Kind: "miss", MixedCase: false, Plural: "misses", Singular: "miss"}, + {Kind: "miss", Plural: "misses", Singular: "miss"}, // Add "s" otherwise - {Kind: "lowercase", MixedCase: false, Plural: "lowercases", Singular: "lowercase"}, + {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"}, } for i, testCase := range testCases { version := unversioned.GroupVersion{} - plural, singular := KindToResource(version.WithKind(testCase.Kind), testCase.MixedCase) + plural, singular := KindToResource(version.WithKind(testCase.Kind)) if singular != version.WithResource(testCase.Singular) || plural != version.WithResource(testCase.Plural) { t.Errorf("%d: unexpected plural and singular: %v %v", i, plural, singular) } @@ -386,32 +374,24 @@ func TestRESTMapperResourceSingularizer(t *testing.T) { testGroupVersion := unversioned.GroupVersion{Group: "tgroup", Version: "test"} testCases := []struct { - Kind string - MixedCase bool - Plural string - Singular string + Kind string + Plural string + Singular string }{ - {Kind: "Pod", MixedCase: true, Plural: "pods", Singular: "pod"}, - {Kind: "Pod", MixedCase: false, Plural: "pods", Singular: "pod"}, + {Kind: "Pod", Plural: "pods", Singular: "pod"}, + {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"}, + {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"}, + {Kind: "Status", Plural: "statuses", Singular: "status"}, - {Kind: "ReplicationController", MixedCase: true, Plural: "replicationControllers", Singular: "replicationController"}, - {Kind: "ReplicationController", MixedCase: false, Plural: "replicationcontrollers", Singular: "replicationcontroller"}, - - {Kind: "ImageRepository", MixedCase: true, Plural: "imageRepositories", Singular: "imageRepository"}, - {Kind: "ImageRepository", MixedCase: false, Plural: "imagerepositories", Singular: "imagerepository"}, - - {Kind: "Status", MixedCase: true, Plural: "statuses", Singular: "status"}, - {Kind: "Status", MixedCase: false, Plural: "statuses", Singular: "status"}, - - {Kind: "lowercase", MixedCase: false, Plural: "lowercases", Singular: "lowercase"}, + {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"}, // TODO this test is broken. This updates to reflect actual behavior. Kinds are expected to be singular // old (incorrect), coment: Don't add extra s if the original object is already plural - {Kind: "lowercases", MixedCase: false, Plural: "lowercaseses", Singular: "lowercases"}, + {Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"}, } for i, testCase := range testCases { mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces) // create singular/plural mapping - mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace, testCase.MixedCase) + mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace) singular, err := mapper.ResourceSingularizer(testCase.Plural) if err != nil { @@ -431,7 +411,6 @@ func TestRESTMapperRESTMapping(t *testing.T) { testCases := []struct { Kind string APIGroupVersions []unversioned.GroupVersion - MixedCase bool DefaultVersions []unversioned.GroupVersion Resource string @@ -451,13 +430,12 @@ func TestRESTMapperRESTMapping(t *testing.T) { {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &unversioned.GroupVersion{Group: testGroup, Version: "test"}}, {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 { mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) - mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace, testCase.MixedCase) + mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace) preferredVersions := []string{} for _, gv := range testCase.APIGroupVersions { @@ -500,8 +478,8 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { otherObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "OtherObject"} mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces) - mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace, false) - mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace, false) + mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) + mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace) // pick default matching object kind based on search order mapping, err := mapper.RESTMapping(otherObjectGK) @@ -557,7 +535,7 @@ func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) { internalObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "InternalObject"} mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces) - mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace, false) + mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) _, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version) if err == nil { t.Errorf("unexpected non-error") diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index e5adcc95512..f997cd4c5e0 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -179,9 +179,9 @@ func init() { gvk := gv.WithKind(kind) root := bool(kind == "SimpleRoot") if root { - nsMapper.Add(gvk, meta.RESTScopeRoot, false) + nsMapper.Add(gvk, meta.RESTScopeRoot) } else { - nsMapper.Add(gvk, meta.RESTScopeNamespace, false) + nsMapper.Add(gvk, meta.RESTScopeNamespace) } } } diff --git a/pkg/client/typed/generated/extensions/unversioned/scale_expansion.go b/pkg/client/typed/generated/extensions/unversioned/scale_expansion.go index 3606a5f7b9c..61a77f260d5 100644 --- a/pkg/client/typed/generated/extensions/unversioned/scale_expansion.go +++ b/pkg/client/typed/generated/extensions/unversioned/scale_expansion.go @@ -34,7 +34,7 @@ func (c *scales) Get(kind string, name string) (result *extensions.Scale, err er // TODO this method needs to take a proper unambiguous kind fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind} - resource, _ := meta.KindToResource(fullyQualifiedKind, false) + resource, _ := meta.KindToResource(fullyQualifiedKind) err = c.client.Get(). Namespace(c.ns). @@ -51,7 +51,7 @@ func (c *scales) Update(kind string, scale *extensions.Scale) (result *extension // TODO this method needs to take a proper unambiguous kind fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind} - resource, _ := meta.KindToResource(fullyQualifiedKind, false) + resource, _ := meta.KindToResource(fullyQualifiedKind) err = c.client.Put(). Namespace(scale.Namespace). diff --git a/pkg/client/unversioned/scale.go b/pkg/client/unversioned/scale.go index 4064ce4dd49..705f6048b59 100644 --- a/pkg/client/unversioned/scale.go +++ b/pkg/client/unversioned/scale.go @@ -52,7 +52,7 @@ func (c *scales) Get(kind string, name string) (result *extensions.Scale, err er // TODO this method needs to take a proper unambiguous kind fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind} - resource, _ := meta.KindToResource(fullyQualifiedKind, false) + resource, _ := meta.KindToResource(fullyQualifiedKind) err = c.client.Get().Namespace(c.ns).Resource(resource.Resource).Name(name).SubResource("scale").Do().Into(result) return @@ -63,7 +63,7 @@ func (c *scales) Update(kind string, scale *extensions.Scale) (result *extension // TODO this method needs to take a proper unambiguous kind fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind} - resource, _ := meta.KindToResource(fullyQualifiedKind, false) + resource, _ := meta.KindToResource(fullyQualifiedKind) err = c.client.Put(). Namespace(scale.Namespace). diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index fbcc2be5fd1..719b7fcf423 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -124,9 +124,8 @@ func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { for kind := range scheme.KnownTypes(gv) { gvk := gv.WithKind(kind) - mixedCase := false scope := meta.RESTScopeNamespace - mapper.Add(gvk, scope, mixedCase) + mapper.Add(gvk, scope) } } diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 14664310485..c3e79637142 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -365,7 +365,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg if err != nil { return err } - _, res := meta.KindToResource(kind, false) + _, res := meta.KindToResource(kind) cmdutil.PrintSuccess(mapper, false, out, res.Resource, oldName, message) return nil } diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index d3c4b6ff00c..38694d18f57 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -234,7 +234,7 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error { if gvk != nil { // TODO: this is wrong, it assumes that meta knows about all Kinds - should take a RESTMapper - _, resource := meta.KindToResource(*gvk, false) + _, resource := meta.KindToResource(*gvk) fmt.Fprintf(w, "%s/%s\n", resource.Resource, name) } else { diff --git a/pkg/registry/thirdpartyresourcedata/codec.go b/pkg/registry/thirdpartyresourcedata/codec.go index 33ee1094520..2e80c8c00d1 100644 --- a/pkg/registry/thirdpartyresourcedata/codec.go +++ b/pkg/registry/thirdpartyresourcedata/codec.go @@ -42,7 +42,7 @@ type thirdPartyResourceDataMapper struct { var _ meta.RESTMapper = &thirdPartyResourceDataMapper{} func (t *thirdPartyResourceDataMapper) getResource() unversioned.GroupVersionResource { - plural, _ := meta.KindToResource(t.getKind(), false) + plural, _ := meta.KindToResource(t.getKind()) return plural }