diff --git a/pkg/api/meta/restmapper.go b/pkg/api/meta/restmapper.go index 27ec213665f..96c109d617c 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 + groupVersions []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 } @@ -100,11 +95,11 @@ type VersionInterfacesFunc func(apiVersion string) (*VersionInterfaces, error) // 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) + 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{} @@ -113,35 +108,35 @@ func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesF } return &DefaultRESTMapper{ - mapping: mapping, - reverse: reverse, - scopes: scopes, - groupVersions: gvs, - plurals: plurals, - singulars: singulars, - interfacesFunc: f, + resourceToKind: resourceToKind, + kindToPluralResource: kindToPluralResource, + kindToScope: kindToScope, + groupVersions: gvs, + singularToPlural: singularToPlural, + pluralToSingular: pluralToSingular, + interfacesFunc: f, } } func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) { gv := unversioned.ParseGroupVersionOrDie(gvString) + gvk := gv.WithKind(kind) 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)] + 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 +168,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 +176,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,8 +214,9 @@ 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 } @@ -232,7 +224,8 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM // 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 { + currGVK := currGroupVersion.WithKind(kind) + if _, ok := m.kindToPluralResource[currGVK]; ok { groupVersion = &currGroupVersion break } @@ -242,14 +235,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 { + if _, ok := m.kindToPluralResource[gvk]; ok { found = append(found, gv) } } @@ -260,7 +253,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/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()