init
This commit is contained in:
		
							
								
								
									
										25
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| reviewers: | ||||
| - thockin | ||||
| - smarterclayton | ||||
| - wojtek-t | ||||
| - deads2k | ||||
| - brendandburns | ||||
| - derekwaynecarr | ||||
| - caesarxuchao | ||||
| - mikedanese | ||||
| - liggitt | ||||
| - nikhiljindal | ||||
| - gmarek | ||||
| - janetkuo | ||||
| - ncdc | ||||
| - eparis | ||||
| - dims | ||||
| - krousey | ||||
| - markturansky | ||||
| - fabioy | ||||
| - resouer | ||||
| - david-mcmahon | ||||
| - mfojtik | ||||
| - jianhuiz | ||||
| - feihujiang | ||||
| - ghodss | ||||
							
								
								
									
										19
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta provides functions for retrieving API metadata from objects | ||||
| // belonging to the Kubernetes API | ||||
| package meta // import "k8s.io/apimachinery/pkg/api/meta" | ||||
							
								
								
									
										121
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/util/sets" | ||||
| ) | ||||
|  | ||||
| // AmbiguousResourceError is returned if the RESTMapper finds multiple matches for a resource | ||||
| type AmbiguousResourceError struct { | ||||
| 	PartialResource schema.GroupVersionResource | ||||
|  | ||||
| 	MatchingResources []schema.GroupVersionResource | ||||
| 	MatchingKinds     []schema.GroupVersionKind | ||||
| } | ||||
|  | ||||
| func (e *AmbiguousResourceError) Error() string { | ||||
| 	switch { | ||||
| 	case len(e.MatchingKinds) > 0 && len(e.MatchingResources) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple resources %v and kinds %v", e.PartialResource, e.MatchingResources, e.MatchingKinds) | ||||
| 	case len(e.MatchingKinds) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple kinds %v", e.PartialResource, e.MatchingKinds) | ||||
| 	case len(e.MatchingResources) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple resources %v", e.PartialResource, e.MatchingResources) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%v matches multiple resources or kinds", e.PartialResource) | ||||
| } | ||||
|  | ||||
| // AmbiguousKindError is returned if the RESTMapper finds multiple matches for a kind | ||||
| type AmbiguousKindError struct { | ||||
| 	PartialKind schema.GroupVersionKind | ||||
|  | ||||
| 	MatchingResources []schema.GroupVersionResource | ||||
| 	MatchingKinds     []schema.GroupVersionKind | ||||
| } | ||||
|  | ||||
| func (e *AmbiguousKindError) Error() string { | ||||
| 	switch { | ||||
| 	case len(e.MatchingKinds) > 0 && len(e.MatchingResources) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple resources %v and kinds %v", e.PartialKind, e.MatchingResources, e.MatchingKinds) | ||||
| 	case len(e.MatchingKinds) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple kinds %v", e.PartialKind, e.MatchingKinds) | ||||
| 	case len(e.MatchingResources) > 0: | ||||
| 		return fmt.Sprintf("%v matches multiple resources %v", e.PartialKind, e.MatchingResources) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%v matches multiple resources or kinds", e.PartialKind) | ||||
| } | ||||
|  | ||||
| func IsAmbiguousError(err error) bool { | ||||
| 	if err == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	switch err.(type) { | ||||
| 	case *AmbiguousResourceError, *AmbiguousKindError: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NoResourceMatchError is returned if the RESTMapper can't find any match for a resource | ||||
| type NoResourceMatchError struct { | ||||
| 	PartialResource schema.GroupVersionResource | ||||
| } | ||||
|  | ||||
| func (e *NoResourceMatchError) Error() string { | ||||
| 	return fmt.Sprintf("no matches for %v", e.PartialResource) | ||||
| } | ||||
|  | ||||
| // NoKindMatchError is returned if the RESTMapper can't find any match for a kind | ||||
| type NoKindMatchError struct { | ||||
| 	// GroupKind is the API group and kind that was searched | ||||
| 	GroupKind schema.GroupKind | ||||
| 	// SearchedVersions is the optional list of versions the search was restricted to | ||||
| 	SearchedVersions []string | ||||
| } | ||||
|  | ||||
| func (e *NoKindMatchError) Error() string { | ||||
| 	searchedVersions := sets.NewString() | ||||
| 	for _, v := range e.SearchedVersions { | ||||
| 		searchedVersions.Insert(schema.GroupVersion{Group: e.GroupKind.Group, Version: v}.String()) | ||||
| 	} | ||||
|  | ||||
| 	switch len(searchedVersions) { | ||||
| 	case 0: | ||||
| 		return fmt.Sprintf("no matches for kind %q in group %q", e.GroupKind.Kind, e.GroupKind.Group) | ||||
| 	case 1: | ||||
| 		return fmt.Sprintf("no matches for kind %q in version %q", e.GroupKind.Kind, searchedVersions.List()[0]) | ||||
| 	default: | ||||
| 		return fmt.Sprintf("no matches for kind %q in versions %q", e.GroupKind.Kind, searchedVersions.List()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func IsNoMatchError(err error) bool { | ||||
| 	if err == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	switch err.(type) { | ||||
| 	case *NoResourceMatchError, *NoKindMatchError: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/firsthit_restmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/firsthit_restmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	utilerrors "k8s.io/apimachinery/pkg/util/errors" | ||||
| ) | ||||
|  | ||||
| // FirstHitRESTMapper is a wrapper for multiple RESTMappers which returns the | ||||
| // first successful result for the singular requests | ||||
| type FirstHitRESTMapper struct { | ||||
| 	MultiRESTMapper | ||||
| } | ||||
|  | ||||
| func (m FirstHitRESTMapper) String() string { | ||||
| 	return fmt.Sprintf("FirstHitRESTMapper{\n\t%v\n}", m.MultiRESTMapper) | ||||
| } | ||||
|  | ||||
| func (m FirstHitRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { | ||||
| 	errors := []error{} | ||||
| 	for _, t := range m.MultiRESTMapper { | ||||
| 		ret, err := t.ResourceFor(resource) | ||||
| 		if err == nil { | ||||
| 			return ret, nil | ||||
| 		} | ||||
| 		errors = append(errors, err) | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionResource{}, collapseAggregateErrors(errors) | ||||
| } | ||||
|  | ||||
| func (m FirstHitRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { | ||||
| 	errors := []error{} | ||||
| 	for _, t := range m.MultiRESTMapper { | ||||
| 		ret, err := t.KindFor(resource) | ||||
| 		if err == nil { | ||||
| 			return ret, nil | ||||
| 		} | ||||
| 		errors = append(errors, err) | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionKind{}, collapseAggregateErrors(errors) | ||||
| } | ||||
|  | ||||
| // RESTMapping provides the REST mapping for the resource based on the | ||||
| // kind and version. This implementation supports multiple REST schemas and | ||||
| // return the first match. | ||||
| func (m FirstHitRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { | ||||
| 	errors := []error{} | ||||
| 	for _, t := range m.MultiRESTMapper { | ||||
| 		ret, err := t.RESTMapping(gk, versions...) | ||||
| 		if err == nil { | ||||
| 			return ret, nil | ||||
| 		} | ||||
| 		errors = append(errors, err) | ||||
| 	} | ||||
|  | ||||
| 	return nil, collapseAggregateErrors(errors) | ||||
| } | ||||
|  | ||||
| // collapseAggregateErrors returns the minimal errors.  it handles empty as nil, handles one item in a list | ||||
| // by returning the item, and collapses all NoMatchErrors to a single one (since they should all be the same) | ||||
| func collapseAggregateErrors(errors []error) error { | ||||
| 	if len(errors) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if len(errors) == 1 { | ||||
| 		return errors[0] | ||||
| 	} | ||||
|  | ||||
| 	allNoMatchErrors := true | ||||
| 	for _, err := range errors { | ||||
| 		allNoMatchErrors = allNoMatchErrors && IsNoMatchError(err) | ||||
| 	} | ||||
| 	if allNoMatchErrors { | ||||
| 		return errors[0] | ||||
| 	} | ||||
|  | ||||
| 	return utilerrors.NewAggregate(errors) | ||||
| } | ||||
							
								
								
									
										218
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/help.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/help.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,218 @@ | ||||
| /* | ||||
| Copyright 2015 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/conversion" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| ) | ||||
|  | ||||
| // IsListType returns true if the provided Object has a slice called Items | ||||
| func IsListType(obj runtime.Object) bool { | ||||
| 	// if we're a runtime.Unstructured, check whether this is a list. | ||||
| 	// TODO: refactor GetItemsPtr to use an interface that returns []runtime.Object | ||||
| 	if unstructured, ok := obj.(runtime.Unstructured); ok { | ||||
| 		return unstructured.IsList() | ||||
| 	} | ||||
|  | ||||
| 	_, err := GetItemsPtr(obj) | ||||
| 	return err == nil | ||||
| } | ||||
|  | ||||
| // GetItemsPtr returns a pointer to the list object's Items member. | ||||
| // If 'list' doesn't have an Items member, it's not really a list type | ||||
| // and an error will be returned. | ||||
| // This function will either return a pointer to a slice, or an error, but not both. | ||||
| func GetItemsPtr(list runtime.Object) (interface{}, error) { | ||||
| 	v, err := conversion.EnforcePtr(list) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	items := v.FieldByName("Items") | ||||
| 	if !items.IsValid() { | ||||
| 		return nil, fmt.Errorf("no Items field in %#v", list) | ||||
| 	} | ||||
| 	switch items.Kind() { | ||||
| 	case reflect.Interface, reflect.Ptr: | ||||
| 		target := reflect.TypeOf(items.Interface()).Elem() | ||||
| 		if target.Kind() != reflect.Slice { | ||||
| 			return nil, fmt.Errorf("items: Expected slice, got %s", target.Kind()) | ||||
| 		} | ||||
| 		return items.Interface(), nil | ||||
| 	case reflect.Slice: | ||||
| 		return items.Addr().Interface(), nil | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("items: Expected slice, got %s", items.Kind()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // EachListItem invokes fn on each runtime.Object in the list. Any error immediately terminates | ||||
| // the loop. | ||||
| func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error { | ||||
| 	if unstructured, ok := obj.(runtime.Unstructured); ok { | ||||
| 		return unstructured.EachListItem(fn) | ||||
| 	} | ||||
| 	// TODO: Change to an interface call? | ||||
| 	itemsPtr, err := GetItemsPtr(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	items, err := conversion.EnforcePtr(itemsPtr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	len := items.Len() | ||||
| 	if len == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	takeAddr := false | ||||
| 	if elemType := items.Type().Elem(); elemType.Kind() != reflect.Ptr && elemType.Kind() != reflect.Interface { | ||||
| 		if !items.Index(0).CanAddr() { | ||||
| 			return fmt.Errorf("unable to take address of items in %T for EachListItem", obj) | ||||
| 		} | ||||
| 		takeAddr = true | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len; i++ { | ||||
| 		raw := items.Index(i) | ||||
| 		if takeAddr { | ||||
| 			raw = raw.Addr() | ||||
| 		} | ||||
| 		switch item := raw.Interface().(type) { | ||||
| 		case *runtime.RawExtension: | ||||
| 			if err := fn(item.Object); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		case runtime.Object: | ||||
| 			if err := fn(item); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		default: | ||||
| 			obj, ok := item.(runtime.Object) | ||||
| 			if !ok { | ||||
| 				return fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind()) | ||||
| 			} | ||||
| 			if err := fn(obj); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ExtractList returns obj's Items element as an array of runtime.Objects. | ||||
| // Returns an error if obj is not a List type (does not have an Items member). | ||||
| func ExtractList(obj runtime.Object) ([]runtime.Object, error) { | ||||
| 	itemsPtr, err := GetItemsPtr(obj) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	items, err := conversion.EnforcePtr(itemsPtr) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	list := make([]runtime.Object, items.Len()) | ||||
| 	for i := range list { | ||||
| 		raw := items.Index(i) | ||||
| 		switch item := raw.Interface().(type) { | ||||
| 		case runtime.RawExtension: | ||||
| 			switch { | ||||
| 			case item.Object != nil: | ||||
| 				list[i] = item.Object | ||||
| 			case item.Raw != nil: | ||||
| 				// TODO: Set ContentEncoding and ContentType correctly. | ||||
| 				list[i] = &runtime.Unknown{Raw: item.Raw} | ||||
| 			default: | ||||
| 				list[i] = nil | ||||
| 			} | ||||
| 		case runtime.Object: | ||||
| 			list[i] = item | ||||
| 		default: | ||||
| 			var found bool | ||||
| 			if list[i], found = raw.Addr().Interface().(runtime.Object); !found { | ||||
| 				return nil, fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind()) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return list, nil | ||||
| } | ||||
|  | ||||
| // objectSliceType is the type of a slice of Objects | ||||
| var objectSliceType = reflect.TypeOf([]runtime.Object{}) | ||||
|  | ||||
| // LenList returns the length of this list or 0 if it is not a list. | ||||
| func LenList(list runtime.Object) int { | ||||
| 	itemsPtr, err := GetItemsPtr(list) | ||||
| 	if err != nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	items, err := conversion.EnforcePtr(itemsPtr) | ||||
| 	if err != nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return items.Len() | ||||
| } | ||||
|  | ||||
| // SetList sets the given list object's Items member have the elements given in | ||||
| // objects. | ||||
| // Returns an error if list is not a List type (does not have an Items member), | ||||
| // or if any of the objects are not of the right type. | ||||
| func SetList(list runtime.Object, objects []runtime.Object) error { | ||||
| 	itemsPtr, err := GetItemsPtr(list) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	items, err := conversion.EnforcePtr(itemsPtr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if items.Type() == objectSliceType { | ||||
| 		items.Set(reflect.ValueOf(objects)) | ||||
| 		return nil | ||||
| 	} | ||||
| 	slice := reflect.MakeSlice(items.Type(), len(objects), len(objects)) | ||||
| 	for i := range objects { | ||||
| 		dest := slice.Index(i) | ||||
| 		if dest.Type() == reflect.TypeOf(runtime.RawExtension{}) { | ||||
| 			dest = dest.FieldByName("Object") | ||||
| 		} | ||||
|  | ||||
| 		// check to see if you're directly assignable | ||||
| 		if reflect.TypeOf(objects[i]).AssignableTo(dest.Type()) { | ||||
| 			dest.Set(reflect.ValueOf(objects[i])) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		src, err := conversion.EnforcePtr(objects[i]) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if src.Type().AssignableTo(dest.Type()) { | ||||
| 			dest.Set(src) | ||||
| 		} else if src.Type().ConvertibleTo(dest.Type()) { | ||||
| 			dest.Set(src.Convert(dest.Type())) | ||||
| 		} else { | ||||
| 			return fmt.Errorf("item[%d]: can't assign or convert %v into %v", i, src.Type(), dest.Type()) | ||||
| 		} | ||||
| 	} | ||||
| 	items.Set(slice) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										134
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/interfaces.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| ) | ||||
|  | ||||
| type ListMetaAccessor interface { | ||||
| 	GetListMeta() List | ||||
| } | ||||
|  | ||||
| // List lets you work with list metadata from any of the versioned or | ||||
| // internal API objects. Attempting to set or retrieve a field on an object that does | ||||
| // not support that field will be a no-op and return a default value. | ||||
| type List metav1.ListInterface | ||||
|  | ||||
| // Type exposes the type and APIVersion of versioned or internal API objects. | ||||
| type Type metav1.Type | ||||
|  | ||||
| // MetadataAccessor lets you work with object and list metadata from any of the versioned or | ||||
| // internal API objects. Attempting to set or retrieve a field on an object that does | ||||
| // not support that field (Name, UID, Namespace on lists) will be a no-op and return | ||||
| // a default value. | ||||
| // | ||||
| // MetadataAccessor exposes Interface in a way that can be used with multiple objects. | ||||
| type MetadataAccessor interface { | ||||
| 	APIVersion(obj runtime.Object) (string, error) | ||||
| 	SetAPIVersion(obj runtime.Object, version string) error | ||||
|  | ||||
| 	Kind(obj runtime.Object) (string, error) | ||||
| 	SetKind(obj runtime.Object, kind string) error | ||||
|  | ||||
| 	Namespace(obj runtime.Object) (string, error) | ||||
| 	SetNamespace(obj runtime.Object, namespace string) error | ||||
|  | ||||
| 	Name(obj runtime.Object) (string, error) | ||||
| 	SetName(obj runtime.Object, name string) error | ||||
|  | ||||
| 	GenerateName(obj runtime.Object) (string, error) | ||||
| 	SetGenerateName(obj runtime.Object, name string) error | ||||
|  | ||||
| 	UID(obj runtime.Object) (types.UID, error) | ||||
| 	SetUID(obj runtime.Object, uid types.UID) error | ||||
|  | ||||
| 	SelfLink(obj runtime.Object) (string, error) | ||||
| 	SetSelfLink(obj runtime.Object, selfLink string) error | ||||
|  | ||||
| 	Labels(obj runtime.Object) (map[string]string, error) | ||||
| 	SetLabels(obj runtime.Object, labels map[string]string) error | ||||
|  | ||||
| 	Annotations(obj runtime.Object) (map[string]string, error) | ||||
| 	SetAnnotations(obj runtime.Object, annotations map[string]string) error | ||||
|  | ||||
| 	Continue(obj runtime.Object) (string, error) | ||||
| 	SetContinue(obj runtime.Object, c string) error | ||||
|  | ||||
| 	runtime.ResourceVersioner | ||||
| } | ||||
|  | ||||
| type RESTScopeName string | ||||
|  | ||||
| const ( | ||||
| 	RESTScopeNameNamespace RESTScopeName = "namespace" | ||||
| 	RESTScopeNameRoot      RESTScopeName = "root" | ||||
| ) | ||||
|  | ||||
| // RESTScope contains the information needed to deal with REST resources that are in a resource hierarchy | ||||
| type RESTScope interface { | ||||
| 	// Name of the scope | ||||
| 	Name() RESTScopeName | ||||
| } | ||||
|  | ||||
| // RESTMapping contains the information needed to deal with objects of a specific | ||||
| // resource and kind in a RESTful manner. | ||||
| type RESTMapping struct { | ||||
| 	// Resource is the GroupVersionResource (location) for this endpoint | ||||
| 	Resource schema.GroupVersionResource | ||||
|  | ||||
| 	// GroupVersionKind is the GroupVersionKind (data format) to submit to this endpoint | ||||
| 	GroupVersionKind schema.GroupVersionKind | ||||
|  | ||||
| 	// Scope contains the information needed to deal with REST Resources that are in a resource hierarchy | ||||
| 	Scope RESTScope | ||||
| } | ||||
|  | ||||
| // RESTMapper allows clients to map resources to kind, and map kind and version | ||||
| // to interfaces for manipulating those objects. It is primarily intended for | ||||
| // consumers of Kubernetes compatible REST APIs as defined in docs/devel/api-conventions.md. | ||||
| // | ||||
| // The Kubernetes API provides versioned resources and object kinds which are scoped | ||||
| // to API groups. In other words, kinds and resources should not be assumed to be | ||||
| // unique across groups. | ||||
| // | ||||
| // TODO: split into sub-interfaces | ||||
| type RESTMapper interface { | ||||
| 	// KindFor takes a partial resource and returns the single match.  Returns an error if there are multiple matches | ||||
| 	KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) | ||||
|  | ||||
| 	// KindsFor takes a partial resource and returns the list of potential kinds in priority order | ||||
| 	KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) | ||||
|  | ||||
| 	// ResourceFor takes a partial resource and returns the single match.  Returns an error if there are multiple matches | ||||
| 	ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) | ||||
|  | ||||
| 	// ResourcesFor takes a partial resource and returns the list of potential resource in priority order | ||||
| 	ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) | ||||
|  | ||||
| 	// RESTMapping identifies a preferred resource mapping for the provided group kind. | ||||
| 	RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) | ||||
| 	// RESTMappings returns all resource mappings for the provided group kind if no | ||||
| 	// version search is provided. Otherwise identifies a preferred resource mapping for | ||||
| 	// the provided version(s). | ||||
| 	RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) | ||||
|  | ||||
| 	ResourceSingularizer(resource string) (singular string, err error) | ||||
| } | ||||
							
								
								
									
										104
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/lazy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| /* | ||||
| Copyright 2017 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"sync" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| // lazyObject defers loading the mapper and typer until necessary. | ||||
| type lazyObject struct { | ||||
| 	loader func() (RESTMapper, error) | ||||
|  | ||||
| 	lock   sync.Mutex | ||||
| 	loaded bool | ||||
| 	err    error | ||||
| 	mapper RESTMapper | ||||
| } | ||||
|  | ||||
| // NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by | ||||
| // returning those initialization errors when the interface methods are invoked. This defers the | ||||
| // initialization and any server calls until a client actually needs to perform the action. | ||||
| func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper { | ||||
| 	obj := &lazyObject{loader: fn} | ||||
| 	return obj | ||||
| } | ||||
|  | ||||
| // init lazily loads the mapper and typer, returning an error if initialization has failed. | ||||
| func (o *lazyObject) init() error { | ||||
| 	o.lock.Lock() | ||||
| 	defer o.lock.Unlock() | ||||
| 	if o.loaded { | ||||
| 		return o.err | ||||
| 	} | ||||
| 	o.mapper, o.err = o.loader() | ||||
| 	o.loaded = true | ||||
| 	return o.err | ||||
| } | ||||
|  | ||||
| var _ RESTMapper = &lazyObject{} | ||||
|  | ||||
| func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return schema.GroupVersionKind{}, err | ||||
| 	} | ||||
| 	return o.mapper.KindFor(resource) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return []schema.GroupVersionKind{}, err | ||||
| 	} | ||||
| 	return o.mapper.KindsFor(resource) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return schema.GroupVersionResource{}, err | ||||
| 	} | ||||
| 	return o.mapper.ResourceFor(input) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return []schema.GroupVersionResource{}, err | ||||
| 	} | ||||
| 	return o.mapper.ResourcesFor(input) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return o.mapper.RESTMapping(gk, versions...) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return o.mapper.RESTMappings(gk, versions...) | ||||
| } | ||||
|  | ||||
| func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err error) { | ||||
| 	if err := o.init(); err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return o.mapper.ResourceSingularizer(resource) | ||||
| } | ||||
							
								
								
									
										650
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/meta.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										650
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/meta.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,650 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
|  | ||||
| 	"k8s.io/klog" | ||||
|  | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" | ||||
| 	"k8s.io/apimachinery/pkg/conversion" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| ) | ||||
|  | ||||
| // errNotList is returned when an object implements the Object style interfaces but not the List style | ||||
| // interfaces. | ||||
| var errNotList = fmt.Errorf("object does not implement the List interfaces") | ||||
|  | ||||
| var errNotCommon = fmt.Errorf("object does not implement the common interface for accessing the SelfLink") | ||||
|  | ||||
| // CommonAccessor returns a Common interface for the provided object or an error if the object does | ||||
| // not provide List. | ||||
| func CommonAccessor(obj interface{}) (metav1.Common, error) { | ||||
| 	switch t := obj.(type) { | ||||
| 	case List: | ||||
| 		return t, nil | ||||
| 	case metav1.ListInterface: | ||||
| 		return t, nil | ||||
| 	case ListMetaAccessor: | ||||
| 		if m := t.GetListMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotCommon | ||||
| 	case metav1.ListMetaAccessor: | ||||
| 		if m := t.GetListMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotCommon | ||||
| 	case metav1.Object: | ||||
| 		return t, nil | ||||
| 	case metav1.ObjectMetaAccessor: | ||||
| 		if m := t.GetObjectMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotCommon | ||||
| 	default: | ||||
| 		return nil, errNotCommon | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ListAccessor returns a List interface for the provided object or an error if the object does | ||||
| // not provide List. | ||||
| // IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an | ||||
| // object *is* a List. | ||||
| func ListAccessor(obj interface{}) (List, error) { | ||||
| 	switch t := obj.(type) { | ||||
| 	case List: | ||||
| 		return t, nil | ||||
| 	case metav1.ListInterface: | ||||
| 		return t, nil | ||||
| 	case ListMetaAccessor: | ||||
| 		if m := t.GetListMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotList | ||||
| 	case metav1.ListMetaAccessor: | ||||
| 		if m := t.GetListMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotList | ||||
| 	default: | ||||
| 		return nil, errNotList | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // errNotObject is returned when an object implements the List style interfaces but not the Object style | ||||
| // interfaces. | ||||
| var errNotObject = fmt.Errorf("object does not implement the Object interfaces") | ||||
|  | ||||
| // Accessor takes an arbitrary object pointer and returns meta.Interface. | ||||
| // obj must be a pointer to an API type. An error is returned if the minimum | ||||
| // required fields are missing. Fields that are not required return the default | ||||
| // value and are a no-op if set. | ||||
| func Accessor(obj interface{}) (metav1.Object, error) { | ||||
| 	switch t := obj.(type) { | ||||
| 	case metav1.Object: | ||||
| 		return t, nil | ||||
| 	case metav1.ObjectMetaAccessor: | ||||
| 		if m := t.GetObjectMeta(); m != nil { | ||||
| 			return m, nil | ||||
| 		} | ||||
| 		return nil, errNotObject | ||||
| 	default: | ||||
| 		return nil, errNotObject | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // AsPartialObjectMetadata takes the metav1 interface and returns a partial object. | ||||
| // TODO: consider making this solely a conversion action. | ||||
| func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata { | ||||
| 	switch t := m.(type) { | ||||
| 	case *metav1.ObjectMeta: | ||||
| 		return &metav1beta1.PartialObjectMetadata{ObjectMeta: *t} | ||||
| 	default: | ||||
| 		return &metav1beta1.PartialObjectMetadata{ | ||||
| 			ObjectMeta: metav1.ObjectMeta{ | ||||
| 				Name:                       m.GetName(), | ||||
| 				GenerateName:               m.GetGenerateName(), | ||||
| 				Namespace:                  m.GetNamespace(), | ||||
| 				SelfLink:                   m.GetSelfLink(), | ||||
| 				UID:                        m.GetUID(), | ||||
| 				ResourceVersion:            m.GetResourceVersion(), | ||||
| 				Generation:                 m.GetGeneration(), | ||||
| 				CreationTimestamp:          m.GetCreationTimestamp(), | ||||
| 				DeletionTimestamp:          m.GetDeletionTimestamp(), | ||||
| 				DeletionGracePeriodSeconds: m.GetDeletionGracePeriodSeconds(), | ||||
| 				Labels:                     m.GetLabels(), | ||||
| 				Annotations:                m.GetAnnotations(), | ||||
| 				OwnerReferences:            m.GetOwnerReferences(), | ||||
| 				Finalizers:                 m.GetFinalizers(), | ||||
| 				ClusterName:                m.GetClusterName(), | ||||
| 				Initializers:               m.GetInitializers(), | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion | ||||
| // and Kind of an in-memory internal object. | ||||
| // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta | ||||
| // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube | ||||
| // api conventions). | ||||
| func TypeAccessor(obj interface{}) (Type, error) { | ||||
| 	if typed, ok := obj.(runtime.Object); ok { | ||||
| 		return objectAccessor{typed}, nil | ||||
| 	} | ||||
| 	v, err := conversion.EnforcePtr(obj) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	t := v.Type() | ||||
| 	if v.Kind() != reflect.Struct { | ||||
| 		return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface()) | ||||
| 	} | ||||
|  | ||||
| 	typeMeta := v.FieldByName("TypeMeta") | ||||
| 	if !typeMeta.IsValid() { | ||||
| 		return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t) | ||||
| 	} | ||||
| 	a := &genericAccessor{} | ||||
| 	if err := extractFromTypeMeta(typeMeta, a); err != nil { | ||||
| 		return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err) | ||||
| 	} | ||||
| 	return a, nil | ||||
| } | ||||
|  | ||||
| type objectAccessor struct { | ||||
| 	runtime.Object | ||||
| } | ||||
|  | ||||
| func (obj objectAccessor) GetKind() string { | ||||
| 	return obj.GetObjectKind().GroupVersionKind().Kind | ||||
| } | ||||
|  | ||||
| func (obj objectAccessor) SetKind(kind string) { | ||||
| 	gvk := obj.GetObjectKind().GroupVersionKind() | ||||
| 	gvk.Kind = kind | ||||
| 	obj.GetObjectKind().SetGroupVersionKind(gvk) | ||||
| } | ||||
|  | ||||
| func (obj objectAccessor) GetAPIVersion() string { | ||||
| 	return obj.GetObjectKind().GroupVersionKind().GroupVersion().String() | ||||
| } | ||||
|  | ||||
| func (obj objectAccessor) SetAPIVersion(version string) { | ||||
| 	gvk := obj.GetObjectKind().GroupVersionKind() | ||||
| 	gv, err := schema.ParseGroupVersion(version) | ||||
| 	if err != nil { | ||||
| 		gv = schema.GroupVersion{Version: version} | ||||
| 	} | ||||
| 	gvk.Group, gvk.Version = gv.Group, gv.Version | ||||
| 	obj.GetObjectKind().SetGroupVersionKind(gvk) | ||||
| } | ||||
|  | ||||
| // NewAccessor returns a MetadataAccessor that can retrieve | ||||
| // or manipulate resource version on objects derived from core API | ||||
| // metadata concepts. | ||||
| func NewAccessor() MetadataAccessor { | ||||
| 	return resourceAccessor{} | ||||
| } | ||||
|  | ||||
| // resourceAccessor implements ResourceVersioner and SelfLinker. | ||||
| type resourceAccessor struct{} | ||||
|  | ||||
| func (resourceAccessor) Kind(obj runtime.Object) (string, error) { | ||||
| 	return objectAccessor{obj}.GetKind(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetKind(obj runtime.Object, kind string) error { | ||||
| 	objectAccessor{obj}.SetKind(kind) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) { | ||||
| 	return objectAccessor{obj}.GetAPIVersion(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error { | ||||
| 	objectAccessor{obj}.SetAPIVersion(version) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) Namespace(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetNamespace(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetNamespace(namespace) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) Name(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetName(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetName(obj runtime.Object, name string) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetName(name) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetGenerateName(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetGenerateName(name) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetUID(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetUID(uid) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := CommonAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetSelfLink(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error { | ||||
| 	accessor, err := CommonAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetSelfLink(selfLink) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return accessor.GetLabels(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetLabels(labels) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return accessor.GetAnnotations(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error { | ||||
| 	accessor, err := Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetAnnotations(annotations) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := CommonAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetResourceVersion(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error { | ||||
| 	accessor, err := CommonAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetResourceVersion(version) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) Continue(obj runtime.Object) (string, error) { | ||||
| 	accessor, err := ListAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return accessor.GetContinue(), nil | ||||
| } | ||||
|  | ||||
| func (resourceAccessor) SetContinue(obj runtime.Object, version string) error { | ||||
| 	accessor, err := ListAccessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	accessor.SetContinue(version) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object. | ||||
| func extractFromOwnerReference(v reflect.Value, o *metav1.OwnerReference) error { | ||||
| 	if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.Field(v, "Kind", &o.Kind); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.Field(v, "Name", &o.Name); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.Field(v, "UID", &o.UID); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var controllerPtr *bool | ||||
| 	if err := runtime.Field(v, "Controller", &controllerPtr); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if controllerPtr != nil { | ||||
| 		controller := *controllerPtr | ||||
| 		o.Controller = &controller | ||||
| 	} | ||||
| 	var blockOwnerDeletionPtr *bool | ||||
| 	if err := runtime.Field(v, "BlockOwnerDeletion", &blockOwnerDeletionPtr); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if blockOwnerDeletionPtr != nil { | ||||
| 		block := *blockOwnerDeletionPtr | ||||
| 		o.BlockOwnerDeletion = &block | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // setOwnerReference sets v to o. v is the OwnerReferences field of an object. | ||||
| func setOwnerReference(v reflect.Value, o *metav1.OwnerReference) error { | ||||
| 	if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.SetField(o.Kind, v, "Kind"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.SetField(o.Name, v, "Name"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.SetField(o.UID, v, "UID"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if o.Controller != nil { | ||||
| 		controller := *(o.Controller) | ||||
| 		if err := runtime.SetField(&controller, v, "Controller"); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if o.BlockOwnerDeletion != nil { | ||||
| 		block := *(o.BlockOwnerDeletion) | ||||
| 		if err := runtime.SetField(&block, v, "BlockOwnerDeletion"); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // genericAccessor contains pointers to strings that can modify an arbitrary | ||||
| // struct and implements the Accessor interface. | ||||
| type genericAccessor struct { | ||||
| 	namespace         *string | ||||
| 	name              *string | ||||
| 	generateName      *string | ||||
| 	uid               *types.UID | ||||
| 	apiVersion        *string | ||||
| 	kind              *string | ||||
| 	resourceVersion   *string | ||||
| 	selfLink          *string | ||||
| 	creationTimestamp *metav1.Time | ||||
| 	deletionTimestamp **metav1.Time | ||||
| 	labels            *map[string]string | ||||
| 	annotations       *map[string]string | ||||
| 	ownerReferences   reflect.Value | ||||
| 	finalizers        *[]string | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetNamespace() string { | ||||
| 	if a.namespace == nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return *a.namespace | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetNamespace(namespace string) { | ||||
| 	if a.namespace == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	*a.namespace = namespace | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetName() string { | ||||
| 	if a.name == nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return *a.name | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetName(name string) { | ||||
| 	if a.name == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	*a.name = name | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetGenerateName() string { | ||||
| 	if a.generateName == nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return *a.generateName | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetGenerateName(generateName string) { | ||||
| 	if a.generateName == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	*a.generateName = generateName | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetUID() types.UID { | ||||
| 	if a.uid == nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return *a.uid | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetUID(uid types.UID) { | ||||
| 	if a.uid == nil { | ||||
| 		return | ||||
| 	} | ||||
| 	*a.uid = uid | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetAPIVersion() string { | ||||
| 	return *a.apiVersion | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetAPIVersion(version string) { | ||||
| 	*a.apiVersion = version | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetKind() string { | ||||
| 	return *a.kind | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetKind(kind string) { | ||||
| 	*a.kind = kind | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetResourceVersion() string { | ||||
| 	return *a.resourceVersion | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetResourceVersion(version string) { | ||||
| 	*a.resourceVersion = version | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetSelfLink() string { | ||||
| 	return *a.selfLink | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetSelfLink(selfLink string) { | ||||
| 	*a.selfLink = selfLink | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetCreationTimestamp() metav1.Time { | ||||
| 	return *a.creationTimestamp | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetCreationTimestamp(timestamp metav1.Time) { | ||||
| 	*a.creationTimestamp = timestamp | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetDeletionTimestamp() *metav1.Time { | ||||
| 	return *a.deletionTimestamp | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetDeletionTimestamp(timestamp *metav1.Time) { | ||||
| 	*a.deletionTimestamp = timestamp | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetLabels() map[string]string { | ||||
| 	if a.labels == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return *a.labels | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetLabels(labels map[string]string) { | ||||
| 	*a.labels = labels | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetAnnotations() map[string]string { | ||||
| 	if a.annotations == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return *a.annotations | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetAnnotations(annotations map[string]string) { | ||||
| 	if a.annotations == nil { | ||||
| 		emptyAnnotations := make(map[string]string) | ||||
| 		a.annotations = &emptyAnnotations | ||||
| 	} | ||||
| 	*a.annotations = annotations | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetFinalizers() []string { | ||||
| 	if a.finalizers == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return *a.finalizers | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetFinalizers(finalizers []string) { | ||||
| 	*a.finalizers = finalizers | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference { | ||||
| 	var ret []metav1.OwnerReference | ||||
| 	s := a.ownerReferences | ||||
| 	if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice { | ||||
| 		klog.Errorf("expect %v to be a pointer to slice", s) | ||||
| 		return ret | ||||
| 	} | ||||
| 	s = s.Elem() | ||||
| 	// Set the capacity to one element greater to avoid copy if the caller later append an element. | ||||
| 	ret = make([]metav1.OwnerReference, s.Len(), s.Len()+1) | ||||
| 	for i := 0; i < s.Len(); i++ { | ||||
| 		if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil { | ||||
| 			klog.Errorf("extractFromOwnerReference failed: %v", err) | ||||
| 			return ret | ||||
| 		} | ||||
| 	} | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| func (a genericAccessor) SetOwnerReferences(references []metav1.OwnerReference) { | ||||
| 	s := a.ownerReferences | ||||
| 	if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice { | ||||
| 		klog.Errorf("expect %v to be a pointer to slice", s) | ||||
| 	} | ||||
| 	s = s.Elem() | ||||
| 	newReferences := reflect.MakeSlice(s.Type(), len(references), len(references)) | ||||
| 	for i := 0; i < len(references); i++ { | ||||
| 		if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil { | ||||
| 			klog.Errorf("setOwnerReference failed: %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	s.Set(newReferences) | ||||
| } | ||||
|  | ||||
| // extractFromTypeMeta extracts pointers to version and kind fields from an object | ||||
| func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error { | ||||
| 	if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										210
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/multirestmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/multirestmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	utilerrors "k8s.io/apimachinery/pkg/util/errors" | ||||
| ) | ||||
|  | ||||
| // MultiRESTMapper is a wrapper for multiple RESTMappers. | ||||
| type MultiRESTMapper []RESTMapper | ||||
|  | ||||
| func (m MultiRESTMapper) String() string { | ||||
| 	nested := []string{} | ||||
| 	for _, t := range m { | ||||
| 		currString := fmt.Sprintf("%v", t) | ||||
| 		splitStrings := strings.Split(currString, "\n") | ||||
| 		nested = append(nested, strings.Join(splitStrings, "\n\t")) | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t")) | ||||
| } | ||||
|  | ||||
| // ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod) | ||||
| // This implementation supports multiple REST schemas and return the first match. | ||||
| func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { | ||||
| 	for _, t := range m { | ||||
| 		singular, err = t.ResourceSingularizer(resource) | ||||
| 		if err == nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (m MultiRESTMapper) ResourcesFor(resource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { | ||||
| 	allGVRs := []schema.GroupVersionResource{} | ||||
| 	for _, t := range m { | ||||
| 		gvrs, err := t.ResourcesFor(resource) | ||||
| 		// ignore "no match" errors, but any other error percolates back up | ||||
| 		if IsNoMatchError(err) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		// walk the existing values to de-dup | ||||
| 		for _, curr := range gvrs { | ||||
| 			found := false | ||||
| 			for _, existing := range allGVRs { | ||||
| 				if curr == existing { | ||||
| 					found = true | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if !found { | ||||
| 				allGVRs = append(allGVRs, curr) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(allGVRs) == 0 { | ||||
| 		return nil, &NoResourceMatchError{PartialResource: resource} | ||||
| 	} | ||||
|  | ||||
| 	return allGVRs, nil | ||||
| } | ||||
|  | ||||
| func (m MultiRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) { | ||||
| 	allGVKs := []schema.GroupVersionKind{} | ||||
| 	for _, t := range m { | ||||
| 		gvks, err := t.KindsFor(resource) | ||||
| 		// ignore "no match" errors, but any other error percolates back up | ||||
| 		if IsNoMatchError(err) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		// walk the existing values to de-dup | ||||
| 		for _, curr := range gvks { | ||||
| 			found := false | ||||
| 			for _, existing := range allGVKs { | ||||
| 				if curr == existing { | ||||
| 					found = true | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if !found { | ||||
| 				allGVKs = append(allGVKs, curr) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(allGVKs) == 0 { | ||||
| 		return nil, &NoResourceMatchError{PartialResource: resource} | ||||
| 	} | ||||
|  | ||||
| 	return allGVKs, nil | ||||
| } | ||||
|  | ||||
| func (m MultiRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { | ||||
| 	resources, err := m.ResourcesFor(resource) | ||||
| 	if err != nil { | ||||
| 		return schema.GroupVersionResource{}, err | ||||
| 	} | ||||
| 	if len(resources) == 1 { | ||||
| 		return resources[0], nil | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources} | ||||
| } | ||||
|  | ||||
| func (m MultiRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { | ||||
| 	kinds, err := m.KindsFor(resource) | ||||
| 	if err != nil { | ||||
| 		return schema.GroupVersionKind{}, err | ||||
| 	} | ||||
| 	if len(kinds) == 1 { | ||||
| 		return kinds[0], nil | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds} | ||||
| } | ||||
|  | ||||
| // RESTMapping provides the REST mapping for the resource based on the | ||||
| // kind and version. This implementation supports multiple REST schemas and | ||||
| // return the first match. | ||||
| func (m MultiRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { | ||||
| 	allMappings := []*RESTMapping{} | ||||
| 	errors := []error{} | ||||
|  | ||||
| 	for _, t := range m { | ||||
| 		currMapping, err := t.RESTMapping(gk, versions...) | ||||
| 		// ignore "no match" errors, but any other error percolates back up | ||||
| 		if IsNoMatchError(err) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			errors = append(errors, err) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		allMappings = append(allMappings, currMapping) | ||||
| 	} | ||||
|  | ||||
| 	// if we got exactly one mapping, then use it even if other requested failed | ||||
| 	if len(allMappings) == 1 { | ||||
| 		return allMappings[0], nil | ||||
| 	} | ||||
| 	if len(allMappings) > 1 { | ||||
| 		var kinds []schema.GroupVersionKind | ||||
| 		for _, m := range allMappings { | ||||
| 			kinds = append(kinds, m.GroupVersionKind) | ||||
| 		} | ||||
| 		return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds} | ||||
| 	} | ||||
| 	if len(errors) > 0 { | ||||
| 		return nil, utilerrors.NewAggregate(errors) | ||||
| 	} | ||||
| 	return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} | ||||
| } | ||||
|  | ||||
| // RESTMappings returns all possible RESTMappings for the provided group kind, or an error | ||||
| // if the type is not recognized. | ||||
| func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { | ||||
| 	var allMappings []*RESTMapping | ||||
| 	var errors []error | ||||
|  | ||||
| 	for _, t := range m { | ||||
| 		currMappings, err := t.RESTMappings(gk, versions...) | ||||
| 		// ignore "no match" errors, but any other error percolates back up | ||||
| 		if IsNoMatchError(err) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			errors = append(errors, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		allMappings = append(allMappings, currMappings...) | ||||
| 	} | ||||
| 	if len(errors) > 0 { | ||||
| 		return nil, utilerrors.NewAggregate(errors) | ||||
| 	} | ||||
| 	if len(allMappings) == 0 { | ||||
| 		return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} | ||||
| 	} | ||||
| 	return allMappings, nil | ||||
| } | ||||
							
								
								
									
										222
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/priority.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/priority.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| /* | ||||
| Copyright 2016 The Kubernetes Authors. | ||||
|  | ||||
| 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 meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	AnyGroup    = "*" | ||||
| 	AnyVersion  = "*" | ||||
| 	AnyResource = "*" | ||||
| 	AnyKind     = "*" | ||||
| ) | ||||
|  | ||||
| // PriorityRESTMapper is a wrapper for automatically choosing a particular Resource or Kind | ||||
| // when multiple matches are possible | ||||
| type PriorityRESTMapper struct { | ||||
| 	// Delegate is the RESTMapper to use to locate all the Kind and Resource matches | ||||
| 	Delegate RESTMapper | ||||
|  | ||||
| 	// ResourcePriority is a list of priority patterns to apply to matching resources. | ||||
| 	// The list of all matching resources is narrowed based on the patterns until only one remains. | ||||
| 	// A pattern with no matches is skipped.  A pattern with more than one match uses its | ||||
| 	// matches as the list to continue matching against. | ||||
| 	ResourcePriority []schema.GroupVersionResource | ||||
|  | ||||
| 	// KindPriority is a list of priority patterns to apply to matching kinds. | ||||
| 	// The list of all matching kinds is narrowed based on the patterns until only one remains. | ||||
| 	// A pattern with no matches is skipped.  A pattern with more than one match uses its | ||||
| 	// matches as the list to continue matching against. | ||||
| 	KindPriority []schema.GroupVersionKind | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) String() string { | ||||
| 	return fmt.Sprintf("PriorityRESTMapper{\n\t%v\n\t%v\n\t%v\n}", m.ResourcePriority, m.KindPriority, m.Delegate) | ||||
| } | ||||
|  | ||||
| // ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit. | ||||
| func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionResource, error) { | ||||
| 	originalGVRs, originalErr := m.Delegate.ResourcesFor(partiallySpecifiedResource) | ||||
| 	if originalErr != nil && len(originalGVRs) == 0 { | ||||
| 		return schema.GroupVersionResource{}, originalErr | ||||
| 	} | ||||
| 	if len(originalGVRs) == 1 { | ||||
| 		return originalGVRs[0], originalErr | ||||
| 	} | ||||
|  | ||||
| 	remainingGVRs := append([]schema.GroupVersionResource{}, originalGVRs...) | ||||
| 	for _, pattern := range m.ResourcePriority { | ||||
| 		matchedGVRs := []schema.GroupVersionResource{} | ||||
| 		for _, gvr := range remainingGVRs { | ||||
| 			if resourceMatches(pattern, gvr) { | ||||
| 				matchedGVRs = append(matchedGVRs, gvr) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch len(matchedGVRs) { | ||||
| 		case 0: | ||||
| 			// if you have no matches, then nothing matched this pattern just move to the next | ||||
| 			continue | ||||
| 		case 1: | ||||
| 			// one match, return | ||||
| 			return matchedGVRs[0], originalErr | ||||
| 		default: | ||||
| 			// more than one match, use the matched hits as the list moving to the next pattern. | ||||
| 			// this way you can have a series of selection criteria | ||||
| 			remainingGVRs = matchedGVRs | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingResources: originalGVRs} | ||||
| } | ||||
|  | ||||
| // KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit. | ||||
| func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionKind, error) { | ||||
| 	originalGVKs, originalErr := m.Delegate.KindsFor(partiallySpecifiedResource) | ||||
| 	if originalErr != nil && len(originalGVKs) == 0 { | ||||
| 		return schema.GroupVersionKind{}, originalErr | ||||
| 	} | ||||
| 	if len(originalGVKs) == 1 { | ||||
| 		return originalGVKs[0], originalErr | ||||
| 	} | ||||
|  | ||||
| 	remainingGVKs := append([]schema.GroupVersionKind{}, originalGVKs...) | ||||
| 	for _, pattern := range m.KindPriority { | ||||
| 		matchedGVKs := []schema.GroupVersionKind{} | ||||
| 		for _, gvr := range remainingGVKs { | ||||
| 			if kindMatches(pattern, gvr) { | ||||
| 				matchedGVKs = append(matchedGVKs, gvr) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch len(matchedGVKs) { | ||||
| 		case 0: | ||||
| 			// if you have no matches, then nothing matched this pattern just move to the next | ||||
| 			continue | ||||
| 		case 1: | ||||
| 			// one match, return | ||||
| 			return matchedGVKs[0], originalErr | ||||
| 		default: | ||||
| 			// more than one match, use the matched hits as the list moving to the next pattern. | ||||
| 			// this way you can have a series of selection criteria | ||||
| 			remainingGVKs = matchedGVKs | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingKinds: originalGVKs} | ||||
| } | ||||
|  | ||||
| func resourceMatches(pattern schema.GroupVersionResource, resource schema.GroupVersionResource) bool { | ||||
| 	if pattern.Group != AnyGroup && pattern.Group != resource.Group { | ||||
| 		return false | ||||
| 	} | ||||
| 	if pattern.Version != AnyVersion && pattern.Version != resource.Version { | ||||
| 		return false | ||||
| 	} | ||||
| 	if pattern.Resource != AnyResource && pattern.Resource != resource.Resource { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func kindMatches(pattern schema.GroupVersionKind, kind schema.GroupVersionKind) bool { | ||||
| 	if pattern.Group != AnyGroup && pattern.Group != kind.Group { | ||||
| 		return false | ||||
| 	} | ||||
| 	if pattern.Version != AnyVersion && pattern.Version != kind.Version { | ||||
| 		return false | ||||
| 	} | ||||
| 	if pattern.Kind != AnyKind && pattern.Kind != kind.Kind { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) { | ||||
| 	mappings, originalErr := m.Delegate.RESTMappings(gk, versions...) | ||||
| 	if originalErr != nil && len(mappings) == 0 { | ||||
| 		return nil, originalErr | ||||
| 	} | ||||
|  | ||||
| 	// any versions the user provides take priority | ||||
| 	priorities := m.KindPriority | ||||
| 	if len(versions) > 0 { | ||||
| 		priorities = make([]schema.GroupVersionKind, 0, len(m.KindPriority)+len(versions)) | ||||
| 		for _, version := range versions { | ||||
| 			gv := schema.GroupVersion{ | ||||
| 				Version: version, | ||||
| 				Group:   gk.Group, | ||||
| 			} | ||||
| 			priorities = append(priorities, gv.WithKind(AnyKind)) | ||||
| 		} | ||||
| 		priorities = append(priorities, m.KindPriority...) | ||||
| 	} | ||||
|  | ||||
| 	remaining := append([]*RESTMapping{}, mappings...) | ||||
| 	for _, pattern := range priorities { | ||||
| 		var matching []*RESTMapping | ||||
| 		for _, m := range remaining { | ||||
| 			if kindMatches(pattern, m.GroupVersionKind) { | ||||
| 				matching = append(matching, m) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch len(matching) { | ||||
| 		case 0: | ||||
| 			// if you have no matches, then nothing matched this pattern just move to the next | ||||
| 			continue | ||||
| 		case 1: | ||||
| 			// one match, return | ||||
| 			return matching[0], originalErr | ||||
| 		default: | ||||
| 			// more than one match, use the matched hits as the list moving to the next pattern. | ||||
| 			// this way you can have a series of selection criteria | ||||
| 			remaining = matching | ||||
| 		} | ||||
| 	} | ||||
| 	if len(remaining) == 1 { | ||||
| 		return remaining[0], originalErr | ||||
| 	} | ||||
|  | ||||
| 	var kinds []schema.GroupVersionKind | ||||
| 	for _, m := range mappings { | ||||
| 		kinds = append(kinds, m.GroupVersionKind) | ||||
| 	} | ||||
| 	return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds} | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { | ||||
| 	return m.Delegate.RESTMappings(gk, versions...) | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { | ||||
| 	return m.Delegate.ResourceSingularizer(resource) | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) ResourcesFor(partiallySpecifiedResource schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { | ||||
| 	return m.Delegate.ResourcesFor(partiallySpecifiedResource) | ||||
| } | ||||
|  | ||||
| func (m PriorityRESTMapper) KindsFor(partiallySpecifiedResource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) { | ||||
| 	return m.Delegate.KindsFor(partiallySpecifiedResource) | ||||
| } | ||||
							
								
								
									
										518
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										518
									
								
								vendor/k8s.io/apimachinery/pkg/api/meta/restmapper.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,518 @@ | ||||
| /* | ||||
| Copyright 2014 The Kubernetes Authors. | ||||
|  | ||||
| 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. | ||||
| */ | ||||
|  | ||||
| // TODO: move everything in this file to pkg/api/rest | ||||
| package meta | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| // Implements RESTScope interface | ||||
| type restScope struct { | ||||
| 	name RESTScopeName | ||||
| } | ||||
|  | ||||
| func (r *restScope) Name() RESTScopeName { | ||||
| 	return r.name | ||||
| } | ||||
|  | ||||
| var RESTScopeNamespace = &restScope{ | ||||
| 	name: RESTScopeNameNamespace, | ||||
| } | ||||
|  | ||||
| var RESTScopeRoot = &restScope{ | ||||
| 	name: RESTScopeNameRoot, | ||||
| } | ||||
|  | ||||
| // 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. | ||||
| // | ||||
| // The resource name of a Kind is defined as the lowercase, | ||||
| // English-plural version of the Kind string. | ||||
| // When converting from resource to Kind, the singular version of the | ||||
| // resource name is also accepted for convenience. | ||||
| // | ||||
| // TODO: Only accept plural for some operations for increased control? | ||||
| // (`get pod bar` vs `get pods bar`) | ||||
| type DefaultRESTMapper struct { | ||||
| 	defaultGroupVersions []schema.GroupVersion | ||||
|  | ||||
| 	resourceToKind       map[schema.GroupVersionResource]schema.GroupVersionKind | ||||
| 	kindToPluralResource map[schema.GroupVersionKind]schema.GroupVersionResource | ||||
| 	kindToScope          map[schema.GroupVersionKind]RESTScope | ||||
| 	singularToPlural     map[schema.GroupVersionResource]schema.GroupVersionResource | ||||
| 	pluralToSingular     map[schema.GroupVersionResource]schema.GroupVersionResource | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) String() string { | ||||
| 	return fmt.Sprintf("DefaultRESTMapper{kindToPluralResource=%v}", m.kindToPluralResource) | ||||
| } | ||||
|  | ||||
| var _ RESTMapper = &DefaultRESTMapper{} | ||||
|  | ||||
| // NewDefaultRESTMapper initializes a mapping between Kind and APIVersion | ||||
| // to a resource name and back based on the objects in a runtime.Scheme | ||||
| // 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 metadata for a given version. | ||||
| func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion) *DefaultRESTMapper { | ||||
| 	resourceToKind := make(map[schema.GroupVersionResource]schema.GroupVersionKind) | ||||
| 	kindToPluralResource := make(map[schema.GroupVersionKind]schema.GroupVersionResource) | ||||
| 	kindToScope := make(map[schema.GroupVersionKind]RESTScope) | ||||
| 	singularToPlural := make(map[schema.GroupVersionResource]schema.GroupVersionResource) | ||||
| 	pluralToSingular := make(map[schema.GroupVersionResource]schema.GroupVersionResource) | ||||
| 	// TODO: verify name mappings work correctly when versions differ | ||||
|  | ||||
| 	return &DefaultRESTMapper{ | ||||
| 		resourceToKind:       resourceToKind, | ||||
| 		kindToPluralResource: kindToPluralResource, | ||||
| 		kindToScope:          kindToScope, | ||||
| 		defaultGroupVersions: defaultGroupVersions, | ||||
| 		singularToPlural:     singularToPlural, | ||||
| 		pluralToSingular:     pluralToSingular, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) Add(kind schema.GroupVersionKind, scope RESTScope) { | ||||
| 	plural, singular := UnsafeGuessKindToResource(kind) | ||||
| 	m.AddSpecific(kind, plural, singular, scope) | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) AddSpecific(kind schema.GroupVersionKind, plural, singular schema.GroupVersionResource, scope RESTScope) { | ||||
| 	m.singularToPlural[singular] = plural | ||||
| 	m.pluralToSingular[plural] = singular | ||||
|  | ||||
| 	m.resourceToKind[singular] = kind | ||||
| 	m.resourceToKind[plural] = kind | ||||
|  | ||||
| 	m.kindToPluralResource[kind] = plural | ||||
| 	m.kindToScope[kind] = scope | ||||
| } | ||||
|  | ||||
| // unpluralizedSuffixes is a list of resource suffixes that are the same plural and singular | ||||
| // This is only is only necessary because some bits of code are lazy and don't actually use the RESTMapper like they should. | ||||
| // TODO eliminate this so that different callers can correctly map to resources.  This probably means updating all | ||||
| // callers to use the RESTMapper they mean. | ||||
| var unpluralizedSuffixes = []string{ | ||||
| 	"endpoints", | ||||
| } | ||||
|  | ||||
| // UnsafeGuessKindToResource converts Kind to a resource name. | ||||
| // Broken. This method only "sort of" works when used outside of this package.  It assumes that Kinds and Resources match | ||||
| // and they aren't guaranteed to do so. | ||||
| func UnsafeGuessKindToResource(kind schema.GroupVersionKind) ( /*plural*/ schema.GroupVersionResource /*singular*/, schema.GroupVersionResource) { | ||||
| 	kindName := kind.Kind | ||||
| 	if len(kindName) == 0 { | ||||
| 		return schema.GroupVersionResource{}, schema.GroupVersionResource{} | ||||
| 	} | ||||
| 	singularName := strings.ToLower(kindName) | ||||
| 	singular := kind.GroupVersion().WithResource(singularName) | ||||
|  | ||||
| 	for _, skip := range unpluralizedSuffixes { | ||||
| 		if strings.HasSuffix(singularName, skip) { | ||||
| 			return singular, singular | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch string(singularName[len(singularName)-1]) { | ||||
| 	case "s": | ||||
| 		return kind.GroupVersion().WithResource(singularName + "es"), singular | ||||
| 	case "y": | ||||
| 		return kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies"), singular | ||||
| 	} | ||||
|  | ||||
| 	return kind.GroupVersion().WithResource(singularName + "s"), singular | ||||
| } | ||||
|  | ||||
| // ResourceSingularizer implements RESTMapper | ||||
| // It converts a resource name from plural to singular (e.g., from pods to pod) | ||||
| func (m *DefaultRESTMapper) ResourceSingularizer(resourceType string) (string, error) { | ||||
| 	partialResource := schema.GroupVersionResource{Resource: resourceType} | ||||
| 	resources, err := m.ResourcesFor(partialResource) | ||||
| 	if err != nil { | ||||
| 		return resourceType, err | ||||
| 	} | ||||
|  | ||||
| 	singular := schema.GroupVersionResource{} | ||||
| 	for _, curr := range resources { | ||||
| 		currSingular, ok := m.pluralToSingular[curr] | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
| 		if singular.Empty() { | ||||
| 			singular = currSingular | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if currSingular.Resource != singular.Resource { | ||||
| 			return resourceType, fmt.Errorf("multiple possible singular resources (%v) found for %v", resources, resourceType) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if singular.Empty() { | ||||
| 		return resourceType, fmt.Errorf("no singular of resource %v has been defined", resourceType) | ||||
| 	} | ||||
|  | ||||
| 	return singular.Resource, nil | ||||
| } | ||||
|  | ||||
| // coerceResourceForMatching makes the resource lower case and converts internal versions to unspecified (legacy behavior) | ||||
| func coerceResourceForMatching(resource schema.GroupVersionResource) schema.GroupVersionResource { | ||||
| 	resource.Resource = strings.ToLower(resource.Resource) | ||||
| 	if resource.Version == runtime.APIVersionInternal { | ||||
| 		resource.Version = "" | ||||
| 	} | ||||
|  | ||||
| 	return resource | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { | ||||
| 	resource := coerceResourceForMatching(input) | ||||
|  | ||||
| 	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 := []schema.GroupVersionResource{} | ||||
| 	switch { | ||||
| 	case hasGroup && hasVersion: | ||||
| 		// fully qualified.  Find the exact match | ||||
| 		for plural, singular := range m.pluralToSingular { | ||||
| 			if singular == resource { | ||||
| 				ret = append(ret, plural) | ||||
| 				break | ||||
| 			} | ||||
| 			if plural == resource { | ||||
| 				ret = append(ret, plural) | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	case hasGroup: | ||||
| 		// given a group, prefer an exact match.  If you don't find one, resort to a prefix match on group | ||||
| 		foundExactMatch := false | ||||
| 		requestedGroupResource := resource.GroupResource() | ||||
| 		for plural, singular := range m.pluralToSingular { | ||||
| 			if singular.GroupResource() == requestedGroupResource { | ||||
| 				foundExactMatch = true | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 			if plural.GroupResource() == requestedGroupResource { | ||||
| 				foundExactMatch = true | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// if you didn't find an exact match, match on group prefixing. This allows storageclass.storage to match | ||||
| 		// storageclass.storage.k8s.io | ||||
| 		if !foundExactMatch { | ||||
| 			for plural, singular := range m.pluralToSingular { | ||||
| 				if !strings.HasPrefix(plural.Group, requestedGroupResource.Group) { | ||||
| 					continue | ||||
| 				} | ||||
| 				if singular.Resource == requestedGroupResource.Resource { | ||||
| 					ret = append(ret, plural) | ||||
| 				} | ||||
| 				if plural.Resource == requestedGroupResource.Resource { | ||||
| 					ret = append(ret, plural) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 	case hasVersion: | ||||
| 		for plural, singular := range m.pluralToSingular { | ||||
| 			if singular.Version == resource.Version && singular.Resource == resource.Resource { | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 			if plural.Version == resource.Version && plural.Resource == resource.Resource { | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	default: | ||||
| 		for plural, singular := range m.pluralToSingular { | ||||
| 			if singular.Resource == resource.Resource { | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 			if plural.Resource == resource.Resource { | ||||
| 				ret = append(ret, plural) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(ret) == 0 { | ||||
| 		return nil, &NoResourceMatchError{PartialResource: resource} | ||||
| 	} | ||||
|  | ||||
| 	sort.Sort(resourceByPreferredGroupVersion{ret, m.defaultGroupVersions}) | ||||
| 	return ret, nil | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) ResourceFor(resource schema.GroupVersionResource) (schema.GroupVersionResource, error) { | ||||
| 	resources, err := m.ResourcesFor(resource) | ||||
| 	if err != nil { | ||||
| 		return schema.GroupVersionResource{}, err | ||||
| 	} | ||||
| 	if len(resources) == 1 { | ||||
| 		return resources[0], nil | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources} | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) KindsFor(input schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { | ||||
| 	resource := coerceResourceForMatching(input) | ||||
|  | ||||
| 	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 := []schema.GroupVersionKind{} | ||||
| 	switch { | ||||
| 	// fully qualified.  Find the exact match | ||||
| 	case hasGroup && hasVersion: | ||||
| 		kind, exists := m.resourceToKind[resource] | ||||
| 		if exists { | ||||
| 			ret = append(ret, kind) | ||||
| 		} | ||||
|  | ||||
| 	case hasGroup: | ||||
| 		foundExactMatch := false | ||||
| 		requestedGroupResource := resource.GroupResource() | ||||
| 		for currResource, currKind := range m.resourceToKind { | ||||
| 			if currResource.GroupResource() == requestedGroupResource { | ||||
| 				foundExactMatch = true | ||||
| 				ret = append(ret, currKind) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// if you didn't find an exact match, match on group prefixing. This allows storageclass.storage to match | ||||
| 		// storageclass.storage.k8s.io | ||||
| 		if !foundExactMatch { | ||||
| 			for currResource, currKind := range m.resourceToKind { | ||||
| 				if !strings.HasPrefix(currResource.Group, requestedGroupResource.Group) { | ||||
| 					continue | ||||
| 				} | ||||
| 				if currResource.Resource == requestedGroupResource.Resource { | ||||
| 					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, &NoResourceMatchError{PartialResource: input} | ||||
| 	} | ||||
|  | ||||
| 	sort.Sort(kindByPreferredGroupVersion{ret, m.defaultGroupVersions}) | ||||
| 	return ret, nil | ||||
| } | ||||
|  | ||||
| func (m *DefaultRESTMapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { | ||||
| 	kinds, err := m.KindsFor(resource) | ||||
| 	if err != nil { | ||||
| 		return schema.GroupVersionKind{}, err | ||||
| 	} | ||||
| 	if len(kinds) == 1 { | ||||
| 		return kinds[0], nil | ||||
| 	} | ||||
|  | ||||
| 	return schema.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds} | ||||
| } | ||||
|  | ||||
| type kindByPreferredGroupVersion struct { | ||||
| 	list      []schema.GroupVersionKind | ||||
| 	sortOrder []schema.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      []schema.GroupVersionResource | ||||
| 	sortOrder []schema.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 | ||||
| } | ||||
|  | ||||
| // RESTMapping returns a struct representing the resource path and conversion interfaces a | ||||
| // RESTClient should use to operate on the provided group/kind in order of versions. If a version search | ||||
| // order is not provided, the search order provided to DefaultRESTMapper will be used to resolve which | ||||
| // version should be used to access the named group/kind. | ||||
| func (m *DefaultRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*RESTMapping, error) { | ||||
| 	mappings, err := m.RESTMappings(gk, versions...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(mappings) == 0 { | ||||
| 		return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} | ||||
| 	} | ||||
| 	// since we rely on RESTMappings method | ||||
| 	// take the first match and return to the caller | ||||
| 	// as this was the existing behavior. | ||||
| 	return mappings[0], nil | ||||
| } | ||||
|  | ||||
| // RESTMappings returns the RESTMappings for the provided group kind. If a version search order | ||||
| // is not provided, the search order provided to DefaultRESTMapper will be used. | ||||
| func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error) { | ||||
| 	mappings := make([]*RESTMapping, 0) | ||||
| 	potentialGVK := make([]schema.GroupVersionKind, 0) | ||||
| 	hadVersion := false | ||||
|  | ||||
| 	// Pick an appropriate version | ||||
| 	for _, version := range versions { | ||||
| 		if len(version) == 0 || version == runtime.APIVersionInternal { | ||||
| 			continue | ||||
| 		} | ||||
| 		currGVK := gk.WithVersion(version) | ||||
| 		hadVersion = true | ||||
| 		if _, ok := m.kindToPluralResource[currGVK]; ok { | ||||
| 			potentialGVK = append(potentialGVK, currGVK) | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	// Use the default preferred versions | ||||
| 	if !hadVersion && len(potentialGVK) == 0 { | ||||
| 		for _, gv := range m.defaultGroupVersions { | ||||
| 			if gv.Group != gk.Group { | ||||
| 				continue | ||||
| 			} | ||||
| 			potentialGVK = append(potentialGVK, gk.WithVersion(gv.Version)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(potentialGVK) == 0 { | ||||
| 		return nil, &NoKindMatchError{GroupKind: gk, SearchedVersions: versions} | ||||
| 	} | ||||
|  | ||||
| 	for _, gvk := range potentialGVK { | ||||
| 		//Ensure we have a REST mapping | ||||
| 		res, ok := m.kindToPluralResource[gvk] | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Ensure we have a REST scope | ||||
| 		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(), gvk.Kind) | ||||
| 		} | ||||
|  | ||||
| 		mappings = append(mappings, &RESTMapping{ | ||||
| 			Resource:         res, | ||||
| 			GroupVersionKind: gvk, | ||||
| 			Scope:            scope, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	if len(mappings) == 0 { | ||||
| 		return nil, &NoResourceMatchError{PartialResource: schema.GroupVersionResource{Group: gk.Group, Resource: gk.Kind}} | ||||
| 	} | ||||
| 	return mappings, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user