make DefaultRESTMapper use GroupVersion

This commit is contained in:
deads2k 2015-11-16 10:36:41 -05:00
parent 5077e9b644
commit 94ad6aa0c4
2 changed files with 50 additions and 52 deletions

View File

@ -56,13 +56,6 @@ var RESTScopeRoot = &restScope{
name: RESTScopeNameRoot, 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 // DefaultRESTMapper exposes mappings between the types defined in a
// runtime.Scheme. It assumes that all types defined the provided scheme // runtime.Scheme. It assumes that all types defined the provided scheme
// can be mapped with the provided MetadataAccessor and Codec interfaces. // can be mapped with the provided MetadataAccessor and Codec interfaces.
@ -76,12 +69,14 @@ type typeMeta struct {
// (`get pod bar` vs `get pods bar`) // (`get pod bar` vs `get pods bar`)
// TODO these maps should be keyed based on GroupVersionKinds // TODO these maps should be keyed based on GroupVersionKinds
type DefaultRESTMapper struct { type DefaultRESTMapper struct {
mapping map[string]typeMeta
reverse map[typeMeta]string
scopes map[typeMeta]RESTScope
groupVersions []unversioned.GroupVersion groupVersions []unversioned.GroupVersion
plurals map[string]string
singulars map[string]string 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 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 // a GroupRESTMapper and CrossGroupRESTMapper, but for now, this one is constructed and
// used a CrossGroupRESTMapper. // used a CrossGroupRESTMapper.
func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesFunc) *DefaultRESTMapper { func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesFunc) *DefaultRESTMapper {
mapping := make(map[string]typeMeta) resourceToKind := make(map[string]unversioned.GroupVersionKind)
reverse := make(map[typeMeta]string) kindToPluralResource := make(map[unversioned.GroupVersionKind]string)
scopes := make(map[typeMeta]RESTScope) kindToScope := make(map[unversioned.GroupVersionKind]RESTScope)
plurals := make(map[string]string) singularToPlural := make(map[string]string)
singulars := make(map[string]string) pluralToSingular := make(map[string]string)
// TODO: verify name mappings work correctly when versions differ // TODO: verify name mappings work correctly when versions differ
gvs := []unversioned.GroupVersion{} gvs := []unversioned.GroupVersion{}
@ -113,35 +108,35 @@ func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesF
} }
return &DefaultRESTMapper{ return &DefaultRESTMapper{
mapping: mapping, resourceToKind: resourceToKind,
reverse: reverse, kindToPluralResource: kindToPluralResource,
scopes: scopes, kindToScope: kindToScope,
groupVersions: gvs, groupVersions: gvs,
plurals: plurals, singularToPlural: singularToPlural,
singulars: singulars, pluralToSingular: pluralToSingular,
interfacesFunc: f, interfacesFunc: f,
} }
} }
func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) { func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) {
gv := unversioned.ParseGroupVersionOrDie(gvString) gv := unversioned.ParseGroupVersionOrDie(gvString)
gvk := gv.WithKind(kind)
plural, singular := KindToResource(kind, mixedCase) plural, singular := KindToResource(kind, mixedCase)
m.plurals[singular] = plural m.singularToPlural[singular] = plural
m.singulars[plural] = singular m.pluralToSingular[plural] = singular
meta := typeMeta{APIVersion: gv.String(), Kind: kind} _, ok1 := m.resourceToKind[plural]
_, ok1 := m.mapping[plural] _, ok2 := m.resourceToKind[strings.ToLower(plural)]
_, ok2 := m.mapping[strings.ToLower(plural)]
if !ok1 && !ok2 { if !ok1 && !ok2 {
m.mapping[plural] = meta m.resourceToKind[plural] = gvk
m.mapping[singular] = meta m.resourceToKind[singular] = gvk
if strings.ToLower(plural) != plural { if strings.ToLower(plural) != plural {
m.mapping[strings.ToLower(plural)] = meta m.resourceToKind[strings.ToLower(plural)] = gvk
m.mapping[strings.ToLower(singular)] = meta m.resourceToKind[strings.ToLower(singular)] = gvk
} }
} }
m.reverse[meta] = plural m.kindToPluralResource[gvk] = plural
m.scopes[meta] = scope m.kindToScope[gvk] = scope
} }
// KindToResource converts Kind to a resource name. // KindToResource converts Kind to a resource name.
@ -173,7 +168,7 @@ func KindToResource(kind string, mixedCase bool) (plural, singular string) {
// ResourceSingularizer implements RESTMapper // ResourceSingularizer implements RESTMapper
// It converts a resource name from plural to singular (e.g., from pods to pod) // 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) { func (m *DefaultRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
singular, ok := m.singulars[resource] singular, ok := m.pluralToSingular[resource]
if !ok { if !ok {
return resource, fmt.Errorf("no singular of resource %q has been defined", resource) 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 // VersionAndKindForResource implements RESTMapper
func (m *DefaultRESTMapper) VersionAndKindForResource(resource string) (defaultVersion, kind string, err error) { func (m *DefaultRESTMapper) VersionAndKindForResource(resource string) (gvString, kind string, err error) {
meta, ok := m.mapping[strings.ToLower(resource)] gvk, ok := m.resourceToKind[strings.ToLower(resource)]
if !ok { if !ok {
return "", "", fmt.Errorf("in version and kind for resource, no resource %q has been defined", resource) 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) { func (m *DefaultRESTMapper) GroupForResource(resource string) (string, error) {
typemeta, exists := m.mapping[strings.ToLower(resource)] gvk, exists := m.resourceToKind[strings.ToLower(resource)]
if !exists { if !exists {
return "", fmt.Errorf("in group for resource, no resource %q has been defined", resource) return "", fmt.Errorf("in group for resource, no resource %q has been defined", resource)
} }
gv, err := unversioned.ParseGroupVersion(typemeta.APIVersion) return gvk.Group, nil
if err != nil {
return "", err
}
return gv.Group, nil
} }
// RESTMapping returns a struct representing the resource path and conversion interfaces a // 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 return nil, err
} }
currGVK := currGroupVersion.WithKind(kind)
hadVersion = true hadVersion = true
if _, ok := m.reverse[typeMeta{APIVersion: currGroupVersion.String(), Kind: kind}]; ok { if _, ok := m.kindToPluralResource[currGVK]; ok {
groupVersion = &currGroupVersion groupVersion = &currGroupVersion
break break
} }
@ -232,7 +224,8 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM
// Use the default preferred versions // Use the default preferred versions
if !hadVersion && (groupVersion == nil) { if !hadVersion && (groupVersion == nil) {
for _, currGroupVersion := range m.groupVersions { 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 groupVersion = &currGroupVersion
break 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) 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 // 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 { if !ok {
found := []unversioned.GroupVersion{} found := []unversioned.GroupVersion{}
for _, gv := range m.groupVersions { 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) found = append(found, gv)
} }
} }
@ -260,7 +253,7 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM
} }
// Ensure we have a REST scope // 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 { 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) return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion().String(), gvk.Kind)
} }

View File

@ -30,6 +30,7 @@ type GroupVersionKind struct {
Kind string Kind string
} }
// TODO remove this
func NewGroupVersionKind(gv GroupVersion, kind string) GroupVersionKind { func NewGroupVersionKind(gv GroupVersion, kind string) GroupVersionKind {
return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
} }
@ -84,6 +85,10 @@ func ParseGroupVersionOrDie(gv string) GroupVersion {
return ret 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. // MarshalJSON implements the json.Marshaller interface.
func (gv GroupVersion) MarshalJSON() ([]byte, error) { func (gv GroupVersion) MarshalJSON() ([]byte, error) {
s := gv.String() s := gv.String()