diff --git a/cmd/libs/go2idl/client-gen/generators/client-generator.go b/cmd/libs/go2idl/client-gen/generators/client-generator.go index 70ca882ad9c..d29b0f628bc 100644 --- a/cmd/libs/go2idl/client-gen/generators/client-generator.go +++ b/cmd/libs/go2idl/client-gen/generators/client-generator.go @@ -32,10 +32,16 @@ import ( // NameSystems returns the name system used by the generators in this package. func NameSystems() namer.NameSystems { + pluralExceptions := map[string]string{ + "Endpoints": "Endpoints", + "ComponentStatus": "ComponentStatus", + } return namer.NameSystems{ - "public": namer.NewPublicNamer(0), - "private": namer.NewPrivateNamer(0), - "raw": namer.NewRawNamer("", nil), + "public": namer.NewPublicNamer(0), + "private": namer.NewPrivateNamer(0), + "raw": namer.NewRawNamer("", nil), + "publicPlural": namer.NewPublicPluralNamer(pluralExceptions), + "privatePlural": namer.NewPrivatePluralNamer(pluralExceptions), } } diff --git a/cmd/libs/go2idl/client-gen/generators/generator-for-group.go b/cmd/libs/go2idl/client-gen/generators/generator-for-group.go index c446b84fd67..6033aa5db68 100644 --- a/cmd/libs/go2idl/client-gen/generators/generator-for-group.go +++ b/cmd/libs/go2idl/client-gen/generators/generator-for-group.go @@ -96,8 +96,8 @@ type $.Group$Client struct { ` var namespacerImplTemplate = ` -func (c *$.Group$Client) $.type.Name.Name$s(namespace string) $.type.Name.Name$Interface { - return new$.type.Name.Name$s(c, namespace) +func (c *$.Group$Client) $.type|publicPlural$(namespace string) $.type.Name.Name$Interface { + return new$.type|publicPlural$(c, namespace) } ` diff --git a/cmd/libs/go2idl/client-gen/generators/generator-for-type.go b/cmd/libs/go2idl/client-gen/generators/generator-for-type.go index c5519b9e26d..f9934be8728 100644 --- a/cmd/libs/go2idl/client-gen/generators/generator-for-type.go +++ b/cmd/libs/go2idl/client-gen/generators/generator-for-type.go @@ -76,7 +76,7 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i var namespacerTemplate = ` // $.type|public$Namespacer has methods to work with $.type|public$ resources in a namespace type $.type|public$Namespacer interface { - $.type|public$s(namespace string) $.type|public$Interface + $.type|publicPlural$(namespace string) $.type|public$Interface } ` @@ -95,28 +95,28 @@ type $.type|public$Interface interface { // template for the struct that implements the interface var structTemplate = ` -// $.type|private$s implements $.type|public$Interface -type $.type|private$s struct { +// $.type|privatePlural$ implements $.type|public$Interface +type $.type|privatePlural$ struct { client *$.Package$Client ns string } ` var newStructTemplate = ` -// new$.type|public$s returns a $.type|public$s -func new$.type|public$s(c *ExtensionsClient, namespace string) *$.type|private$s { - return &$.type|private$s{ +// new$.type|publicPlural$ returns a $.type|publicPlural$ +func new$.type|publicPlural$(c *ExtensionsClient, namespace string) *$.type|privatePlural$ { + return &$.type|privatePlural${ client: c, ns: namespace, } } ` var listTemplate = ` -// List takes label and field selectors, and returns the list of $.type|public$s that match those selectors. -func (c *$.type|private$s) List(opts $.unvListOptions|raw$) (result *$.type|raw$List, err error) { +// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors. +func (c *$.type|privatePlural$) List(opts $.unvListOptions|raw$) (result *$.type|raw$List, err error) { result = &$.type|raw$List{} err = c.client.Get(). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). VersionedParams(&opts, api.Scheme). Do(). Into(result) @@ -125,11 +125,11 @@ func (c *$.type|private$s) List(opts $.unvListOptions|raw$) (result *$.type|raw$ ` var getTemplate = ` // Get takes name of the $.type|private$, and returns the corresponding $.type|private$ object, and an error if there is any. -func (c *$.type|private$s) Get(name string) (result *$.type|raw$, err error) { +func (c *$.type|privatePlural$) Get(name string) (result *$.type|raw$, err error) { result = &$.type|raw${} err = c.client.Get(). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). Name(name). Do(). Into(result) @@ -139,9 +139,9 @@ func (c *$.type|private$s) Get(name string) (result *$.type|raw$, err error) { var deleteTemplate = ` // Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs. -func (c *$.type|private$s) Delete(name string, options *$.apiDeleteOptions|raw$) error { +func (c *$.type|privatePlural$) Delete(name string, options *$.apiDeleteOptions|raw$) error { if options == nil { - return c.client.Delete().Namespace(c.ns).Resource("$.type|private$s").Name(name).Do().Error() + return c.client.Delete().Namespace(c.ns).Resource("$.type|privatePlural$").Name(name).Do().Error() } body, err := api.Scheme.EncodeToVersion(options, c.client.APIVersion()) if err != nil { @@ -149,7 +149,7 @@ func (c *$.type|private$s) Delete(name string, options *$.apiDeleteOptions|raw$) } return c.client.Delete(). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). Name(name). Body(body). Do(). @@ -159,11 +159,11 @@ func (c *$.type|private$s) Delete(name string, options *$.apiDeleteOptions|raw$) var createTemplate = ` // Create takes the representation of a $.type|private$ and creates it. Returns the server's representation of the $.type|private$, and an error, if there is any. -func (c *$.type|private$s) Create($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) { +func (c *$.type|privatePlural$) Create($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) { result = &$.type|raw${} err = c.client.Post(). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). Body($.type|private$). Do(). Into(result) @@ -173,11 +173,11 @@ func (c *$.type|private$s) Create($.type|private$ *$.type|raw$) (result *$.type| var updateTemplate = ` // Update takes the representation of a $.type|private$ and updates it. Returns the server's representation of the $.type|private$, and an error, if there is any. -func (c *$.type|private$s) Update($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) { +func (c *$.type|privatePlural$) Update($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) { result = &$.type|raw${} err = c.client.Put(). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). Name($.type|private$.Name). Body($.type|private$). Do(). @@ -187,12 +187,12 @@ func (c *$.type|private$s) Update($.type|private$ *$.type|raw$) (result *$.type| ` var watchTemplate = ` -// Watch returns a $.watchInterface|raw$ that watches the requested $.type|private$s. -func (c *$.type|private$s) Watch(opts $.unvListOptions|raw$) ($.watchInterface|raw$, error) { +// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$. +func (c *$.type|privatePlural$) Watch(opts $.unvListOptions|raw$) ($.watchInterface|raw$, error) { return c.client.Get(). Prefix("watch"). Namespace(c.ns). - Resource("$.type|private$s"). + Resource("$.type|privatePlural$"). VersionedParams(&opts, api.Scheme). Watch() } diff --git a/cmd/libs/go2idl/namer/plural_namer.go b/cmd/libs/go2idl/namer/plural_namer.go new file mode 100644 index 00000000000..bcd42c8e12c --- /dev/null +++ b/cmd/libs/go2idl/namer/plural_namer.go @@ -0,0 +1,58 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package namer + +import "k8s.io/kubernetes/cmd/libs/go2idl/types" + +type pluralNamer struct { + // key is the case-sensitive type name, value is the case-insensitive + // intended output. + exceptions map[string]string + finalize func(string) string +} + +// NewPublicPluralNamer returns a namer that returns the plural form of the input +// type's name, starting with a uppercase letter. +func NewPublicPluralNamer(exceptions map[string]string) *pluralNamer { + return &pluralNamer{exceptions, IC} +} + +// NewPrivatePluralNamer returns a namer that returns the plural form of the input +// type's name, starting with a lowercase letter. +func NewPrivatePluralNamer(exceptions map[string]string) *pluralNamer { + return &pluralNamer{exceptions, IL} +} + +// Name returns the plural form of the type's name. If the type's name is found +// in the exceptions map, the map value is returned. +func (r *pluralNamer) Name(t *types.Type) string { + singular := t.Name.Name + var plural string + var ok bool + if plural, ok = r.exceptions[singular]; ok { + return r.finalize(plural) + } + switch string(singular[len(singular)-1]) { + case "s", "x": + plural = singular + "es" + case "y": + plural = singular[:len(singular)-1] + "ies" + default: + plural = singular + "s" + } + return r.finalize(plural) +} diff --git a/cmd/libs/go2idl/namer/plural_namer_test.go b/cmd/libs/go2idl/namer/plural_namer_test.go new file mode 100644 index 00000000000..3715ff47ac9 --- /dev/null +++ b/cmd/libs/go2idl/namer/plural_namer_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package namer + +import ( + "testing" + + "k8s.io/kubernetes/cmd/libs/go2idl/types" +) + +func TestPluralNamer(t *testing.T) { + exceptions := map[string]string{ + // The type name is already in the plural form + "Endpoints": "endpoints", + } + public := NewPublicPluralNamer(exceptions) + private := NewPrivatePluralNamer(exceptions) + + cases := []struct { + typeName string + expectedPrivate string + expectedPublic string + }{ + { + "Pod", + "pods", + "Pods", + }, + { + "Entry", + "entries", + "Entries", + }, + { + "Endpoints", + "endpoints", + "Endpoints", + }, + { + "Bus", + "buses", + "Buses", + }, + } + for _, c := range cases { + testType := &types.Type{Name: types.Name{Name: c.typeName}} + if e, a := c.expectedPrivate, private.Name(testType); e != a { + t.Errorf("Unexpected result from private plural namer. Expected: %s, Got: %s", e, a) + } + if e, a := c.expectedPublic, public.Name(testType); e != a { + t.Errorf("Unexpected result from public plural namer. Expected: %s, Got: %s", e, a) + } + } +}