mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
commit
08c2cba266
@ -78,7 +78,7 @@ func TestRESTMapper(t *testing.T) {
|
||||
rcGVK := gv.WithKind("ReplicationController")
|
||||
podTemplateGVK := gv.WithKind("PodTemplate")
|
||||
|
||||
if gvk, err := latest.GroupOrDie(internal.GroupName).RESTMapper.KindFor(internal.SchemeGroupVersion.WithResource("replicationcontrollers")); err != nil || gvk != rcGVK {
|
||||
if gvk, err := latest.GroupOrDie(internal.GroupName).RESTMapper.KindFor("replicationcontrollers"); err != nil || gvk != rcGVK {
|
||||
t.Errorf("unexpected version mapping: %v %v", gvk, err)
|
||||
}
|
||||
|
||||
|
@ -158,23 +158,12 @@ type RESTMapping struct {
|
||||
// TODO(caesarxuchao): Add proper multi-group support so that kinds & resources are
|
||||
// scoped to groups. See http://issues.k8s.io/12413 and http://issues.k8s.io/10009.
|
||||
type RESTMapper interface {
|
||||
// KindFor takes a partial resource and returns back the single match. Returns an error if there are multiple matches
|
||||
KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error)
|
||||
|
||||
// KindsFor takes a partial resource and returns back the list of potential kinds in priority order
|
||||
KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error)
|
||||
|
||||
// ResourceFor takes a partial resource and returns back the single match. Returns an error if there are multiple matches
|
||||
ResourceFor(input unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error)
|
||||
|
||||
// ResourcesFor takes a partial resource and returns back the list of potential resource in priority order
|
||||
ResourcesFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error)
|
||||
// KindFor takes a resource and returns back the unambiguous Kind (GroupVersionKind)
|
||||
KindFor(resource string) (unversioned.GroupVersionKind, error)
|
||||
|
||||
RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error)
|
||||
|
||||
AliasesForResource(resource string) ([]string, bool)
|
||||
ResourceSingularizer(resource string) (singular string, err error)
|
||||
|
||||
// ResourceIsValid takes a partial resource and returns back whether or not the resource matches at least one kind
|
||||
ResourceIsValid(resource unversioned.GroupVersionResource) bool
|
||||
ResourceIsValid(resource string) bool
|
||||
}
|
||||
|
@ -19,11 +19,9 @@ package meta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
// Implements RESTScope interface
|
||||
@ -73,11 +71,11 @@ var RESTScopeRoot = &restScope{
|
||||
type DefaultRESTMapper struct {
|
||||
defaultGroupVersions []unversioned.GroupVersion
|
||||
|
||||
resourceToKind map[unversioned.GroupVersionResource]unversioned.GroupVersionKind
|
||||
kindToPluralResource map[unversioned.GroupVersionKind]unversioned.GroupVersionResource
|
||||
resourceToKind map[string]unversioned.GroupVersionKind
|
||||
kindToPluralResource map[unversioned.GroupVersionKind]string
|
||||
kindToScope map[unversioned.GroupVersionKind]RESTScope
|
||||
singularToPlural map[unversioned.GroupVersionResource]unversioned.GroupVersionResource
|
||||
pluralToSingular map[unversioned.GroupVersionResource]unversioned.GroupVersionResource
|
||||
singularToPlural map[string]string
|
||||
pluralToSingular map[string]string
|
||||
|
||||
interfacesFunc VersionInterfacesFunc
|
||||
}
|
||||
@ -94,11 +92,11 @@ type VersionInterfacesFunc func(version unversioned.GroupVersion) (*VersionInter
|
||||
// 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.
|
||||
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper {
|
||||
resourceToKind := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionKind)
|
||||
kindToPluralResource := make(map[unversioned.GroupVersionKind]unversioned.GroupVersionResource)
|
||||
resourceToKind := make(map[string]unversioned.GroupVersionKind)
|
||||
kindToPluralResource := make(map[unversioned.GroupVersionKind]string)
|
||||
kindToScope := make(map[unversioned.GroupVersionKind]RESTScope)
|
||||
singularToPlural := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
|
||||
pluralToSingular := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
|
||||
singularToPlural := make(map[string]string)
|
||||
pluralToSingular := make(map[string]string)
|
||||
// TODO: verify name mappings work correctly when versions differ
|
||||
|
||||
return &DefaultRESTMapper{
|
||||
@ -112,54 +110,45 @@ 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(gvk unversioned.GroupVersionKind, scope RESTScope, mixedCase bool) {
|
||||
plural, singular := KindToResource(gvk.Kind, mixedCase)
|
||||
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
|
||||
_, ok1 := m.resourceToKind[plural]
|
||||
_, ok2 := m.resourceToKind[strings.ToLower(plural)]
|
||||
if !ok1 && !ok2 {
|
||||
m.resourceToKind[plural] = gvk
|
||||
m.resourceToKind[singular] = gvk
|
||||
if strings.ToLower(plural) != plural {
|
||||
m.resourceToKind[strings.ToLower(plural)] = gvk
|
||||
m.resourceToKind[strings.ToLower(singular)] = gvk
|
||||
}
|
||||
}
|
||||
|
||||
if _, lowerCaseExists := m.resourceToKind[lowerPlural]; !lowerCaseExists && (lowerPlural != plural) {
|
||||
m.resourceToKind[lowerPlural] = kind
|
||||
m.resourceToKind[lowerSingular] = kind
|
||||
}
|
||||
|
||||
m.kindToPluralResource[kind] = plural
|
||||
m.kindToScope[kind] = scope
|
||||
m.kindToPluralResource[gvk] = plural
|
||||
m.kindToScope[gvk] = scope
|
||||
}
|
||||
|
||||
// KindToResource converts Kind to a resource name.
|
||||
func KindToResource(kind unversioned.GroupVersionKind, mixedCase bool) (plural, singular unversioned.GroupVersionResource) {
|
||||
kindName := kind.Kind
|
||||
if len(kindName) == 0 {
|
||||
func KindToResource(kind string, mixedCase bool) (plural, singular string) {
|
||||
if len(kind) == 0 {
|
||||
return
|
||||
}
|
||||
if mixedCase {
|
||||
// Legacy support for mixed case names
|
||||
singular = kind.GroupVersion().WithResource(strings.ToLower(kindName[:1]) + kindName[1:])
|
||||
singular = strings.ToLower(kind[:1]) + kind[1:]
|
||||
} else {
|
||||
singular = kind.GroupVersion().WithResource(strings.ToLower(kindName))
|
||||
singular = strings.ToLower(kind)
|
||||
}
|
||||
|
||||
singularName := singular.Resource
|
||||
if strings.HasSuffix(singularName, "endpoints") {
|
||||
if strings.HasSuffix(singular, "endpoints") {
|
||||
plural = singular
|
||||
} else {
|
||||
switch string(singularName[len(singularName)-1]) {
|
||||
switch string(singular[len(singular)-1]) {
|
||||
case "s":
|
||||
plural = kind.GroupVersion().WithResource(singularName + "es")
|
||||
plural = singular + "es"
|
||||
case "y":
|
||||
plural = kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies")
|
||||
plural = strings.TrimSuffix(singular, "y") + "ies"
|
||||
default:
|
||||
plural = kind.GroupVersion().WithResource(singularName + "s")
|
||||
plural = singular + "s"
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -167,240 +156,21 @@ func KindToResource(kind unversioned.GroupVersionKind, mixedCase bool) (plural,
|
||||
|
||||
// ResourceSingularizer implements RESTMapper
|
||||
// It converts a resource name from plural to singular (e.g., from pods to pod)
|
||||
// It must have exactly one match and it must match case perfectly. This is congruent with old functionality
|
||||
func (m *DefaultRESTMapper) ResourceSingularizer(resourceType string) (string, error) {
|
||||
partialResource := unversioned.GroupVersionResource{Resource: resourceType}
|
||||
resource, err := m.ResourceFor(partialResource)
|
||||
if err != nil {
|
||||
return resourceType, err
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
||||
singular, ok := m.pluralToSingular[resource]
|
||||
if !ok {
|
||||
return resourceType, fmt.Errorf("no singular of resource %v has been defined", resource)
|
||||
return resource, fmt.Errorf("no singular of resource %q has been defined", resource)
|
||||
}
|
||||
return singular.Resource, nil
|
||||
return singular, nil
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
|
||||
hasResource := len(resource.Resource) > 0
|
||||
hasGroup := len(resource.Group) > 0
|
||||
hasVersion := len(resource.Version) > 0
|
||||
|
||||
if !hasResource {
|
||||
return nil, fmt.Errorf("a resource must be present, got: %v", resource)
|
||||
// VersionAndKindForResource implements RESTMapper
|
||||
func (m *DefaultRESTMapper) KindFor(resource string) (unversioned.GroupVersionKind, error) {
|
||||
gvk, ok := m.resourceToKind[strings.ToLower(resource)]
|
||||
if !ok {
|
||||
return gvk, fmt.Errorf("in version and kind for resource, no resource %q has been defined", resource)
|
||||
}
|
||||
|
||||
ret := []unversioned.GroupVersionResource{}
|
||||
switch {
|
||||
// fully qualified. Find the exact match
|
||||
case hasGroup && hasVersion:
|
||||
for plural, singular := range m.pluralToSingular {
|
||||
if singular == resource {
|
||||
ret = append(ret, plural)
|
||||
break
|
||||
}
|
||||
if plural == resource {
|
||||
ret = append(ret, plural)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case hasGroup:
|
||||
requestedGroupResource := resource.GroupResource()
|
||||
for currResource := range m.pluralToSingular {
|
||||
if currResource.GroupResource() == requestedGroupResource {
|
||||
ret = append(ret, currResource)
|
||||
}
|
||||
}
|
||||
|
||||
case hasVersion:
|
||||
for currResource := range m.pluralToSingular {
|
||||
if currResource.Version == resource.Version && currResource.Resource == resource.Resource {
|
||||
ret = append(ret, currResource)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
for currResource := range m.pluralToSingular {
|
||||
if currResource.Resource == resource.Resource {
|
||||
ret = append(ret, currResource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(ret) == 0 {
|
||||
return nil, fmt.Errorf("no resource %v has been defined; known resources: %v", resource, m.pluralToSingular)
|
||||
}
|
||||
|
||||
sort.Sort(resourceByPreferredGroupVersion{ret, m.defaultGroupVersions})
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
|
||||
resources, err := m.ResourcesFor(resource)
|
||||
if err != nil {
|
||||
return unversioned.GroupVersionResource{}, err
|
||||
}
|
||||
if len(resources) == 1 {
|
||||
return resources[0], nil
|
||||
}
|
||||
|
||||
return unversioned.GroupVersionResource{}, fmt.Errorf("%v is ambiguous, got: %v", resource, resources)
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) KindsFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
|
||||
resource := input.GroupVersion().WithResource(strings.ToLower(input.Resource))
|
||||
|
||||
hasResource := len(resource.Resource) > 0
|
||||
hasGroup := len(resource.Group) > 0
|
||||
hasVersion := len(resource.Version) > 0
|
||||
|
||||
if !hasResource {
|
||||
return nil, fmt.Errorf("a resource must be present, got: %v", resource)
|
||||
}
|
||||
|
||||
ret := []unversioned.GroupVersionKind{}
|
||||
switch {
|
||||
// fully qualified. Find the exact match
|
||||
case hasGroup && hasVersion:
|
||||
kind, exists := m.resourceToKind[resource]
|
||||
if exists {
|
||||
ret = append(ret, kind)
|
||||
}
|
||||
|
||||
case hasGroup:
|
||||
requestedGroupResource := resource.GroupResource()
|
||||
for currResource, currKind := range m.resourceToKind {
|
||||
if currResource.GroupResource() == requestedGroupResource {
|
||||
ret = append(ret, currKind)
|
||||
}
|
||||
}
|
||||
|
||||
case hasVersion:
|
||||
for currResource, currKind := range m.resourceToKind {
|
||||
if currResource.Version == resource.Version && currResource.Resource == resource.Resource {
|
||||
ret = append(ret, currKind)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
for currResource, currKind := range m.resourceToKind {
|
||||
if currResource.Resource == resource.Resource {
|
||||
ret = append(ret, currKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(ret) == 0 {
|
||||
return nil, fmt.Errorf("no kind %v has been defined; known resources: %v", resource, m.pluralToSingular)
|
||||
}
|
||||
|
||||
sort.Sort(kindByPreferredGroupVersion{ret, m.defaultGroupVersions})
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
|
||||
kinds, err := m.KindsFor(resource)
|
||||
if err != nil {
|
||||
return unversioned.GroupVersionKind{}, err
|
||||
}
|
||||
|
||||
// TODO for each group, choose the most preferred (first) version. This keeps us consistent with code today.
|
||||
// eventually, we'll need a RESTMapper that is aware of what's available server-side and deconflicts that with
|
||||
// user preferences
|
||||
oneKindPerGroup := []unversioned.GroupVersionKind{}
|
||||
groupsAdded := sets.String{}
|
||||
for _, kind := range kinds {
|
||||
if groupsAdded.Has(kind.Group) {
|
||||
continue
|
||||
}
|
||||
|
||||
oneKindPerGroup = append(oneKindPerGroup, kind)
|
||||
groupsAdded.Insert(kind.Group)
|
||||
}
|
||||
|
||||
if len(oneKindPerGroup) == 1 {
|
||||
return oneKindPerGroup[0], nil
|
||||
}
|
||||
|
||||
return unversioned.GroupVersionKind{}, fmt.Errorf("%v is ambiguous, got: %v", resource, kinds)
|
||||
}
|
||||
|
||||
type kindByPreferredGroupVersion struct {
|
||||
list []unversioned.GroupVersionKind
|
||||
sortOrder []unversioned.GroupVersion
|
||||
}
|
||||
|
||||
func (o kindByPreferredGroupVersion) Len() int { return len(o.list) }
|
||||
func (o kindByPreferredGroupVersion) Swap(i, j int) { o.list[i], o.list[j] = o.list[j], o.list[i] }
|
||||
func (o kindByPreferredGroupVersion) Less(i, j int) bool {
|
||||
lhs := o.list[i]
|
||||
rhs := o.list[j]
|
||||
if lhs == rhs {
|
||||
return false
|
||||
}
|
||||
|
||||
if lhs.GroupVersion() == rhs.GroupVersion() {
|
||||
return lhs.Kind < rhs.Kind
|
||||
}
|
||||
|
||||
// otherwise, the difference is in the GroupVersion, so we need to sort with respect to the preferred order
|
||||
lhsIndex := -1
|
||||
rhsIndex := -1
|
||||
|
||||
for i := range o.sortOrder {
|
||||
if o.sortOrder[i] == lhs.GroupVersion() {
|
||||
lhsIndex = i
|
||||
}
|
||||
if o.sortOrder[i] == rhs.GroupVersion() {
|
||||
rhsIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
if rhsIndex == -1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return lhsIndex < rhsIndex
|
||||
}
|
||||
|
||||
type resourceByPreferredGroupVersion struct {
|
||||
list []unversioned.GroupVersionResource
|
||||
sortOrder []unversioned.GroupVersion
|
||||
}
|
||||
|
||||
func (o resourceByPreferredGroupVersion) Len() int { return len(o.list) }
|
||||
func (o resourceByPreferredGroupVersion) Swap(i, j int) { o.list[i], o.list[j] = o.list[j], o.list[i] }
|
||||
func (o resourceByPreferredGroupVersion) Less(i, j int) bool {
|
||||
lhs := o.list[i]
|
||||
rhs := o.list[j]
|
||||
if lhs == rhs {
|
||||
return false
|
||||
}
|
||||
|
||||
if lhs.GroupVersion() == rhs.GroupVersion() {
|
||||
return lhs.Resource < rhs.Resource
|
||||
}
|
||||
|
||||
// otherwise, the difference is in the GroupVersion, so we need to sort with respect to the preferred order
|
||||
lhsIndex := -1
|
||||
rhsIndex := -1
|
||||
|
||||
for i := range o.sortOrder {
|
||||
if o.sortOrder[i] == lhs.GroupVersion() {
|
||||
lhsIndex = i
|
||||
}
|
||||
if o.sortOrder[i] == rhs.GroupVersion() {
|
||||
rhsIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
if rhsIndex == -1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return lhsIndex < rhsIndex
|
||||
return gvk, nil
|
||||
}
|
||||
|
||||
// RESTMapping returns a struct representing the resource path and conversion interfaces a
|
||||
@ -468,7 +238,7 @@ func (m *DefaultRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...st
|
||||
}
|
||||
|
||||
retVal := &RESTMapping{
|
||||
Resource: resource.Resource,
|
||||
Resource: resource,
|
||||
GroupVersionKind: *gvk,
|
||||
Scope: scope,
|
||||
|
||||
@ -499,8 +269,8 @@ func (m *DefaultRESTMapper) AliasesForResource(alias string) ([]string, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// ResourceIsValid takes a partial resource and checks if it's valid
|
||||
func (m *DefaultRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
||||
// ResourceIsValid takes a string (kind) and checks if it's a valid resource
|
||||
func (m *DefaultRESTMapper) ResourceIsValid(resource string) bool {
|
||||
_, err := m.KindFor(resource)
|
||||
return err == nil
|
||||
}
|
||||
@ -520,41 +290,10 @@ func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string,
|
||||
return
|
||||
}
|
||||
|
||||
func (m MultiRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionResource, err error) {
|
||||
for _, t := range m {
|
||||
gvk, err = t.ResourcesFor(resource)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KindsFor provides the Kind mappings for the REST resources. This implementation supports multiple REST schemas and returns
|
||||
// VersionAndKindForResource provides the Version and Kind mappings for the
|
||||
// REST resources. This implementation supports multiple REST schemas and return
|
||||
// the first match.
|
||||
func (m MultiRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
|
||||
for _, t := range m {
|
||||
gvk, err = t.KindsFor(resource)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m MultiRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (gvk unversioned.GroupVersionResource, err error) {
|
||||
for _, t := range m {
|
||||
gvk, err = t.ResourceFor(resource)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KindsFor provides the Kind mapping for the REST resources. This implementation supports multiple REST schemas and returns
|
||||
// the first match.
|
||||
func (m MultiRESTMapper) KindFor(resource unversioned.GroupVersionResource) (gvk unversioned.GroupVersionKind, err error) {
|
||||
func (m MultiRESTMapper) KindFor(resource string) (gvk unversioned.GroupVersionKind, err error) {
|
||||
for _, t := range m {
|
||||
gvk, err = t.KindFor(resource)
|
||||
if err == nil {
|
||||
@ -588,7 +327,7 @@ func (m MultiRESTMapper) AliasesForResource(alias string) (aliases []string, ok
|
||||
}
|
||||
|
||||
// ResourceIsValid takes a string (either group/kind or kind) and checks if it's a valid resource
|
||||
func (m MultiRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
||||
func (m MultiRESTMapper) ResourceIsValid(resource string) bool {
|
||||
for _, t := range m {
|
||||
if t.ResourceIsValid(resource) {
|
||||
return true
|
||||
|
@ -20,8 +20,6 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
@ -94,23 +92,23 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) {
|
||||
testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: testVersion}
|
||||
|
||||
testCases := []struct {
|
||||
Resource unversioned.GroupVersionResource
|
||||
Resource string
|
||||
GroupVersionToRegister unversioned.GroupVersion
|
||||
ExpectedGVK unversioned.GroupVersionKind
|
||||
MixedCase bool
|
||||
Err bool
|
||||
}{
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "internalobjec"}, Err: true},
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "internalObjec"}, Err: true},
|
||||
{Resource: "internalobjec", Err: true},
|
||||
{Resource: "internalObjec", Err: true},
|
||||
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "internalobject"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
{Resource: "internalobject", ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
{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: "internalobject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
{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")},
|
||||
{Resource: "internalObject", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
{Resource: "internalObjects", MixedCase: true, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces)
|
||||
@ -136,19 +134,18 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) {
|
||||
|
||||
func TestRESTMapperGroupForResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Resource unversioned.GroupVersionResource
|
||||
Resource string
|
||||
GroupVersionKind unversioned.GroupVersionKind
|
||||
Err bool
|
||||
}{
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "myObject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "myobject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "myObje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: unversioned.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: "myObject", GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: "myobject", GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: "myObje", Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
{Resource: "myobje", Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces)
|
||||
mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace, false)
|
||||
|
||||
actualGVK, err := mapper.KindFor(testCase.Resource)
|
||||
if testCase.Err {
|
||||
if err == nil {
|
||||
@ -162,230 +159,6 @@ func TestRESTMapperGroupForResource(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTMapperKindsFor(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
PreferredOrder []unversioned.GroupVersion
|
||||
KindsToRegister []unversioned.GroupVersionKind
|
||||
PartialResourceToRequest unversioned.GroupVersionResource
|
||||
|
||||
ExpectedKinds []unversioned.GroupVersionKind
|
||||
ExpectedKindErr string
|
||||
}{
|
||||
{
|
||||
Name: "ambiguous groups, with preference order",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"},
|
||||
|
||||
ExpectedKinds: []unversioned.GroupVersionKind{
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
},
|
||||
ExpectedKindErr: "is ambiguous",
|
||||
},
|
||||
|
||||
{
|
||||
Name: "ambiguous groups, with explicit group match",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
|
||||
|
||||
ExpectedKinds: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "ambiguous groups, with ambiguous version match",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
|
||||
|
||||
ExpectedKinds: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
},
|
||||
ExpectedKindErr: "is ambiguous",
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
tcName := testCase.Name
|
||||
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
|
||||
for _, kind := range testCase.KindsToRegister {
|
||||
mapper.Add(kind, RESTScopeNamespace, false)
|
||||
}
|
||||
|
||||
actualKinds, err := mapper.KindsFor(testCase.PartialResourceToRequest)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", tcName, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.ExpectedKinds, actualKinds) {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds, actualKinds)
|
||||
}
|
||||
|
||||
singleKind, err := mapper.KindFor(testCase.PartialResourceToRequest)
|
||||
if err == nil && len(testCase.ExpectedKindErr) != 0 {
|
||||
t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedKindErr)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
if len(testCase.ExpectedKindErr) == 0 {
|
||||
t.Errorf("%s: unexpected error: %v", tcName, err)
|
||||
continue
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), testCase.ExpectedKindErr) {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKindErr, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if testCase.ExpectedKinds[0] != singleKind {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds[0], singleKind)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTMapperResourcesFor(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Name string
|
||||
PreferredOrder []unversioned.GroupVersion
|
||||
KindsToRegister []unversioned.GroupVersionKind
|
||||
PartialResourceToRequest unversioned.GroupVersionResource
|
||||
|
||||
ExpectedResources []unversioned.GroupVersionResource
|
||||
ExpectedResourceErr string
|
||||
}{
|
||||
{
|
||||
Name: "ambiguous groups, with preference order",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"},
|
||||
|
||||
ExpectedResources: []unversioned.GroupVersionResource{
|
||||
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
|
||||
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
|
||||
},
|
||||
ExpectedResourceErr: "is ambiguous",
|
||||
},
|
||||
|
||||
{
|
||||
Name: "ambiguous groups, with explicit group match",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
|
||||
|
||||
ExpectedResources: []unversioned.GroupVersionResource{
|
||||
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "ambiguous groups, with ambiguous version match",
|
||||
PreferredOrder: []unversioned.GroupVersion{
|
||||
{Group: "first-group", Version: "first-version"},
|
||||
{Group: "second-group", Version: "first-version"},
|
||||
},
|
||||
KindsToRegister: []unversioned.GroupVersionKind{
|
||||
{Group: "first-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "first-group", Version: "first-version", Kind: "your-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "my-kind"},
|
||||
{Group: "second-group", Version: "first-version", Kind: "your-kind"},
|
||||
},
|
||||
PartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
|
||||
|
||||
ExpectedResources: []unversioned.GroupVersionResource{
|
||||
{Group: "first-group", Version: "first-version", Resource: "my-kinds"},
|
||||
{Group: "second-group", Version: "first-version", Resource: "my-kinds"},
|
||||
},
|
||||
ExpectedResourceErr: "is ambiguous",
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
tcName := testCase.Name
|
||||
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
|
||||
for _, kind := range testCase.KindsToRegister {
|
||||
mapper.Add(kind, RESTScopeNamespace, false)
|
||||
}
|
||||
|
||||
actualResources, err := mapper.ResourcesFor(testCase.PartialResourceToRequest)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", tcName, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(testCase.ExpectedResources, actualResources) {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources, actualResources)
|
||||
}
|
||||
|
||||
singleResource, err := mapper.ResourceFor(testCase.PartialResourceToRequest)
|
||||
if err == nil && len(testCase.ExpectedResourceErr) != 0 {
|
||||
t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedResourceErr)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
if len(testCase.ExpectedResourceErr) == 0 {
|
||||
t.Errorf("%s: unexpected error: %v", tcName, err)
|
||||
continue
|
||||
} else {
|
||||
if !strings.Contains(err.Error(), testCase.ExpectedResourceErr) {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResourceErr, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if testCase.ExpectedResources[0] != singleResource {
|
||||
t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources[0], singleResource)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKindToResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Kind string
|
||||
@ -408,11 +181,9 @@ func TestKindToResource(t *testing.T) {
|
||||
{Kind: "lowercase", MixedCase: false, Plural: "lowercases", Singular: "lowercase"},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
version := unversioned.GroupVersion{}
|
||||
|
||||
plural, singular := KindToResource(version.WithKind(testCase.Kind), testCase.MixedCase)
|
||||
if singular != version.WithResource(testCase.Singular) || plural != version.WithResource(testCase.Plural) {
|
||||
t.Errorf("%d: unexpected plural and singular: %v %v", i, plural, singular)
|
||||
plural, singular := KindToResource(testCase.Kind, testCase.MixedCase)
|
||||
if singular != testCase.Singular || plural != testCase.Plural {
|
||||
t.Errorf("%d: unexpected plural and singular: %s %s", i, plural, singular)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -453,7 +224,7 @@ func TestRESTMapperResourceSingularizer(t *testing.T) {
|
||||
t.Errorf("%d: unexpected error: %v", i, err)
|
||||
}
|
||||
if singular != testCase.Singular {
|
||||
t.Errorf("%d: mismatched singular: got %v, expected %v", i, singular, testCase.Singular)
|
||||
t.Errorf("%d: mismatched singular: %s, should be %s", i, singular, testCase.Singular)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,10 +29,6 @@ type GroupResource struct {
|
||||
Resource string
|
||||
}
|
||||
|
||||
func (gr GroupResource) WithVersion(version string) GroupVersionResource {
|
||||
return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
|
||||
}
|
||||
|
||||
func (gr GroupResource) IsEmpty() bool {
|
||||
return len(gr.Group) == 0 && len(gr.Resource) == 0
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func TestRESTMapper(t *testing.T) {
|
||||
gv := unversioned.GroupVersion{Group: componentconfig.GroupName, Version: "v1alpha1"}
|
||||
proxyGVK := gv.WithKind("KubeProxyConfiguration")
|
||||
|
||||
if gvk, err := latest.GroupOrDie(componentconfig.GroupName).RESTMapper.KindFor(gv.WithResource("kubeproxyconfiguration")); err != nil || gvk != proxyGVK {
|
||||
if gvk, err := latest.GroupOrDie(componentconfig.GroupName).RESTMapper.KindFor("kubeproxyconfiguration"); err != nil || gvk != proxyGVK {
|
||||
t.Errorf("unexpected version mapping: %v %v", gvk, err)
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ func TestRESTMapper(t *testing.T) {
|
||||
hpaGVK := gv.WithKind("HorizontalPodAutoscaler")
|
||||
daemonSetGVK := gv.WithKind("DaemonSet")
|
||||
|
||||
if gvk, err := latest.GroupOrDie(extensions.GroupName).RESTMapper.KindFor(gv.WithResource("horizontalpodautoscalers")); err != nil || gvk != hpaGVK {
|
||||
if gvk, err := latest.GroupOrDie(extensions.GroupName).RESTMapper.KindFor("horizontalpodautoscalers"); err != nil || gvk != hpaGVK {
|
||||
t.Errorf("unexpected version mapping: %v %v", gvk, err)
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ package unversioned
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
@ -49,25 +48,17 @@ func newScales(c *ExtensionsClient, namespace string) *scales {
|
||||
// Get takes the reference to scale subresource and returns the subresource or error, if one occurs.
|
||||
func (c *scales) Get(kind string, name string) (result *extensions.Scale, err error) {
|
||||
result = &extensions.Scale{}
|
||||
|
||||
// TODO this method needs to take a proper unambiguous kind
|
||||
fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind}
|
||||
resource, _ := meta.KindToResource(fullyQualifiedKind, false)
|
||||
|
||||
err = c.client.Get().Namespace(c.ns).Resource(resource.Resource).Name(name).SubResource("scale").Do().Into(result)
|
||||
resource, _ := meta.KindToResource(kind, false)
|
||||
err = c.client.Get().Namespace(c.ns).Resource(resource).Name(name).SubResource("scale").Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *scales) Update(kind string, scale *extensions.Scale) (result *extensions.Scale, err error) {
|
||||
result = &extensions.Scale{}
|
||||
|
||||
// TODO this method needs to take a proper unambiguous kind
|
||||
fullyQualifiedKind := unversioned.GroupVersionKind{Kind: kind}
|
||||
resource, _ := meta.KindToResource(fullyQualifiedKind, false)
|
||||
|
||||
resource, _ := meta.KindToResource(kind, false)
|
||||
err = c.client.Put().
|
||||
Namespace(scale.Namespace).
|
||||
Resource(resource.Resource).
|
||||
Resource(resource).
|
||||
Name(scale.Name).
|
||||
SubResource("scale").
|
||||
Body(scale).
|
||||
|
@ -59,7 +59,7 @@ type ObjectScheme interface {
|
||||
func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
|
||||
return func(action Action) (bool, runtime.Object, error) {
|
||||
kind, err := mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetResource()})
|
||||
gvk, err := mapper.KindFor(action.GetResource())
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err)
|
||||
}
|
||||
@ -67,16 +67,16 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
// TODO: have mapper return a Kind for a subresource?
|
||||
switch castAction := action.(type) {
|
||||
case ListAction:
|
||||
kind.Kind += "List"
|
||||
resource, err := o.Kind(kind, "")
|
||||
gvk.Kind += "List"
|
||||
resource, err := o.Kind(gvk, "")
|
||||
return true, resource, err
|
||||
|
||||
case GetAction:
|
||||
resource, err := o.Kind(kind, castAction.GetName())
|
||||
resource, err := o.Kind(gvk, castAction.GetName())
|
||||
return true, resource, err
|
||||
|
||||
case DeleteAction:
|
||||
resource, err := o.Kind(kind, castAction.GetName())
|
||||
resource, err := o.Kind(gvk, castAction.GetName())
|
||||
return true, resource, err
|
||||
|
||||
case CreateAction:
|
||||
@ -84,7 +84,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
resource, err := o.Kind(kind, meta.Name)
|
||||
resource, err := o.Kind(gvk, meta.Name)
|
||||
return true, resource, err
|
||||
|
||||
case UpdateAction:
|
||||
@ -92,7 +92,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
resource, err := o.Kind(kind, meta.Name)
|
||||
resource, err := o.Kind(gvk, meta.Name)
|
||||
return true, resource, err
|
||||
|
||||
default:
|
||||
|
@ -84,7 +84,7 @@ func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
|
||||
}
|
||||
|
||||
// TODO: We should deduce the group for a resource by discovering the supported resources at server.
|
||||
gvk, err := mapper.KindFor(unversioned.GroupVersionResource{Resource: inModel})
|
||||
gvk, err := mapper.KindFor(inModel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -360,12 +360,12 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
|
||||
if outputFormat != "" {
|
||||
return f.PrintObject(cmd, newRc, out)
|
||||
}
|
||||
kind, err := api.Scheme.ObjectKind(newRc)
|
||||
gvk, err := api.Scheme.ObjectKind(newRc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, res := meta.KindToResource(kind, false)
|
||||
cmdutil.PrintSuccess(mapper, false, out, res.Resource, oldName, message)
|
||||
_, res := meta.KindToResource(gvk.Kind, false)
|
||||
cmdutil.PrintSuccess(mapper, false, out, res, oldName, message)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -175,12 +175,16 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
return clients.ClientConfigForVersion(nil)
|
||||
},
|
||||
RESTClient: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
gvk, err := api.RESTMapper.KindFor(mapping.Resource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mappingVersion := mapping.GroupVersionKind.GroupVersion()
|
||||
client, err := clients.ClientForVersion(&mappingVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch mapping.GroupVersionKind.Group {
|
||||
switch gvk.Group {
|
||||
case api.GroupName:
|
||||
return client.RESTClient, nil
|
||||
case extensions.GroupName:
|
||||
|
@ -44,7 +44,7 @@ func GetSwaggerSchema(version unversioned.GroupVersion, kubeClient client.Interf
|
||||
// SplitAndParseResourceRequest separates the users input into a model and fields
|
||||
func SplitAndParseResourceRequest(inResource string, mapper meta.RESTMapper) (string, []string, error) {
|
||||
inResource, fieldsPath := splitDotNotation(inResource)
|
||||
inResource, _ = mapper.ResourceSingularizer(expandResourceShortcut(unversioned.GroupVersionResource{Resource: inResource}).Resource)
|
||||
inResource, _ = mapper.ResourceSingularizer(expandResourceShortcut(inResource))
|
||||
return inResource, fieldsPath, nil
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
const kubectlAnnotationPrefix = "kubectl.kubernetes.io/"
|
||||
@ -81,40 +80,40 @@ var _ meta.RESTMapper = &ShortcutExpander{}
|
||||
|
||||
// KindFor implements meta.RESTMapper. It expands the resource first, then invokes the wrapped
|
||||
// mapper.
|
||||
func (e ShortcutExpander) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
|
||||
func (e ShortcutExpander) KindFor(resource string) (unversioned.GroupVersionKind, error) {
|
||||
resource = expandResourceShortcut(resource)
|
||||
return e.RESTMapper.KindFor(resource)
|
||||
}
|
||||
|
||||
// ResourceIsValid takes a string (kind) and checks if it's a valid resource.
|
||||
// It expands the resource first, then invokes the wrapped mapper.
|
||||
func (e ShortcutExpander) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
||||
func (e ShortcutExpander) ResourceIsValid(resource string) bool {
|
||||
return e.RESTMapper.ResourceIsValid(expandResourceShortcut(resource))
|
||||
}
|
||||
|
||||
// expandResourceShortcut will return the expanded version of resource
|
||||
// (something that a pkg/api/meta.RESTMapper can understand), if it is
|
||||
// indeed a shortcut. Otherwise, will return resource unmodified.
|
||||
func expandResourceShortcut(resource unversioned.GroupVersionResource) unversioned.GroupVersionResource {
|
||||
shortForms := map[string]unversioned.GroupVersionResource{
|
||||
func expandResourceShortcut(resource string) string {
|
||||
shortForms := map[string]string{
|
||||
// Please keep this alphabetized
|
||||
"cs": api.SchemeGroupVersion.WithResource("componentstatuses"),
|
||||
"ds": extensions.SchemeGroupVersion.WithResource("daemonsets"),
|
||||
"ep": api.SchemeGroupVersion.WithResource("endpoints"),
|
||||
"ev": api.SchemeGroupVersion.WithResource("events"),
|
||||
"hpa": extensions.SchemeGroupVersion.WithResource("horizontalpodautoscalers"),
|
||||
"ing": extensions.SchemeGroupVersion.WithResource("ingresses"),
|
||||
"limits": api.SchemeGroupVersion.WithResource("limitranges"),
|
||||
"no": api.SchemeGroupVersion.WithResource("nodes"),
|
||||
"ns": api.SchemeGroupVersion.WithResource("namespaces"),
|
||||
"po": api.SchemeGroupVersion.WithResource("pods"),
|
||||
"pvc": api.SchemeGroupVersion.WithResource("persistentvolumeclaims"),
|
||||
"pv": api.SchemeGroupVersion.WithResource("persistentvolumes"),
|
||||
"quota": api.SchemeGroupVersion.WithResource("resourcequotas"),
|
||||
"rc": api.SchemeGroupVersion.WithResource("replicationcontrollers"),
|
||||
"svc": api.SchemeGroupVersion.WithResource("services"),
|
||||
"cs": "componentstatuses",
|
||||
"ds": "daemonsets",
|
||||
"ep": "endpoints",
|
||||
"ev": "events",
|
||||
"hpa": "horizontalpodautoscalers",
|
||||
"ing": "ingresses",
|
||||
"limits": "limitranges",
|
||||
"no": "nodes",
|
||||
"ns": "namespaces",
|
||||
"po": "pods",
|
||||
"pvc": "persistentvolumeclaims",
|
||||
"pv": "persistentvolumes",
|
||||
"quota": "resourcequotas",
|
||||
"rc": "replicationcontrollers",
|
||||
"svc": "services",
|
||||
}
|
||||
if expanded, ok := shortForms[resource.Resource]; ok {
|
||||
if expanded, ok := shortForms[resource]; ok {
|
||||
return expanded
|
||||
}
|
||||
return resource
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
@ -427,7 +426,7 @@ func (b *Builder) resourceMappings() ([]*meta.RESTMapping, error) {
|
||||
}
|
||||
mappings := []*meta.RESTMapping{}
|
||||
for _, r := range b.resources {
|
||||
gvk, err := b.mapper.KindFor(unversioned.GroupVersionResource{Resource: r})
|
||||
gvk, err := b.mapper.KindFor(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -447,7 +446,7 @@ func (b *Builder) resourceTupleMappings() (map[string]*meta.RESTMapping, error)
|
||||
if _, ok := mappings[r.Resource]; ok {
|
||||
continue
|
||||
}
|
||||
gvk, err := b.mapper.KindFor(unversioned.GroupVersionResource{Resource: r.Resource})
|
||||
gvk, err := b.mapper.KindFor(r.Resource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -203,24 +203,11 @@ type NamePrinter struct {
|
||||
// and print "resource/name" pair. If the object is a List, print all items in it.
|
||||
func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
objvalue := reflect.ValueOf(obj).Elem()
|
||||
kindString := objvalue.FieldByName("Kind")
|
||||
groupVersionString := objvalue.FieldByName("APIVersion")
|
||||
kind := unversioned.GroupVersionKind{}
|
||||
if !kindString.IsValid() {
|
||||
kindString = reflect.ValueOf("<unknown>")
|
||||
kind := objvalue.FieldByName("Kind")
|
||||
if !kind.IsValid() {
|
||||
kind = reflect.ValueOf("<unknown>")
|
||||
}
|
||||
kind.Kind = kindString.String()
|
||||
|
||||
if !groupVersionString.IsValid() {
|
||||
groupVersionString = reflect.ValueOf("<unknown>/<unknown>")
|
||||
}
|
||||
gv, err := unversioned.ParseGroupVersion(groupVersionString.String())
|
||||
if err != nil {
|
||||
kind.Group = gv.Group
|
||||
kind.Version = gv.Version
|
||||
}
|
||||
|
||||
if kind.Kind == "List" {
|
||||
if kind.String() == "List" {
|
||||
items := objvalue.FieldByName("Items")
|
||||
if items.Type().String() == "[]runtime.RawExtension" {
|
||||
for i := 0; i < items.Len(); i++ {
|
||||
@ -250,9 +237,9 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
if !name.IsValid() {
|
||||
name = reflect.ValueOf("<unknown>")
|
||||
}
|
||||
_, resource := meta.KindToResource(kind, false)
|
||||
_, resource := meta.KindToResource(kind.String(), false)
|
||||
|
||||
fmt.Fprintf(w, "%s/%s\n", resource.Resource, name)
|
||||
fmt.Fprintf(w, "%s/%s\n", resource, name)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -41,55 +41,14 @@ type thirdPartyResourceDataMapper struct {
|
||||
|
||||
var _ meta.RESTMapper = &thirdPartyResourceDataMapper{}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) getResource() unversioned.GroupVersionResource {
|
||||
plural, _ := meta.KindToResource(t.getKind(), false)
|
||||
|
||||
return plural
|
||||
func (t *thirdPartyResourceDataMapper) isThirdPartyResource(resource string) bool {
|
||||
plural, _ := meta.KindToResource(t.kind, false)
|
||||
return resource == plural
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) getKind() unversioned.GroupVersionKind {
|
||||
return unversioned.GroupVersionKind{Group: t.group, Version: t.version, Kind: t.kind}
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) isThirdPartyResource(partialResource unversioned.GroupVersionResource) bool {
|
||||
actualResource := t.getResource()
|
||||
if strings.ToLower(partialResource.Resource) != strings.ToLower(actualResource.Resource) {
|
||||
return false
|
||||
}
|
||||
if len(partialResource.Group) != 0 && partialResource.Group != actualResource.Group {
|
||||
return false
|
||||
}
|
||||
if len(partialResource.Version) != 0 && partialResource.Version != actualResource.Version {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
|
||||
func (t *thirdPartyResourceDataMapper) KindFor(resource string) (unversioned.GroupVersionKind, error) {
|
||||
if t.isThirdPartyResource(resource) {
|
||||
return []unversioned.GroupVersionResource{t.getResource()}, nil
|
||||
}
|
||||
return t.mapper.ResourcesFor(resource)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
|
||||
if t.isThirdPartyResource(resource) {
|
||||
return []unversioned.GroupVersionKind{t.getKind()}, nil
|
||||
}
|
||||
return t.mapper.KindsFor(resource)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
|
||||
if t.isThirdPartyResource(resource) {
|
||||
return t.getResource(), nil
|
||||
}
|
||||
return t.mapper.ResourceFor(resource)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
|
||||
if t.isThirdPartyResource(resource) {
|
||||
return t.getKind(), nil
|
||||
return unversioned.GroupVersionKind{Group: t.group, Version: t.version, Kind: t.kind}, nil
|
||||
}
|
||||
return t.mapper.KindFor(resource)
|
||||
}
|
||||
@ -127,7 +86,8 @@ func (t *thirdPartyResourceDataMapper) ResourceSingularizer(resource string) (si
|
||||
return t.mapper.ResourceSingularizer(resource)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool {
|
||||
// ResourceIsValid takes a string (kind) and checks if it's a valid resource
|
||||
func (t *thirdPartyResourceDataMapper) ResourceIsValid(resource string) bool {
|
||||
return t.isThirdPartyResource(resource) || t.mapper.ResourceIsValid(resource)
|
||||
}
|
||||
|
||||
|
@ -212,9 +212,9 @@ func TestResourceIsValid(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
mapper := &thirdPartyResourceDataMapper{kind: test.kind}
|
||||
mapper.mapper = api.RESTMapper
|
||||
valid := mapper.ResourceIsValid(unversioned.GroupVersionResource{Resource: test.resource})
|
||||
valid := mapper.ResourceIsValid(test.resource)
|
||||
if valid != test.valid {
|
||||
t.Errorf("%s: expected: %v, actual: %v", test.name, test.valid, valid)
|
||||
t.Errorf("expected: %v, saw: %v for %s", test.valid, valid, test.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +45,11 @@ type provision struct {
|
||||
}
|
||||
|
||||
func (p *provision) Admit(a admission.Attributes) (err error) {
|
||||
kind, err := api.RESTMapper.KindFor(a.GetResource().WithVersion(""))
|
||||
gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
mapping, err := api.RESTMapper.RESTMapping(kind.GroupKind(), kind.Version)
|
||||
mapping, err := api.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
|
@ -46,11 +46,11 @@ type exists struct {
|
||||
}
|
||||
|
||||
func (e *exists) Admit(a admission.Attributes) (err error) {
|
||||
kind, err := api.RESTMapper.KindFor(a.GetResource().WithVersion(""))
|
||||
gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
|
||||
if err != nil {
|
||||
return errors.NewInternalError(err)
|
||||
}
|
||||
mapping, err := api.RESTMapper.RESTMapping(kind.GroupKind(), kind.Version)
|
||||
mapping, err := api.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return errors.NewInternalError(err)
|
||||
}
|
||||
|
@ -48,16 +48,17 @@ type lifecycle struct {
|
||||
}
|
||||
|
||||
func (l *lifecycle) Admit(a admission.Attributes) (err error) {
|
||||
|
||||
// prevent deletion of immortal namespaces
|
||||
if a.GetOperation() == admission.Delete && a.GetKind() == api.Kind("Namespace") && l.immortalNamespaces.Has(a.GetName()) {
|
||||
return errors.NewForbidden(a.GetResource(), a.GetName(), fmt.Errorf("this namespace may not be deleted"))
|
||||
}
|
||||
|
||||
kind, err := api.RESTMapper.KindFor(a.GetResource().WithVersion(""))
|
||||
gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
|
||||
if err != nil {
|
||||
return errors.NewInternalError(err)
|
||||
}
|
||||
mapping, err := api.RESTMapper.RESTMapping(kind.GroupKind(), kind.Version)
|
||||
mapping, err := api.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return errors.NewInternalError(err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user