Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update DefaultRESTMapper types #17327

Merged
merged 3 commits into from
Nov 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 12 additions & 8 deletions pkg/api/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/registered"
apiutil "k8s.io/kubernetes/pkg/api/util"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime"
)
Expand All @@ -48,20 +48,24 @@ func init() {
glog.V(4).Infof("%v", err)
return
}

worstToBestGroupVersions := []unversioned.GroupVersion{}

// Use the first API version in the list of registered versions as the latest.
registeredGroupVersions := registered.GroupVersionsForGroup("")
groupVersion := registeredGroupVersions[0]
*groupMeta = latest.GroupMeta{
GroupVersion: groupVersion,
Group: apiutil.GetGroup(groupVersion),
Version: apiutil.GetVersion(groupVersion),
Codec: runtime.CodecFor(api.Scheme, groupVersion),
GroupVersion: groupVersion.String(),
Group: groupVersion.Group,
Version: groupVersion.Version,
Codec: runtime.CodecFor(api.Scheme, groupVersion.String()),
}
var versions []string
var groupVersions []string
for i := len(registeredGroupVersions) - 1; i >= 0; i-- {
versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i]))
groupVersions = append(groupVersions, registeredGroupVersions[i])
versions = append(versions, registeredGroupVersions[i].Version)
groupVersions = append(groupVersions, registeredGroupVersions[i].String())
worstToBestGroupVersions = append(worstToBestGroupVersions, registeredGroupVersions[i])
}
groupMeta.Versions = versions
groupMeta.GroupVersions = groupVersions
Expand Down Expand Up @@ -90,7 +94,7 @@ func init() {
"ThirdPartyResourceData",
"ThirdPartyResourceList")

mapper := api.NewDefaultRESTMapper("", versions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
mapper := api.NewDefaultRESTMapper(worstToBestGroupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
// setup aliases for groups of resources
mapper.AddResourceAlias("all", userResources...)
groupMeta.RESTMapper = mapper
Expand Down
20 changes: 6 additions & 14 deletions pkg/api/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package api

import (
"fmt"
"strings"

"k8s.io/kubernetes/pkg/api/meta"
Expand All @@ -35,23 +34,16 @@ func RegisterRESTMapper(m meta.RESTMapper) {
RESTMapper = append(RESTMapper.(meta.MultiRESTMapper), m)
}

func NewDefaultRESTMapper(group string, groupVersionStrings []string, interfacesFunc meta.VersionInterfacesFunc,
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc,
importPathPrefix string, ignoredKinds, rootScoped sets.String) *meta.DefaultRESTMapper {

mapper := meta.NewDefaultRESTMapper(group, groupVersionStrings, interfacesFunc)
mapper := meta.NewDefaultRESTMapper(defaultGroupVersions, interfacesFunc)
// enumerate all supported versions, get the kinds, and register with the mapper how to address
// our resources.
for _, gvString := range groupVersionStrings {
gv, err := unversioned.ParseGroupVersion(gvString)
// TODO stop panicing when the types are fixed
if err != nil {
panic(err)
}
if gv.Group != group {
panic(fmt.Sprintf("%q does not match the expect %q", gv.Group, group))
}

for _, gv := range defaultGroupVersions {
for kind, oType := range Scheme.KnownTypes(gv.String()) {
gvk := gv.WithKind(kind)

// TODO: Remove import path prefix check.
// We check the import path prefix because we currently stuff both "api" and "extensions" objects
// into the same group within Scheme since Scheme has no notion of groups yet.
Expand All @@ -62,7 +54,7 @@ func NewDefaultRESTMapper(group string, groupVersionStrings []string, interfaces
if rootScoped.Has(kind) {
scope = meta.RESTScopeRoot
}
mapper.Add(scope, kind, gv.String(), false)
mapper.Add(gvk, scope, false)
}
}
return mapper
Expand Down
118 changes: 49 additions & 69 deletions pkg/api/meta/restmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
defaultGroupVersions []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
}

Expand All @@ -94,54 +89,41 @@ type VersionInterfacesFunc func(apiVersion string) (*VersionInterfaces, error)
// and the Kubernetes API conventions. Takes a group name, a priority list of the versions
// to search when an object has no default version (set empty to return an error),
// and a function that retrieves the correct codec and metadata for a given version.
// TODO remove group when this API is fixed. It is no longer used.
// The external API for a RESTMapper is cross-version and this is currently called using
// group/version tuples. In the end, the structure may be easier to understand with
// 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)
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper {
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{}
for _, gvString := range gvStrings {
gvs = append(gvs, unversioned.ParseGroupVersionOrDie(gvString))
}

return &DefaultRESTMapper{
mapping: mapping,
reverse: reverse,
scopes: scopes,
groupVersions: gvs,
plurals: plurals,
singulars: singulars,
interfacesFunc: f,
resourceToKind: resourceToKind,
kindToPluralResource: kindToPluralResource,
kindToScope: kindToScope,
defaultGroupVersions: defaultGroupVersions,
singularToPlural: singularToPlural,
pluralToSingular: pluralToSingular,
interfacesFunc: f,
}
}

func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) {
gv := unversioned.ParseGroupVersionOrDie(gvString)

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)]
func (m *DefaultRESTMapper) Add(gvk unversioned.GroupVersionKind, scope RESTScope, mixedCase bool) {
plural, singular := KindToResource(gvk.Kind, mixedCase)
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.
Expand Down Expand Up @@ -173,33 +155,29 @@ 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)
}
return singular, nil
}

// 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
Expand All @@ -223,16 +201,18 @@ 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
}
}
// 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 {
for _, currGroupVersion := range m.defaultGroupVersions {
currGVK := currGroupVersion.WithKind(kind)
if _, ok := m.kindToPluralResource[currGVK]; ok {
groupVersion = &currGroupVersion
break
}
Expand All @@ -242,14 +222,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 {
for _, gv := range m.defaultGroupVersions {
if _, ok := m.kindToPluralResource[gvk]; ok {
found = append(found, gv)
}
}
Expand All @@ -260,7 +240,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)
}
Expand Down