vendor: revendor
This commit is contained in:
		
							
								
								
									
										671
									
								
								vendor/k8s.io/client-go/testing/actions.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										671
									
								
								vendor/k8s.io/client-go/testing/actions.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,671 @@ | ||||
| /* | ||||
| 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 testing | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/fields" | ||||
| 	"k8s.io/apimachinery/pkg/labels" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| ) | ||||
|  | ||||
| func NewRootGetAction(resource schema.GroupVersionResource, name string) GetActionImpl { | ||||
| 	action := GetActionImpl{} | ||||
| 	action.Verb = "get" | ||||
| 	action.Resource = resource | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewGetAction(resource schema.GroupVersionResource, namespace, name string) GetActionImpl { | ||||
| 	action := GetActionImpl{} | ||||
| 	action.Verb = "get" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewGetSubresourceAction(resource schema.GroupVersionResource, namespace, subresource, name string) GetActionImpl { | ||||
| 	action := GetActionImpl{} | ||||
| 	action.Verb = "get" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootGetSubresourceAction(resource schema.GroupVersionResource, subresource, name string) GetActionImpl { | ||||
| 	action := GetActionImpl{} | ||||
| 	action.Verb = "get" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl { | ||||
| 	action := ListActionImpl{} | ||||
| 	action.Verb = "list" | ||||
| 	action.Resource = resource | ||||
| 	action.Kind = kind | ||||
| 	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) | ||||
| 	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl { | ||||
| 	action := ListActionImpl{} | ||||
| 	action.Verb = "list" | ||||
| 	action.Resource = resource | ||||
| 	action.Kind = kind | ||||
| 	action.Namespace = namespace | ||||
| 	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) | ||||
| 	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootCreateAction(resource schema.GroupVersionResource, object runtime.Object) CreateActionImpl { | ||||
| 	action := CreateActionImpl{} | ||||
| 	action.Verb = "create" | ||||
| 	action.Resource = resource | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewCreateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) CreateActionImpl { | ||||
| 	action := CreateActionImpl{} | ||||
| 	action.Verb = "create" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource string, object runtime.Object) CreateActionImpl { | ||||
| 	action := CreateActionImpl{} | ||||
| 	action.Verb = "create" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Name = name | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewCreateSubresourceAction(resource schema.GroupVersionResource, name, subresource, namespace string, object runtime.Object) CreateActionImpl { | ||||
| 	action := CreateActionImpl{} | ||||
| 	action.Verb = "create" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Subresource = subresource | ||||
| 	action.Name = name | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootUpdateAction(resource schema.GroupVersionResource, object runtime.Object) UpdateActionImpl { | ||||
| 	action := UpdateActionImpl{} | ||||
| 	action.Verb = "update" | ||||
| 	action.Resource = resource | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewUpdateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) UpdateActionImpl { | ||||
| 	action := UpdateActionImpl{} | ||||
| 	action.Verb = "update" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootPatchAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte) PatchActionImpl { | ||||
| 	action := PatchActionImpl{} | ||||
| 	action.Verb = "patch" | ||||
| 	action.Resource = resource | ||||
| 	action.Name = name | ||||
| 	action.PatchType = pt | ||||
| 	action.Patch = patch | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, pt types.PatchType, patch []byte) PatchActionImpl { | ||||
| 	action := PatchActionImpl{} | ||||
| 	action.Verb = "patch" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
| 	action.PatchType = pt | ||||
| 	action.Patch = patch | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl { | ||||
| 	action := PatchActionImpl{} | ||||
| 	action.Verb = "patch" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = path.Join(subresources...) | ||||
| 	action.Name = name | ||||
| 	action.PatchType = pt | ||||
| 	action.Patch = patch | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl { | ||||
| 	action := PatchActionImpl{} | ||||
| 	action.Verb = "patch" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = path.Join(subresources...) | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
| 	action.PatchType = pt | ||||
| 	action.Patch = patch | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, object runtime.Object) UpdateActionImpl { | ||||
| 	action := UpdateActionImpl{} | ||||
| 	action.Verb = "update" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
| func NewUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, namespace string, object runtime.Object) UpdateActionImpl { | ||||
| 	action := UpdateActionImpl{} | ||||
| 	action.Verb = "update" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Object = object | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootDeleteAction(resource schema.GroupVersionResource, name string) DeleteActionImpl { | ||||
| 	action := DeleteActionImpl{} | ||||
| 	action.Verb = "delete" | ||||
| 	action.Resource = resource | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl { | ||||
| 	action := DeleteActionImpl{} | ||||
| 	action.Verb = "delete" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl { | ||||
| 	action := DeleteActionImpl{} | ||||
| 	action.Verb = "delete" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl { | ||||
| 	action := DeleteActionImpl{} | ||||
| 	action.Verb = "delete" | ||||
| 	action.Resource = resource | ||||
| 	action.Subresource = subresource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Name = name | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl { | ||||
| 	action := DeleteCollectionActionImpl{} | ||||
| 	action.Verb = "delete-collection" | ||||
| 	action.Resource = resource | ||||
| 	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) | ||||
| 	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewDeleteCollectionAction(resource schema.GroupVersionResource, namespace string, opts interface{}) DeleteCollectionActionImpl { | ||||
| 	action := DeleteCollectionActionImpl{} | ||||
| 	action.Verb = "delete-collection" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts) | ||||
| 	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewRootWatchAction(resource schema.GroupVersionResource, opts interface{}) WatchActionImpl { | ||||
| 	action := WatchActionImpl{} | ||||
| 	action.Verb = "watch" | ||||
| 	action.Resource = resource | ||||
| 	labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts) | ||||
| 	action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func ExtractFromListOptions(opts interface{}) (labelSelector labels.Selector, fieldSelector fields.Selector, resourceVersion string) { | ||||
| 	var err error | ||||
| 	switch t := opts.(type) { | ||||
| 	case metav1.ListOptions: | ||||
| 		labelSelector, err = labels.Parse(t.LabelSelector) | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Errorf("invalid selector %q: %v", t.LabelSelector, err)) | ||||
| 		} | ||||
| 		fieldSelector, err = fields.ParseSelector(t.FieldSelector) | ||||
| 		if err != nil { | ||||
| 			panic(fmt.Errorf("invalid selector %q: %v", t.FieldSelector, err)) | ||||
| 		} | ||||
| 		resourceVersion = t.ResourceVersion | ||||
| 	default: | ||||
| 		panic(fmt.Errorf("expect a ListOptions %T", opts)) | ||||
| 	} | ||||
| 	if labelSelector == nil { | ||||
| 		labelSelector = labels.Everything() | ||||
| 	} | ||||
| 	if fieldSelector == nil { | ||||
| 		fieldSelector = fields.Everything() | ||||
| 	} | ||||
| 	return labelSelector, fieldSelector, resourceVersion | ||||
| } | ||||
|  | ||||
| func NewWatchAction(resource schema.GroupVersionResource, namespace string, opts interface{}) WatchActionImpl { | ||||
| 	action := WatchActionImpl{} | ||||
| 	action.Verb = "watch" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts) | ||||
| 	action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion} | ||||
|  | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| func NewProxyGetAction(resource schema.GroupVersionResource, namespace, scheme, name, port, path string, params map[string]string) ProxyGetActionImpl { | ||||
| 	action := ProxyGetActionImpl{} | ||||
| 	action.Verb = "get" | ||||
| 	action.Resource = resource | ||||
| 	action.Namespace = namespace | ||||
| 	action.Scheme = scheme | ||||
| 	action.Name = name | ||||
| 	action.Port = port | ||||
| 	action.Path = path | ||||
| 	action.Params = params | ||||
| 	return action | ||||
| } | ||||
|  | ||||
| type ListRestrictions struct { | ||||
| 	Labels labels.Selector | ||||
| 	Fields fields.Selector | ||||
| } | ||||
| type WatchRestrictions struct { | ||||
| 	Labels          labels.Selector | ||||
| 	Fields          fields.Selector | ||||
| 	ResourceVersion string | ||||
| } | ||||
|  | ||||
| type Action interface { | ||||
| 	GetNamespace() string | ||||
| 	GetVerb() string | ||||
| 	GetResource() schema.GroupVersionResource | ||||
| 	GetSubresource() string | ||||
| 	Matches(verb, resource string) bool | ||||
|  | ||||
| 	// DeepCopy is used to copy an action to avoid any risk of accidental mutation.  Most people never need to call this | ||||
| 	// because the invocation logic deep copies before calls to storage and reactors. | ||||
| 	DeepCopy() Action | ||||
| } | ||||
|  | ||||
| type GenericAction interface { | ||||
| 	Action | ||||
| 	GetValue() interface{} | ||||
| } | ||||
|  | ||||
| type GetAction interface { | ||||
| 	Action | ||||
| 	GetName() string | ||||
| } | ||||
|  | ||||
| type ListAction interface { | ||||
| 	Action | ||||
| 	GetListRestrictions() ListRestrictions | ||||
| } | ||||
|  | ||||
| type CreateAction interface { | ||||
| 	Action | ||||
| 	GetObject() runtime.Object | ||||
| } | ||||
|  | ||||
| type UpdateAction interface { | ||||
| 	Action | ||||
| 	GetObject() runtime.Object | ||||
| } | ||||
|  | ||||
| type DeleteAction interface { | ||||
| 	Action | ||||
| 	GetName() string | ||||
| } | ||||
|  | ||||
| type DeleteCollectionAction interface { | ||||
| 	Action | ||||
| 	GetListRestrictions() ListRestrictions | ||||
| } | ||||
|  | ||||
| type PatchAction interface { | ||||
| 	Action | ||||
| 	GetName() string | ||||
| 	GetPatchType() types.PatchType | ||||
| 	GetPatch() []byte | ||||
| } | ||||
|  | ||||
| type WatchAction interface { | ||||
| 	Action | ||||
| 	GetWatchRestrictions() WatchRestrictions | ||||
| } | ||||
|  | ||||
| type ProxyGetAction interface { | ||||
| 	Action | ||||
| 	GetScheme() string | ||||
| 	GetName() string | ||||
| 	GetPort() string | ||||
| 	GetPath() string | ||||
| 	GetParams() map[string]string | ||||
| } | ||||
|  | ||||
| type ActionImpl struct { | ||||
| 	Namespace   string | ||||
| 	Verb        string | ||||
| 	Resource    schema.GroupVersionResource | ||||
| 	Subresource string | ||||
| } | ||||
|  | ||||
| func (a ActionImpl) GetNamespace() string { | ||||
| 	return a.Namespace | ||||
| } | ||||
| func (a ActionImpl) GetVerb() string { | ||||
| 	return a.Verb | ||||
| } | ||||
| func (a ActionImpl) GetResource() schema.GroupVersionResource { | ||||
| 	return a.Resource | ||||
| } | ||||
| func (a ActionImpl) GetSubresource() string { | ||||
| 	return a.Subresource | ||||
| } | ||||
| func (a ActionImpl) Matches(verb, resource string) bool { | ||||
| 	return strings.ToLower(verb) == strings.ToLower(a.Verb) && | ||||
| 		strings.ToLower(resource) == strings.ToLower(a.Resource.Resource) | ||||
| } | ||||
| func (a ActionImpl) DeepCopy() Action { | ||||
| 	ret := a | ||||
| 	return ret | ||||
| } | ||||
|  | ||||
| type GenericActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Value interface{} | ||||
| } | ||||
|  | ||||
| func (a GenericActionImpl) GetValue() interface{} { | ||||
| 	return a.Value | ||||
| } | ||||
|  | ||||
| func (a GenericActionImpl) DeepCopy() Action { | ||||
| 	return GenericActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		// TODO this is wrong, but no worse than before | ||||
| 		Value: a.Value, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type GetActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Name string | ||||
| } | ||||
|  | ||||
| func (a GetActionImpl) GetName() string { | ||||
| 	return a.Name | ||||
| } | ||||
|  | ||||
| func (a GetActionImpl) DeepCopy() Action { | ||||
| 	return GetActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Name:       a.Name, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type ListActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Kind             schema.GroupVersionKind | ||||
| 	Name             string | ||||
| 	ListRestrictions ListRestrictions | ||||
| } | ||||
|  | ||||
| func (a ListActionImpl) GetKind() schema.GroupVersionKind { | ||||
| 	return a.Kind | ||||
| } | ||||
|  | ||||
| func (a ListActionImpl) GetListRestrictions() ListRestrictions { | ||||
| 	return a.ListRestrictions | ||||
| } | ||||
|  | ||||
| func (a ListActionImpl) DeepCopy() Action { | ||||
| 	return ListActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Kind:       a.Kind, | ||||
| 		Name:       a.Name, | ||||
| 		ListRestrictions: ListRestrictions{ | ||||
| 			Labels: a.ListRestrictions.Labels.DeepCopySelector(), | ||||
| 			Fields: a.ListRestrictions.Fields.DeepCopySelector(), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type CreateActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Name   string | ||||
| 	Object runtime.Object | ||||
| } | ||||
|  | ||||
| func (a CreateActionImpl) GetObject() runtime.Object { | ||||
| 	return a.Object | ||||
| } | ||||
|  | ||||
| func (a CreateActionImpl) DeepCopy() Action { | ||||
| 	return CreateActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Name:       a.Name, | ||||
| 		Object:     a.Object.DeepCopyObject(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type UpdateActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Object runtime.Object | ||||
| } | ||||
|  | ||||
| func (a UpdateActionImpl) GetObject() runtime.Object { | ||||
| 	return a.Object | ||||
| } | ||||
|  | ||||
| func (a UpdateActionImpl) DeepCopy() Action { | ||||
| 	return UpdateActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Object:     a.Object.DeepCopyObject(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type PatchActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Name      string | ||||
| 	PatchType types.PatchType | ||||
| 	Patch     []byte | ||||
| } | ||||
|  | ||||
| func (a PatchActionImpl) GetName() string { | ||||
| 	return a.Name | ||||
| } | ||||
|  | ||||
| func (a PatchActionImpl) GetPatch() []byte { | ||||
| 	return a.Patch | ||||
| } | ||||
|  | ||||
| func (a PatchActionImpl) GetPatchType() types.PatchType { | ||||
| 	return a.PatchType | ||||
| } | ||||
|  | ||||
| func (a PatchActionImpl) DeepCopy() Action { | ||||
| 	patch := make([]byte, len(a.Patch)) | ||||
| 	copy(patch, a.Patch) | ||||
| 	return PatchActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Name:       a.Name, | ||||
| 		PatchType:  a.PatchType, | ||||
| 		Patch:      patch, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type DeleteActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Name string | ||||
| } | ||||
|  | ||||
| func (a DeleteActionImpl) GetName() string { | ||||
| 	return a.Name | ||||
| } | ||||
|  | ||||
| func (a DeleteActionImpl) DeepCopy() Action { | ||||
| 	return DeleteActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Name:       a.Name, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type DeleteCollectionActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	ListRestrictions ListRestrictions | ||||
| } | ||||
|  | ||||
| func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions { | ||||
| 	return a.ListRestrictions | ||||
| } | ||||
|  | ||||
| func (a DeleteCollectionActionImpl) DeepCopy() Action { | ||||
| 	return DeleteCollectionActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		ListRestrictions: ListRestrictions{ | ||||
| 			Labels: a.ListRestrictions.Labels.DeepCopySelector(), | ||||
| 			Fields: a.ListRestrictions.Fields.DeepCopySelector(), | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type WatchActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	WatchRestrictions WatchRestrictions | ||||
| } | ||||
|  | ||||
| func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions { | ||||
| 	return a.WatchRestrictions | ||||
| } | ||||
|  | ||||
| func (a WatchActionImpl) DeepCopy() Action { | ||||
| 	return WatchActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		WatchRestrictions: WatchRestrictions{ | ||||
| 			Labels:          a.WatchRestrictions.Labels.DeepCopySelector(), | ||||
| 			Fields:          a.WatchRestrictions.Fields.DeepCopySelector(), | ||||
| 			ResourceVersion: a.WatchRestrictions.ResourceVersion, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type ProxyGetActionImpl struct { | ||||
| 	ActionImpl | ||||
| 	Scheme string | ||||
| 	Name   string | ||||
| 	Port   string | ||||
| 	Path   string | ||||
| 	Params map[string]string | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) GetScheme() string { | ||||
| 	return a.Scheme | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) GetName() string { | ||||
| 	return a.Name | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) GetPort() string { | ||||
| 	return a.Port | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) GetPath() string { | ||||
| 	return a.Path | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) GetParams() map[string]string { | ||||
| 	return a.Params | ||||
| } | ||||
|  | ||||
| func (a ProxyGetActionImpl) DeepCopy() Action { | ||||
| 	params := map[string]string{} | ||||
| 	for k, v := range a.Params { | ||||
| 		params[k] = v | ||||
| 	} | ||||
| 	return ProxyGetActionImpl{ | ||||
| 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl), | ||||
| 		Scheme:     a.Scheme, | ||||
| 		Name:       a.Name, | ||||
| 		Port:       a.Port, | ||||
| 		Path:       a.Path, | ||||
| 		Params:     params, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										216
									
								
								vendor/k8s.io/client-go/testing/fake.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								vendor/k8s.io/client-go/testing/fake.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | ||||
| /* | ||||
| 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 testing | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
|  | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/watch" | ||||
| 	restclient "k8s.io/client-go/rest" | ||||
| ) | ||||
|  | ||||
| // Fake implements client.Interface. Meant to be embedded into a struct to get | ||||
| // a default implementation. This makes faking out just the method you want to | ||||
| // test easier. | ||||
| type Fake struct { | ||||
| 	sync.RWMutex | ||||
| 	actions []Action // these may be castable to other types, but "Action" is the minimum | ||||
|  | ||||
| 	// ReactionChain is the list of reactors that will be attempted for every | ||||
| 	// request in the order they are tried. | ||||
| 	ReactionChain []Reactor | ||||
| 	// WatchReactionChain is the list of watch reactors that will be attempted | ||||
| 	// for every request in the order they are tried. | ||||
| 	WatchReactionChain []WatchReactor | ||||
| 	// ProxyReactionChain is the list of proxy reactors that will be attempted | ||||
| 	// for every request in the order they are tried. | ||||
| 	ProxyReactionChain []ProxyReactor | ||||
|  | ||||
| 	Resources []*metav1.APIResourceList | ||||
| } | ||||
|  | ||||
| // Reactor is an interface to allow the composition of reaction functions. | ||||
| type Reactor interface { | ||||
| 	// Handles indicates whether or not this Reactor deals with a given | ||||
| 	// action. | ||||
| 	Handles(action Action) bool | ||||
| 	// React handles the action and returns results.  It may choose to | ||||
| 	// delegate by indicated handled=false. | ||||
| 	React(action Action) (handled bool, ret runtime.Object, err error) | ||||
| } | ||||
|  | ||||
| // WatchReactor is an interface to allow the composition of watch functions. | ||||
| type WatchReactor interface { | ||||
| 	// Handles indicates whether or not this Reactor deals with a given | ||||
| 	// action. | ||||
| 	Handles(action Action) bool | ||||
| 	// React handles a watch action and returns results.  It may choose to | ||||
| 	// delegate by indicating handled=false. | ||||
| 	React(action Action) (handled bool, ret watch.Interface, err error) | ||||
| } | ||||
|  | ||||
| // ProxyReactor is an interface to allow the composition of proxy get | ||||
| // functions. | ||||
| type ProxyReactor interface { | ||||
| 	// Handles indicates whether or not this Reactor deals with a given | ||||
| 	// action. | ||||
| 	Handles(action Action) bool | ||||
| 	// React handles a watch action and returns results.  It may choose to | ||||
| 	// delegate by indicating handled=false. | ||||
| 	React(action Action) (handled bool, ret restclient.ResponseWrapper, err error) | ||||
| } | ||||
|  | ||||
| // ReactionFunc is a function that returns an object or error for a given | ||||
| // Action.  If "handled" is false, then the test client will ignore the | ||||
| // results and continue to the next ReactionFunc.  A ReactionFunc can describe | ||||
| // reactions on subresources by testing the result of the action's | ||||
| // GetSubresource() method. | ||||
| type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error) | ||||
|  | ||||
| // WatchReactionFunc is a function that returns a watch interface.  If | ||||
| // "handled" is false, then the test client will ignore the results and | ||||
| // continue to the next ReactionFunc. | ||||
| type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error) | ||||
|  | ||||
| // ProxyReactionFunc is a function that returns a ResponseWrapper interface | ||||
| // for a given Action.  If "handled" is false, then the test client will | ||||
| // ignore the results and continue to the next ProxyReactionFunc. | ||||
| type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error) | ||||
|  | ||||
| // AddReactor appends a reactor to the end of the chain. | ||||
| func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) { | ||||
| 	c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction}) | ||||
| } | ||||
|  | ||||
| // PrependReactor adds a reactor to the beginning of the chain. | ||||
| func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) { | ||||
| 	c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...) | ||||
| } | ||||
|  | ||||
| // AddWatchReactor appends a reactor to the end of the chain. | ||||
| func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) { | ||||
| 	c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction}) | ||||
| } | ||||
|  | ||||
| // PrependWatchReactor adds a reactor to the beginning of the chain. | ||||
| func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) { | ||||
| 	c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...) | ||||
| } | ||||
|  | ||||
| // AddProxyReactor appends a reactor to the end of the chain. | ||||
| func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) { | ||||
| 	c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction}) | ||||
| } | ||||
|  | ||||
| // PrependProxyReactor adds a reactor to the beginning of the chain. | ||||
| func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) { | ||||
| 	c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...) | ||||
| } | ||||
|  | ||||
| // Invokes records the provided Action and then invokes the ReactionFunc that | ||||
| // handles the action if one exists. defaultReturnObj is expected to be of the | ||||
| // same type a normal call would return. | ||||
| func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	actionCopy := action.DeepCopy() | ||||
| 	c.actions = append(c.actions, action.DeepCopy()) | ||||
| 	for _, reactor := range c.ReactionChain { | ||||
| 		if !reactor.Handles(actionCopy) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		handled, ret, err := reactor.React(actionCopy) | ||||
| 		if !handled { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		return ret, err | ||||
| 	} | ||||
|  | ||||
| 	return defaultReturnObj, nil | ||||
| } | ||||
|  | ||||
| // InvokesWatch records the provided Action and then invokes the ReactionFunc | ||||
| // that handles the action if one exists. | ||||
| func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	actionCopy := action.DeepCopy() | ||||
| 	c.actions = append(c.actions, action.DeepCopy()) | ||||
| 	for _, reactor := range c.WatchReactionChain { | ||||
| 		if !reactor.Handles(actionCopy) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		handled, ret, err := reactor.React(actionCopy) | ||||
| 		if !handled { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		return ret, err | ||||
| 	} | ||||
|  | ||||
| 	return nil, fmt.Errorf("unhandled watch: %#v", action) | ||||
| } | ||||
|  | ||||
| // InvokesProxy records the provided Action and then invokes the ReactionFunc | ||||
| // that handles the action if one exists. | ||||
| func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	actionCopy := action.DeepCopy() | ||||
| 	c.actions = append(c.actions, action.DeepCopy()) | ||||
| 	for _, reactor := range c.ProxyReactionChain { | ||||
| 		if !reactor.Handles(actionCopy) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		handled, ret, err := reactor.React(actionCopy) | ||||
| 		if !handled || err != nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		return ret | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ClearActions clears the history of actions called on the fake client. | ||||
| func (c *Fake) ClearActions() { | ||||
| 	c.Lock() | ||||
| 	defer c.Unlock() | ||||
|  | ||||
| 	c.actions = make([]Action, 0) | ||||
| } | ||||
|  | ||||
| // Actions returns a chronologically ordered slice fake actions called on the | ||||
| // fake client. | ||||
| func (c *Fake) Actions() []Action { | ||||
| 	c.RLock() | ||||
| 	defer c.RUnlock() | ||||
| 	fa := make([]Action, len(c.actions)) | ||||
| 	copy(fa, c.actions) | ||||
| 	return fa | ||||
| } | ||||
							
								
								
									
										557
									
								
								vendor/k8s.io/client-go/testing/fixture.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										557
									
								
								vendor/k8s.io/client-go/testing/fixture.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,557 @@ | ||||
| /* | ||||
| 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 testing | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
|  | ||||
| 	jsonpatch "github.com/evanphx/json-patch" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	"k8s.io/apimachinery/pkg/api/meta" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/apimachinery/pkg/util/json" | ||||
| 	"k8s.io/apimachinery/pkg/util/strategicpatch" | ||||
| 	"k8s.io/apimachinery/pkg/watch" | ||||
| 	restclient "k8s.io/client-go/rest" | ||||
| ) | ||||
|  | ||||
| // ObjectTracker keeps track of objects. It is intended to be used to | ||||
| // fake calls to a server by returning objects based on their kind, | ||||
| // namespace and name. | ||||
| type ObjectTracker interface { | ||||
| 	// Add adds an object to the tracker. If object being added | ||||
| 	// is a list, its items are added separately. | ||||
| 	Add(obj runtime.Object) error | ||||
|  | ||||
| 	// Get retrieves the object by its kind, namespace and name. | ||||
| 	Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error) | ||||
|  | ||||
| 	// Create adds an object to the tracker in the specified namespace. | ||||
| 	Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error | ||||
|  | ||||
| 	// Update updates an existing object in the tracker in the specified namespace. | ||||
| 	Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error | ||||
|  | ||||
| 	// List retrieves all objects of a given kind in the given | ||||
| 	// namespace. Only non-List kinds are accepted. | ||||
| 	List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error) | ||||
|  | ||||
| 	// Delete deletes an existing object from the tracker. If object | ||||
| 	// didn't exist in the tracker prior to deletion, Delete returns | ||||
| 	// no error. | ||||
| 	Delete(gvr schema.GroupVersionResource, ns, name string) error | ||||
|  | ||||
| 	// Watch watches objects from the tracker. Watch returns a channel | ||||
| 	// which will push added / modified / deleted object. | ||||
| 	Watch(gvr schema.GroupVersionResource, ns string) (watch.Interface, error) | ||||
| } | ||||
|  | ||||
| // ObjectScheme abstracts the implementation of common operations on objects. | ||||
| type ObjectScheme interface { | ||||
| 	runtime.ObjectCreater | ||||
| 	runtime.ObjectTyper | ||||
| } | ||||
|  | ||||
| // ObjectReaction returns a ReactionFunc that applies core.Action to | ||||
| // the given tracker. | ||||
| func ObjectReaction(tracker ObjectTracker) ReactionFunc { | ||||
| 	return func(action Action) (bool, runtime.Object, error) { | ||||
| 		ns := action.GetNamespace() | ||||
| 		gvr := action.GetResource() | ||||
| 		// Here and below we need to switch on implementation types, | ||||
| 		// not on interfaces, as some interfaces are identical | ||||
| 		// (e.g. UpdateAction and CreateAction), so if we use them, | ||||
| 		// updates and creates end up matching the same case branch. | ||||
| 		switch action := action.(type) { | ||||
|  | ||||
| 		case ListActionImpl: | ||||
| 			obj, err := tracker.List(gvr, action.GetKind(), ns) | ||||
| 			return true, obj, err | ||||
|  | ||||
| 		case GetActionImpl: | ||||
| 			obj, err := tracker.Get(gvr, ns, action.GetName()) | ||||
| 			return true, obj, err | ||||
|  | ||||
| 		case CreateActionImpl: | ||||
| 			objMeta, err := meta.Accessor(action.GetObject()) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
| 			if action.GetSubresource() == "" { | ||||
| 				err = tracker.Create(gvr, action.GetObject(), ns) | ||||
| 			} else { | ||||
| 				// TODO: Currently we're handling subresource creation as an update | ||||
| 				// on the enclosing resource. This works for some subresources but | ||||
| 				// might not be generic enough. | ||||
| 				err = tracker.Update(gvr, action.GetObject(), ns) | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
| 			obj, err := tracker.Get(gvr, ns, objMeta.GetName()) | ||||
| 			return true, obj, err | ||||
|  | ||||
| 		case UpdateActionImpl: | ||||
| 			objMeta, err := meta.Accessor(action.GetObject()) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
| 			err = tracker.Update(gvr, action.GetObject(), ns) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
| 			obj, err := tracker.Get(gvr, ns, objMeta.GetName()) | ||||
| 			return true, obj, err | ||||
|  | ||||
| 		case DeleteActionImpl: | ||||
| 			err := tracker.Delete(gvr, ns, action.GetName()) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
| 			return true, nil, nil | ||||
|  | ||||
| 		case PatchActionImpl: | ||||
| 			obj, err := tracker.Get(gvr, ns, action.GetName()) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
|  | ||||
| 			old, err := json.Marshal(obj) | ||||
| 			if err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
|  | ||||
| 			switch action.GetPatchType() { | ||||
| 			case types.JSONPatchType: | ||||
| 				patch, err := jsonpatch.DecodePatch(action.GetPatch()) | ||||
| 				if err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 				modified, err := patch.Apply(old) | ||||
| 				if err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 				if err = json.Unmarshal(modified, obj); err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 			case types.MergePatchType: | ||||
| 				modified, err := jsonpatch.MergePatch(old, action.GetPatch()) | ||||
| 				if err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
|  | ||||
| 				if err := json.Unmarshal(modified, obj); err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 			case types.StrategicMergePatchType: | ||||
| 				mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj) | ||||
| 				if err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 				if err = json.Unmarshal(mergedByte, obj); err != nil { | ||||
| 					return true, nil, err | ||||
| 				} | ||||
| 			default: | ||||
| 				return true, nil, fmt.Errorf("PatchType is not supported") | ||||
| 			} | ||||
|  | ||||
| 			if err = tracker.Update(gvr, obj, ns); err != nil { | ||||
| 				return true, nil, err | ||||
| 			} | ||||
|  | ||||
| 			return true, obj, nil | ||||
|  | ||||
| 		default: | ||||
| 			return false, nil, fmt.Errorf("no reaction implemented for %s", action) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type tracker struct { | ||||
| 	scheme  ObjectScheme | ||||
| 	decoder runtime.Decoder | ||||
| 	lock    sync.RWMutex | ||||
| 	objects map[schema.GroupVersionResource][]runtime.Object | ||||
| 	// The value type of watchers is a map of which the key is either a namespace or | ||||
| 	// all/non namespace aka "" and its value is list of fake watchers. | ||||
| 	// Manipulations on resources will broadcast the notification events into the | ||||
| 	// watchers' channel. Note that too many unhandled events (currently 100, | ||||
| 	// see apimachinery/pkg/watch.DefaultChanSize) will cause a panic. | ||||
| 	watchers map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher | ||||
| } | ||||
|  | ||||
| var _ ObjectTracker = &tracker{} | ||||
|  | ||||
| // NewObjectTracker returns an ObjectTracker that can be used to keep track | ||||
| // of objects for the fake clientset. Mostly useful for unit tests. | ||||
| func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracker { | ||||
| 	return &tracker{ | ||||
| 		scheme:   scheme, | ||||
| 		decoder:  decoder, | ||||
| 		objects:  make(map[schema.GroupVersionResource][]runtime.Object), | ||||
| 		watchers: make(map[schema.GroupVersionResource]map[string][]*watch.RaceFreeFakeWatcher), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (t *tracker) List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error) { | ||||
| 	// Heuristic for list kind: original kind + List suffix. Might | ||||
| 	// not always be true but this tracker has a pretty limited | ||||
| 	// understanding of the actual API model. | ||||
| 	listGVK := gvk | ||||
| 	listGVK.Kind = listGVK.Kind + "List" | ||||
| 	// GVK does have the concept of "internal version". The scheme recognizes | ||||
| 	// the runtime.APIVersionInternal, but not the empty string. | ||||
| 	if listGVK.Version == "" { | ||||
| 		listGVK.Version = runtime.APIVersionInternal | ||||
| 	} | ||||
|  | ||||
| 	list, err := t.scheme.New(listGVK) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if !meta.IsListType(list) { | ||||
| 		return nil, fmt.Errorf("%q is not a list type", listGVK.Kind) | ||||
| 	} | ||||
|  | ||||
| 	t.lock.RLock() | ||||
| 	defer t.lock.RUnlock() | ||||
|  | ||||
| 	objs, ok := t.objects[gvr] | ||||
| 	if !ok { | ||||
| 		return list, nil | ||||
| 	} | ||||
|  | ||||
| 	matchingObjs, err := filterByNamespaceAndName(objs, ns, "") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := meta.SetList(list, matchingObjs); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return list.DeepCopyObject(), nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) Watch(gvr schema.GroupVersionResource, ns string) (watch.Interface, error) { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
|  | ||||
| 	fakewatcher := watch.NewRaceFreeFake() | ||||
|  | ||||
| 	if _, exists := t.watchers[gvr]; !exists { | ||||
| 		t.watchers[gvr] = make(map[string][]*watch.RaceFreeFakeWatcher) | ||||
| 	} | ||||
| 	t.watchers[gvr][ns] = append(t.watchers[gvr][ns], fakewatcher) | ||||
| 	return fakewatcher, nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error) { | ||||
| 	errNotFound := errors.NewNotFound(gvr.GroupResource(), name) | ||||
|  | ||||
| 	t.lock.RLock() | ||||
| 	defer t.lock.RUnlock() | ||||
|  | ||||
| 	objs, ok := t.objects[gvr] | ||||
| 	if !ok { | ||||
| 		return nil, errNotFound | ||||
| 	} | ||||
|  | ||||
| 	matchingObjs, err := filterByNamespaceAndName(objs, ns, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(matchingObjs) == 0 { | ||||
| 		return nil, errNotFound | ||||
| 	} | ||||
| 	if len(matchingObjs) > 1 { | ||||
| 		return nil, fmt.Errorf("more than one object matched gvr %s, ns: %q name: %q", gvr, ns, name) | ||||
| 	} | ||||
|  | ||||
| 	// Only one object should match in the tracker if it works | ||||
| 	// correctly, as Add/Update methods enforce kind/namespace/name | ||||
| 	// uniqueness. | ||||
| 	obj := matchingObjs[0].DeepCopyObject() | ||||
| 	if status, ok := obj.(*metav1.Status); ok { | ||||
| 		if status.Status != metav1.StatusSuccess { | ||||
| 			return nil, &errors.StatusError{ErrStatus: *status} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return obj, nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) Add(obj runtime.Object) error { | ||||
| 	if meta.IsListType(obj) { | ||||
| 		return t.addList(obj, false) | ||||
| 	} | ||||
| 	objMeta, err := meta.Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	gvks, _, err := t.scheme.ObjectKinds(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if len(gvks) == 0 { | ||||
| 		return fmt.Errorf("no registered kinds for %v", obj) | ||||
| 	} | ||||
| 	for _, gvk := range gvks { | ||||
| 		// NOTE: UnsafeGuessKindToResource is a heuristic and default match. The | ||||
| 		// actual registration in apiserver can specify arbitrary route for a | ||||
| 		// gvk. If a test uses such objects, it cannot preset the tracker with | ||||
| 		// objects via Add(). Instead, it should trigger the Create() function | ||||
| 		// of the tracker, where an arbitrary gvr can be specified. | ||||
| 		gvr, _ := meta.UnsafeGuessKindToResource(gvk) | ||||
| 		// Resource doesn't have the concept of "__internal" version, just set it to "". | ||||
| 		if gvr.Version == runtime.APIVersionInternal { | ||||
| 			gvr.Version = "" | ||||
| 		} | ||||
|  | ||||
| 		err := t.add(gvr, obj, objMeta.GetNamespace(), false) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error { | ||||
| 	return t.add(gvr, obj, ns, false) | ||||
| } | ||||
|  | ||||
| func (t *tracker) Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error { | ||||
| 	return t.add(gvr, obj, ns, true) | ||||
| } | ||||
|  | ||||
| func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watch.RaceFreeFakeWatcher { | ||||
| 	watches := []*watch.RaceFreeFakeWatcher{} | ||||
| 	if t.watchers[gvr] != nil { | ||||
| 		if w := t.watchers[gvr][ns]; w != nil { | ||||
| 			watches = append(watches, w...) | ||||
| 		} | ||||
| 		if ns != metav1.NamespaceAll { | ||||
| 			if w := t.watchers[gvr][metav1.NamespaceAll]; w != nil { | ||||
| 				watches = append(watches, w...) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return watches | ||||
| } | ||||
|  | ||||
| func (t *tracker) add(gvr schema.GroupVersionResource, obj runtime.Object, ns string, replaceExisting bool) error { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
|  | ||||
| 	gr := gvr.GroupResource() | ||||
|  | ||||
| 	// To avoid the object from being accidentally modified by caller | ||||
| 	// after it's been added to the tracker, we always store the deep | ||||
| 	// copy. | ||||
| 	obj = obj.DeepCopyObject() | ||||
|  | ||||
| 	newMeta, err := meta.Accessor(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Propagate namespace to the new object if hasn't already been set. | ||||
| 	if len(newMeta.GetNamespace()) == 0 { | ||||
| 		newMeta.SetNamespace(ns) | ||||
| 	} | ||||
|  | ||||
| 	if ns != newMeta.GetNamespace() { | ||||
| 		msg := fmt.Sprintf("request namespace does not match object namespace, request: %q object: %q", ns, newMeta.GetNamespace()) | ||||
| 		return errors.NewBadRequest(msg) | ||||
| 	} | ||||
|  | ||||
| 	for i, existingObj := range t.objects[gvr] { | ||||
| 		oldMeta, err := meta.Accessor(existingObj) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if oldMeta.GetNamespace() == newMeta.GetNamespace() && oldMeta.GetName() == newMeta.GetName() { | ||||
| 			if replaceExisting { | ||||
| 				for _, w := range t.getWatches(gvr, ns) { | ||||
| 					w.Modify(obj) | ||||
| 				} | ||||
| 				t.objects[gvr][i] = obj | ||||
| 				return nil | ||||
| 			} | ||||
| 			return errors.NewAlreadyExists(gr, newMeta.GetName()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if replaceExisting { | ||||
| 		// Tried to update but no matching object was found. | ||||
| 		return errors.NewNotFound(gr, newMeta.GetName()) | ||||
| 	} | ||||
|  | ||||
| 	t.objects[gvr] = append(t.objects[gvr], obj) | ||||
|  | ||||
| 	for _, w := range t.getWatches(gvr, ns) { | ||||
| 		w.Add(obj) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) addList(obj runtime.Object, replaceExisting bool) error { | ||||
| 	list, err := meta.ExtractList(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	errs := runtime.DecodeList(list, t.decoder) | ||||
| 	if len(errs) > 0 { | ||||
| 		return errs[0] | ||||
| 	} | ||||
| 	for _, obj := range list { | ||||
| 		if err := t.Add(obj); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *tracker) Delete(gvr schema.GroupVersionResource, ns, name string) error { | ||||
| 	t.lock.Lock() | ||||
| 	defer t.lock.Unlock() | ||||
|  | ||||
| 	found := false | ||||
|  | ||||
| 	for i, existingObj := range t.objects[gvr] { | ||||
| 		objMeta, err := meta.Accessor(existingObj) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if objMeta.GetNamespace() == ns && objMeta.GetName() == name { | ||||
| 			obj := t.objects[gvr][i] | ||||
| 			t.objects[gvr] = append(t.objects[gvr][:i], t.objects[gvr][i+1:]...) | ||||
| 			for _, w := range t.getWatches(gvr, ns) { | ||||
| 				w.Delete(obj) | ||||
| 			} | ||||
| 			found = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if found { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return errors.NewNotFound(gvr.GroupResource(), name) | ||||
| } | ||||
|  | ||||
| // filterByNamespaceAndName returns all objects in the collection that | ||||
| // match provided namespace and name. Empty namespace matches | ||||
| // non-namespaced objects. | ||||
| func filterByNamespaceAndName(objs []runtime.Object, ns, name string) ([]runtime.Object, error) { | ||||
| 	var res []runtime.Object | ||||
|  | ||||
| 	for _, obj := range objs { | ||||
| 		acc, err := meta.Accessor(obj) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if ns != "" && acc.GetNamespace() != ns { | ||||
| 			continue | ||||
| 		} | ||||
| 		if name != "" && acc.GetName() != name { | ||||
| 			continue | ||||
| 		} | ||||
| 		res = append(res, obj) | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
|  | ||||
| func DefaultWatchReactor(watchInterface watch.Interface, err error) WatchReactionFunc { | ||||
| 	return func(action Action) (bool, watch.Interface, error) { | ||||
| 		return true, watchInterface, err | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SimpleReactor is a Reactor.  Each reaction function is attached to a given verb,resource tuple.  "*" in either field matches everything for that value. | ||||
| // For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions | ||||
| type SimpleReactor struct { | ||||
| 	Verb     string | ||||
| 	Resource string | ||||
|  | ||||
| 	Reaction ReactionFunc | ||||
| } | ||||
|  | ||||
| func (r *SimpleReactor) Handles(action Action) bool { | ||||
| 	verbCovers := r.Verb == "*" || r.Verb == action.GetVerb() | ||||
| 	if !verbCovers { | ||||
| 		return false | ||||
| 	} | ||||
| 	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource | ||||
| 	if !resourceCovers { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) { | ||||
| 	return r.Reaction(action) | ||||
| } | ||||
|  | ||||
| // SimpleWatchReactor is a WatchReactor.  Each reaction function is attached to a given resource.  "*" matches everything for that value. | ||||
| // For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions | ||||
| type SimpleWatchReactor struct { | ||||
| 	Resource string | ||||
|  | ||||
| 	Reaction WatchReactionFunc | ||||
| } | ||||
|  | ||||
| func (r *SimpleWatchReactor) Handles(action Action) bool { | ||||
| 	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource | ||||
| 	if !resourceCovers { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) { | ||||
| 	return r.Reaction(action) | ||||
| } | ||||
|  | ||||
| // SimpleProxyReactor is a ProxyReactor.  Each reaction function is attached to a given resource.  "*" matches everything for that value. | ||||
| // For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions. | ||||
| type SimpleProxyReactor struct { | ||||
| 	Resource string | ||||
|  | ||||
| 	Reaction ProxyReactionFunc | ||||
| } | ||||
|  | ||||
| func (r *SimpleProxyReactor) Handles(action Action) bool { | ||||
| 	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource | ||||
| 	if !resourceCovers { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (r *SimpleProxyReactor) React(action Action) (bool, restclient.ResponseWrapper, error) { | ||||
| 	return r.Reaction(action) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user