From 7e180c258dfa1acdaf30ddac9838669247901727 Mon Sep 17 00:00:00 2001 From: deads2k Date: Mon, 3 Aug 2015 13:30:35 -0400 Subject: [PATCH] update testclient for delegating reaction chain --- .../unversioned/testclient/fake_daemons.go | 3 +- .../unversioned/testclient/fake_endpoints.go | 3 +- .../unversioned/testclient/fake_events.go | 3 +- .../testclient/fake_limit_ranges.go | 3 +- .../unversioned/testclient/fake_namespaces.go | 5 +- .../unversioned/testclient/fake_nodes.go | 3 +- .../fake_persistent_volume_claims.go | 3 +- .../testclient/fake_persistent_volumes.go | 3 +- .../testclient/fake_pod_templates.go | 3 +- .../unversioned/testclient/fake_pods.go | 3 +- .../fake_replication_controllers.go | 3 +- .../testclient/fake_resource_quotas.go | 3 +- .../unversioned/testclient/fake_secrets.go | 3 +- .../testclient/fake_service_accounts.go | 3 +- .../unversioned/testclient/fake_services.go | 3 +- pkg/client/unversioned/testclient/fixture.go | 87 +++++++++++-- .../unversioned/testclient/testclient.go | 115 +++++++++++++----- .../unversioned/testclient/testclient_test.go | 6 +- .../namespace/namespace_controller_test.go | 5 +- ...tentvolume_claim_binder_controller_test.go | 12 +- .../replication_controller_test.go | 26 ++-- pkg/kubelet/kubelet_test.go | 45 ++++--- pkg/volume/aws_ebs/aws_ebs_test.go | 3 +- pkg/volume/gce_pd/gce_pd_test.go | 3 +- pkg/volume/glusterfs/glusterfs_test.go | 3 +- pkg/volume/host_path/host_path_test.go | 3 +- pkg/volume/iscsi/iscsi_test.go | 3 +- pkg/volume/nfs/nfs_test.go | 3 +- .../persistent_claim/persistent_claim_test.go | 6 +- pkg/volume/rbd/rbd_test.go | 3 +- .../exec/denyprivileged/admission_test.go | 17 ++- .../namespace/autoprovision/admission_test.go | 5 +- .../namespace/lifecycle/admission_test.go | 27 ++-- 33 files changed, 270 insertions(+), 149 deletions(-) diff --git a/pkg/client/unversioned/testclient/fake_daemons.go b/pkg/client/unversioned/testclient/fake_daemons.go index 05716e0547d..382d62f3922 100644 --- a/pkg/client/unversioned/testclient/fake_daemons.go +++ b/pkg/client/unversioned/testclient/fake_daemons.go @@ -72,6 +72,5 @@ func (c *FakeDaemons) Delete(name string) error { } func (c *FakeDaemons) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("daemons", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewWatchAction("daemons", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_endpoints.go b/pkg/client/unversioned/testclient/fake_endpoints.go index 65b554016b3..1ba9b5d4234 100644 --- a/pkg/client/unversioned/testclient/fake_endpoints.go +++ b/pkg/client/unversioned/testclient/fake_endpoints.go @@ -72,6 +72,5 @@ func (c *FakeEndpoints) Delete(name string) error { } func (c *FakeEndpoints) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("endpoints", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("endpoints", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_events.go b/pkg/client/unversioned/testclient/fake_events.go index 46a1a1d0c3b..23cdc62eb60 100644 --- a/pkg/client/unversioned/testclient/fake_events.go +++ b/pkg/client/unversioned/testclient/fake_events.go @@ -102,8 +102,7 @@ func (c *FakeEvents) Watch(label labels.Selector, field fields.Selector, resourc if c.Namespace != "" { action = NewWatchAction("events", c.Namespace, label, field, resourceVersion) } - c.Fake.Invokes(action, nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(action) } // Search returns a list of events matching the specified object. diff --git a/pkg/client/unversioned/testclient/fake_limit_ranges.go b/pkg/client/unversioned/testclient/fake_limit_ranges.go index 4045daef4da..f7f72feaa33 100644 --- a/pkg/client/unversioned/testclient/fake_limit_ranges.go +++ b/pkg/client/unversioned/testclient/fake_limit_ranges.go @@ -72,6 +72,5 @@ func (c *FakeLimitRanges) Delete(name string) error { } func (c *FakeLimitRanges) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("limitranges", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewWatchAction("limitranges", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_namespaces.go b/pkg/client/unversioned/testclient/fake_namespaces.go index aef0dd34480..638ee7a92df 100644 --- a/pkg/client/unversioned/testclient/fake_namespaces.go +++ b/pkg/client/unversioned/testclient/fake_namespaces.go @@ -53,7 +53,7 @@ func (c *FakeNamespaces) Create(namespace *api.Namespace) (*api.Namespace, error return nil, err } - return obj.(*api.Namespace), c.Fake.Err() + return obj.(*api.Namespace), err } func (c *FakeNamespaces) Update(namespace *api.Namespace) (*api.Namespace, error) { @@ -71,8 +71,7 @@ func (c *FakeNamespaces) Delete(name string) error { } func (c *FakeNamespaces) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewRootWatchAction("namespaces", label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewRootWatchAction("namespaces", label, field, resourceVersion)) } func (c *FakeNamespaces) Finalize(namespace *api.Namespace) (*api.Namespace, error) { diff --git a/pkg/client/unversioned/testclient/fake_nodes.go b/pkg/client/unversioned/testclient/fake_nodes.go index fdbe218ec55..5a1b2de4cbd 100644 --- a/pkg/client/unversioned/testclient/fake_nodes.go +++ b/pkg/client/unversioned/testclient/fake_nodes.go @@ -71,8 +71,7 @@ func (c *FakeNodes) Delete(name string) error { } func (c *FakeNodes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewRootWatchAction("nodes", label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewRootWatchAction("nodes", label, field, resourceVersion)) } func (c *FakeNodes) UpdateStatus(minion *api.Node) (*api.Node, error) { diff --git a/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go b/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go index c97c73539e2..a0ca6526a5d 100644 --- a/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go +++ b/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go @@ -70,8 +70,7 @@ func (c *FakePersistentVolumeClaims) Delete(name string) error { } func (c *FakePersistentVolumeClaims) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("persistentvolumeclaims", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("persistentvolumeclaims", c.Namespace, label, field, resourceVersion)) } func (c *FakePersistentVolumeClaims) UpdateStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { diff --git a/pkg/client/unversioned/testclient/fake_persistent_volumes.go b/pkg/client/unversioned/testclient/fake_persistent_volumes.go index 262fdbbf35f..d26ead23ae6 100644 --- a/pkg/client/unversioned/testclient/fake_persistent_volumes.go +++ b/pkg/client/unversioned/testclient/fake_persistent_volumes.go @@ -69,8 +69,7 @@ func (c *FakePersistentVolumes) Delete(name string) error { } func (c *FakePersistentVolumes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewRootWatchAction("persistentvolumes", label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewRootWatchAction("persistentvolumes", label, field, resourceVersion)) } func (c *FakePersistentVolumes) UpdateStatus(pv *api.PersistentVolume) (*api.PersistentVolume, error) { diff --git a/pkg/client/unversioned/testclient/fake_pod_templates.go b/pkg/client/unversioned/testclient/fake_pod_templates.go index 8c70e37cc35..74cb68261ba 100644 --- a/pkg/client/unversioned/testclient/fake_pod_templates.go +++ b/pkg/client/unversioned/testclient/fake_pod_templates.go @@ -72,6 +72,5 @@ func (c *FakePodTemplates) Delete(name string, options *api.DeleteOptions) error } func (c *FakePodTemplates) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("podtemplates", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("podtemplates", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_pods.go b/pkg/client/unversioned/testclient/fake_pods.go index 7e72e50b81c..e6904a07070 100644 --- a/pkg/client/unversioned/testclient/fake_pods.go +++ b/pkg/client/unversioned/testclient/fake_pods.go @@ -72,8 +72,7 @@ func (c *FakePods) Delete(name string, options *api.DeleteOptions) error { } func (c *FakePods) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("pods", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("pods", c.Namespace, label, field, resourceVersion)) } func (c *FakePods) Bind(binding *api.Binding) error { diff --git a/pkg/client/unversioned/testclient/fake_replication_controllers.go b/pkg/client/unversioned/testclient/fake_replication_controllers.go index b5f365c4d11..34307e3579d 100644 --- a/pkg/client/unversioned/testclient/fake_replication_controllers.go +++ b/pkg/client/unversioned/testclient/fake_replication_controllers.go @@ -72,6 +72,5 @@ func (c *FakeReplicationControllers) Delete(name string) error { } func (c *FakeReplicationControllers) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("replicationcontrollers", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewWatchAction("replicationcontrollers", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_resource_quotas.go b/pkg/client/unversioned/testclient/fake_resource_quotas.go index f1386c714d2..69ea6ca782c 100644 --- a/pkg/client/unversioned/testclient/fake_resource_quotas.go +++ b/pkg/client/unversioned/testclient/fake_resource_quotas.go @@ -72,8 +72,7 @@ func (c *FakeResourceQuotas) Delete(name string) error { } func (c *FakeResourceQuotas) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("resourcequotas", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewWatchAction("resourcequotas", c.Namespace, label, field, resourceVersion)) } func (c *FakeResourceQuotas) UpdateStatus(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { diff --git a/pkg/client/unversioned/testclient/fake_secrets.go b/pkg/client/unversioned/testclient/fake_secrets.go index 73d1c3aba24..7db25bc4011 100644 --- a/pkg/client/unversioned/testclient/fake_secrets.go +++ b/pkg/client/unversioned/testclient/fake_secrets.go @@ -72,6 +72,5 @@ func (c *FakeSecrets) Delete(name string) error { } func (c *FakeSecrets) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("secrets", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("secrets", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_service_accounts.go b/pkg/client/unversioned/testclient/fake_service_accounts.go index 9510c1bdd1b..4dcd20d68d7 100644 --- a/pkg/client/unversioned/testclient/fake_service_accounts.go +++ b/pkg/client/unversioned/testclient/fake_service_accounts.go @@ -72,6 +72,5 @@ func (c *FakeServiceAccounts) Delete(name string) error { } func (c *FakeServiceAccounts) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("serviceaccounts", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, c.Fake.Err() + return c.Fake.InvokesWatch(NewWatchAction("serviceaccounts", c.Namespace, label, field, resourceVersion)) } diff --git a/pkg/client/unversioned/testclient/fake_services.go b/pkg/client/unversioned/testclient/fake_services.go index c9ec705db25..a24b2db5bb7 100644 --- a/pkg/client/unversioned/testclient/fake_services.go +++ b/pkg/client/unversioned/testclient/fake_services.go @@ -73,8 +73,7 @@ func (c *FakeServices) Delete(name string) error { } func (c *FakeServices) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) { - c.Fake.Invokes(NewWatchAction("services", c.Namespace, label, field, resourceVersion), nil) - return c.Fake.Watch, nil + return c.Fake.InvokesWatch(NewWatchAction("services", c.Namespace, label, field, resourceVersion)) } func (c *FakeServices) ProxyGet(name, path string, params map[string]string) unversioned.ResponseWrapper { diff --git a/pkg/client/unversioned/testclient/fixture.go b/pkg/client/unversioned/testclient/fixture.go index a7375da99d1..ce0f750e757 100644 --- a/pkg/client/unversioned/testclient/fixture.go +++ b/pkg/client/unversioned/testclient/fixture.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util/yaml" + "k8s.io/kubernetes/pkg/watch" ) // ObjectRetriever abstracts the implementation for retrieving or setting generic @@ -47,35 +48,48 @@ type ObjectRetriever interface { // ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. // TODO: add support for sub resources func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { - return func(action Action) (runtime.Object, error) { + + return func(action Action) (bool, runtime.Object, error) { _, kind, err := mapper.VersionAndKindForResource(action.GetResource()) if err != nil { - return nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) + return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) } // TODO: have mapper return a Kind for a subresource? switch castAction := action.(type) { case ListAction: - return o.Kind(kind+"List", "") + resource, err := o.Kind(kind+"List", "") + return true, resource, err + case GetAction: - return o.Kind(kind, castAction.GetName()) + resource, err := o.Kind(kind, castAction.GetName()) + return true, resource, err + case DeleteAction: - return o.Kind(kind, castAction.GetName()) + resource, err := o.Kind(kind, castAction.GetName()) + return true, resource, err + case CreateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { - return nil, err + return true, nil, err } - return o.Kind(kind, meta.Name) + resource, err := o.Kind(kind, meta.Name) + return true, resource, err + case UpdateAction: meta, err := api.ObjectMetaFor(castAction.GetObject()) if err != nil { - return nil, err + return true, nil, err } - return o.Kind(kind, meta.Name) + resource, err := o.Kind(kind, meta.Name) + return true, resource, err + default: - return nil, fmt.Errorf("no reaction implemented for %s", action) + return false, nil, fmt.Errorf("no reaction implemented for %s", action) } + + return true, nil, nil } } @@ -213,3 +227,56 @@ func (o objects) Add(obj runtime.Object) error { return 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() + if !resourceCovers { + return false + } + + return true +} + +func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) { + return r.Reaction(action) +} + +// SimpleWatchReactor 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 SimpleWatchReactor struct { + Resource string + + Reaction WatchReactionFunc +} + +func (r *SimpleWatchReactor) Handles(action Action) bool { + resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() + if !resourceCovers { + return false + } + + return true +} + +func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) { + return r.Reaction(action) +} diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index c7dc030eaac..5814fb5cb1e 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -17,6 +17,7 @@ limitations under the License. package testclient import ( + "fmt" "sync" "k8s.io/kubernetes/pkg/api" @@ -36,24 +37,64 @@ func NewSimpleFake(objects ...runtime.Object) *Fake { panic(err) } } - return &Fake{ReactFn: ObjectReaction(o, latest.RESTMapper)} -} -// ReactionFunc is a function that returns an object or error for a given Action -type ReactionFunc func(Action) (runtime.Object, error) + fakeClient := &Fake{} + fakeClient.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) + + return fakeClient +} // 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 - err error - Watch watch.Interface - // ReactFn is an optional function that will be invoked with the provided action - // and return a response. It can implement scenario specific behavior. The type - // of object returned must match the expected type from the caller (even if nil). - ReactFn ReactionFunc + // 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 +} + +// 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 indicated handled=false + React(action Action) (handled bool, ret watch.Interface, 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 continue ignore the results and continue to the next ReactionFunc +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 continue ignore the results and continue to the next ReactionFunc +type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, 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) { + newChain := make([]Reactor, 0, len(c.ReactionChain)+1) + newChain[0] = &SimpleReactor{verb, resource, reaction} + newChain = append(newChain, 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}) } // Invokes records the provided Action and then invokes the ReactFn (if provided). @@ -63,10 +104,42 @@ func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime. defer c.Unlock() c.actions = append(c.actions, action) - if c.ReactFn != nil { - return c.ReactFn(action) + for _, reactor := range c.ReactionChain { + if !reactor.Handles(action) { + continue + } + + handled, ret, err := reactor.React(action) + if !handled { + continue + } + + return ret, err } - return defaultReturnObj, c.err + + return defaultReturnObj, nil +} + +// InvokesWatch records the provided Action and then invokes the ReactFn (if provided). +func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { + c.Lock() + defer c.Unlock() + + c.actions = append(c.actions, action) + for _, reactor := range c.WatchReactionChain { + if !reactor.Handles(action) { + continue + } + + handled, ret, err := reactor.React(action) + if !handled { + continue + } + + return ret, err + } + + return nil, fmt.Errorf("unhandled watch: %#v", action) } // ClearActions clears the history of actions called on the fake client @@ -86,22 +159,6 @@ func (c *Fake) Actions() []Action { return fa } -// SetErr sets the error to return for client calls -func (c *Fake) SetErr(err error) { - c.Lock() - defer c.Unlock() - - c.err = err -} - -// Err returns any a client error or nil -func (c *Fake) Err() error { - c.RLock() - c.RUnlock() - - return c.err -} - func (c *Fake) LimitRanges(namespace string) client.LimitRangeInterface { return &FakeLimitRanges{Fake: c, Namespace: namespace} } diff --git a/pkg/client/unversioned/testclient/testclient_test.go b/pkg/client/unversioned/testclient/testclient_test.go index f814437a221..a8e1f85381d 100644 --- a/pkg/client/unversioned/testclient/testclient_test.go +++ b/pkg/client/unversioned/testclient/testclient_test.go @@ -31,7 +31,8 @@ func TestNewClient(t *testing.T) { if err := AddObjectsFromPath("../../../../examples/guestbook/frontend-service.yaml", o, api.Scheme); err != nil { t.Fatal(err) } - client := &Fake{ReactFn: ObjectReaction(o, latest.RESTMapper)} + client := &Fake{} + client.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) list, err := client.Services("test").List(labels.Everything()) if err != nil { t.Fatal(err) @@ -61,7 +62,8 @@ func TestErrors(t *testing.T) { &(errors.NewForbidden("ServiceList", "", nil).(*errors.StatusError).ErrStatus), }, }) - client := &Fake{ReactFn: ObjectReaction(o, latest.RESTMapper)} + client := &Fake{} + client.AddReactor("*", "*", ObjectReaction(o, latest.RESTMapper)) _, err := client.Services("test").List(labels.Everything()) if !errors.IsNotFound(err) { t.Fatalf("unexpected error: %v", err) diff --git a/pkg/controller/namespace/namespace_controller_test.go b/pkg/controller/namespace/namespace_controller_test.go index 5d3f066fc8e..b98e038c5b3 100644 --- a/pkg/controller/namespace/namespace_controller_test.go +++ b/pkg/controller/namespace/namespace_controller_test.go @@ -134,9 +134,8 @@ func TestSyncNamespaceThatIsActive(t *testing.T) { } func TestRunStop(t *testing.T) { - o := testclient.NewObjects(api.Scheme, api.Scheme) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} - nsController := NewNamespaceController(client, 1*time.Second) + mockClient := &testclient.Fake{} + nsController := NewNamespaceController(mockClient, 1*time.Second) if nsController.StopEverything != nil { t.Errorf("Non-running manager should not have a stop channel. Got %v", nsController.StopEverything) diff --git a/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go b/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go index 2dcb279c84e..3376f54a63e 100644 --- a/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go +++ b/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go @@ -30,8 +30,7 @@ import ( ) func TestRunStop(t *testing.T) { - o := testclient.NewObjects(api.Scheme, api.Scheme) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} binder := NewPersistentVolumeClaimBinder(client, 1*time.Second) if len(binder.stopChannels) != 0 { @@ -118,7 +117,8 @@ func TestExampleObjects(t *testing.T) { t.Fatal(err) } - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, api.RESTMapper)) if reflect.TypeOf(scenario.expected) == reflect.TypeOf(&api.PersistentVolumeClaim{}) { pvc, err := client.PersistentVolumeClaims("ns").Get("doesntmatter") @@ -178,7 +178,8 @@ func TestBindingWithExamples(t *testing.T) { t.Fatal(err) } - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, api.RESTMapper)) pv, err := client.PersistentVolumes().Get("any") pv.Spec.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimRecycle @@ -281,7 +282,8 @@ func TestMissingFromIndex(t *testing.T) { t.Fatal(err) } - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, api.RESTMapper)) pv, err := client.PersistentVolumes().Get("any") if err != nil { diff --git a/pkg/controller/replication/replication_controller_test.go b/pkg/controller/replication/replication_controller_test.go index 456771d8c21..6249071ad03 100644 --- a/pkg/controller/replication/replication_controller_test.go +++ b/pkg/controller/replication/replication_controller_test.go @@ -501,7 +501,8 @@ type FakeWatcher struct { func TestWatchControllers(t *testing.T) { fakeWatch := watch.NewFake() - client := &testclient.Fake{Watch: fakeWatch} + client := &testclient.Fake{} + client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady @@ -543,7 +544,8 @@ func TestWatchControllers(t *testing.T) { func TestWatchPods(t *testing.T) { fakeWatch := watch.NewFake() - client := &testclient.Fake{Watch: fakeWatch} + client := &testclient.Fake{} + client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady @@ -587,7 +589,8 @@ func TestWatchPods(t *testing.T) { func TestUpdatePods(t *testing.T) { fakeWatch := watch.NewFake() - client := &testclient.Fake{Watch: fakeWatch} + client := &testclient.Fake{} + client.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady @@ -681,15 +684,14 @@ func TestControllerUpdateRequeue(t *testing.T) { func TestControllerUpdateStatusWithFailure(t *testing.T) { rc := newReplicationController(1) - fakeClient := &testclient.Fake{ - ReactFn: func(action testclient.Action) (runtime.Object, error) { - if action.GetVerb() == "get" && action.GetResource() == "replicationcontrollers" { - return rc, nil - } - return &api.ReplicationController{}, fmt.Errorf("Fake error") - }, - } - fakeRCClient := &testclient.FakeReplicationControllers{Fake: fakeClient, Namespace: "default"} + fakeClient := &testclient.Fake{} + fakeClient.AddReactor("get", "replicationcontrollers", func(action testclient.Action) (bool, runtime.Object, error) { + return true, rc, nil + }) + fakeClient.AddReactor("*", "*", func(action testclient.Action) (bool, runtime.Object, error) { + return true, &api.ReplicationController{}, fmt.Errorf("Fake error") + }) + fakeRCClient := &testclient.FakeReplicationControllers{fakeClient, "default"} numReplicas := 10 updateReplicaCount(fakeRCClient, *rc, numReplicas) updates, gets := 0, 0 diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 900fbaa5e73..b922a683b4f 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -2333,9 +2333,9 @@ func TestUpdateNewNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet kubeClient := testKubelet.fakeKubeClient - kubeClient.ReactFn = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ + kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ {ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}}, - }}).ReactFn + }}).ReactionChain machineInfo := &cadvisorApi.MachineInfo{ MachineID: "123", SystemUUID: "abc", @@ -2418,7 +2418,7 @@ func TestUpdateExistingNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet kubeClient := testKubelet.fakeKubeClient - kubeClient.ReactFn = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ + kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ { ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}, Spec: api.NodeSpec{}, @@ -2439,7 +2439,7 @@ func TestUpdateExistingNodeStatus(t *testing.T) { }, }, }, - }}).ReactFn + }}).ReactionChain mockCadvisor := testKubelet.fakeCadvisor machineInfo := &cadvisorApi.MachineInfo{ MachineID: "123", @@ -2530,9 +2530,9 @@ func TestUpdateNodeStatusWithoutContainerRuntime(t *testing.T) { // simulates that container runtime is down. fakeRuntime.VersionInfo = "" - kubeClient.ReactFn = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ + kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ {ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}}, - }}).ReactFn + }}).ReactionChain mockCadvisor := testKubelet.fakeCadvisor machineInfo := &cadvisorApi.MachineInfo{ MachineID: "123", @@ -2618,7 +2618,7 @@ func TestUpdateNodeStatusError(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet // No matching node for the kubelet - testKubelet.fakeKubeClient.ReactFn = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{}}).ReactFn + testKubelet.fakeKubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{}}).ReactionChain if err := kubelet.updateNodeStatus(); err == nil { t.Errorf("unexpected non error: %v", err) @@ -3007,23 +3007,22 @@ func TestRegisterExistingNodeWithApiserver(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet kubeClient := testKubelet.fakeKubeClient - kubeClient.ReactFn = func(action testclient.Action) (runtime.Object, error) { - switch action.GetVerb() { - case "create": - // Return an error on create. - return &api.Node{}, &apierrors.StatusError{ - ErrStatus: api.Status{Reason: api.StatusReasonAlreadyExists}, - } - case "get": - // Return an existing (matching) node on get. - return &api.Node{ - ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}, - Spec: api.NodeSpec{ExternalID: testKubeletHostname}, - }, nil - default: - return nil, fmt.Errorf("no reaction implemented for %s", action) + kubeClient.AddReactor("create", "nodes", func(action testclient.Action) (bool, runtime.Object, error) { + // Return an error on create. + return true, &api.Node{}, &apierrors.StatusError{ + ErrStatus: api.Status{Reason: api.StatusReasonAlreadyExists}, } - } + }) + kubeClient.AddReactor("get", "nodes", func(action testclient.Action) (bool, runtime.Object, error) { + // Return an existing (matching) node on get. + return true, &api.Node{ + ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}, + Spec: api.NodeSpec{ExternalID: testKubeletHostname}, + }, nil + }) + kubeClient.AddReactor("*", "*", func(action testclient.Action) (bool, runtime.Object, error) { + return true, nil, fmt.Errorf("no reaction implemented for %s", action) + }) machineInfo := &cadvisorApi.MachineInfo{ MachineID: "123", SystemUUID: "abc", diff --git a/pkg/volume/aws_ebs/aws_ebs_test.go b/pkg/volume/aws_ebs/aws_ebs_test.go index 40430819cf5..f622238f986 100644 --- a/pkg/volume/aws_ebs/aws_ebs_test.go +++ b/pkg/volume/aws_ebs/aws_ebs_test.go @@ -191,7 +191,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/gce_pd/gce_pd_test.go b/pkg/volume/gce_pd/gce_pd_test.go index 9c53d44f0c3..711e1a2ef03 100644 --- a/pkg/volume/gce_pd/gce_pd_test.go +++ b/pkg/volume/gce_pd/gce_pd_test.go @@ -205,7 +205,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/glusterfs/glusterfs_test.go b/pkg/volume/glusterfs/glusterfs_test.go index ec5e6c43a65..95b3fcf75ce 100644 --- a/pkg/volume/glusterfs/glusterfs_test.go +++ b/pkg/volume/glusterfs/glusterfs_test.go @@ -200,7 +200,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o.Add(pv) o.Add(claim) o.Add(ep) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/host_path/host_path_test.go b/pkg/volume/host_path/host_path_test.go index b9a4c200ff3..7a3509f573b 100644 --- a/pkg/volume/host_path/host_path_test.go +++ b/pkg/volume/host_path/host_path_test.go @@ -176,7 +176,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/iscsi/iscsi_test.go b/pkg/volume/iscsi/iscsi_test.go index 309e31c1855..d204a8f6f89 100644 --- a/pkg/volume/iscsi/iscsi_test.go +++ b/pkg/volume/iscsi/iscsi_test.go @@ -234,7 +234,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/nfs/nfs_test.go b/pkg/volume/nfs/nfs_test.go index 4ba60638f6a..0f6f4e265b4 100644 --- a/pkg/volume/nfs/nfs_test.go +++ b/pkg/volume/nfs/nfs_test.go @@ -235,7 +235,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/pkg/volume/persistent_claim/persistent_claim_test.go b/pkg/volume/persistent_claim/persistent_claim_test.go index 1297a2bab21..10e2cd4f2d3 100644 --- a/pkg/volume/persistent_claim/persistent_claim_test.go +++ b/pkg/volume/persistent_claim/persistent_claim_test.go @@ -237,7 +237,8 @@ func TestNewBuilder(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(item.pv) o.Add(item.claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, api.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(testProbeVolumePlugins(), newTestHost(t, client)) @@ -294,7 +295,8 @@ func TestNewBuilderClaimNotBound(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, api.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, api.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(testProbeVolumePlugins(), newTestHost(t, client)) diff --git a/pkg/volume/rbd/rbd_test.go b/pkg/volume/rbd/rbd_test.go index eb6926bc46e..ef78b2f2b9c 100644 --- a/pkg/volume/rbd/rbd_test.go +++ b/pkg/volume/rbd/rbd_test.go @@ -191,7 +191,8 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) { o := testclient.NewObjects(api.Scheme, api.Scheme) o.Add(pv) o.Add(claim) - client := &testclient.Fake{ReactFn: testclient.ObjectReaction(o, latest.RESTMapper)} + client := &testclient.Fake{} + client.AddReactor("*", "*", testclient.ObjectReaction(o, latest.RESTMapper)) plugMgr := volume.VolumePluginMgr{} plugMgr.InitPlugins(ProbeVolumePlugins(), volume.NewFakeVolumeHost("/tmp/fake", client, nil)) diff --git a/plugin/pkg/admission/exec/denyprivileged/admission_test.go b/plugin/pkg/admission/exec/denyprivileged/admission_test.go index c19c1b80f37..22d5b97613d 100644 --- a/plugin/pkg/admission/exec/denyprivileged/admission_test.go +++ b/plugin/pkg/admission/exec/denyprivileged/admission_test.go @@ -36,15 +36,14 @@ func TestAdmissionDeny(t *testing.T) { } func testAdmission(t *testing.T, pod *api.Pod, shouldAccept bool) { - mockClient := &testclient.Fake{ - ReactFn: func(action testclient.Action) (runtime.Object, error) { - if action.Matches("get", "pods") && action.(testclient.GetAction).GetName() == pod.Name { - return pod, nil - } - t.Errorf("Unexpected API call: %#v", action) - return nil, nil - }, - } + mockClient := &testclient.Fake{} + mockClient.AddReactor("get", "pods", func(action testclient.Action) (bool, runtime.Object, error) { + if action.(testclient.GetAction).GetName() == pod.Name { + return true, pod, nil + } + t.Errorf("Unexpected API call: %#v", action) + return true, nil, nil + }) handler := &denyExecOnPrivileged{ client: mockClient, } diff --git a/plugin/pkg/admission/namespace/autoprovision/admission_test.go b/plugin/pkg/admission/namespace/autoprovision/admission_test.go index 5af8a654b2d..a5a53395646 100644 --- a/plugin/pkg/admission/namespace/autoprovision/admission_test.go +++ b/plugin/pkg/admission/namespace/autoprovision/admission_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/client/unversioned/cache" "k8s.io/kubernetes/pkg/client/unversioned/testclient" + "k8s.io/kubernetes/pkg/runtime" ) // TestAdmission verifies a namespace is created on create requests for namespace managed resources @@ -107,7 +108,9 @@ func TestIgnoreAdmission(t *testing.T) { func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) { namespace := "test" mockClient := &testclient.Fake{} - mockClient.SetErr(errors.NewAlreadyExists("namespaces", namespace)) + mockClient.AddReactor("create", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) { + return true, nil, errors.NewAlreadyExists("namespaces", namespace) + }) store := cache.NewStore(cache.MetaNamespaceKeyFunc) handler := &provision{ diff --git a/plugin/pkg/admission/namespace/lifecycle/admission_test.go b/plugin/pkg/admission/namespace/lifecycle/admission_test.go index 470580c8cc2..4f04d940e58 100644 --- a/plugin/pkg/admission/namespace/lifecycle/admission_test.go +++ b/plugin/pkg/admission/namespace/lifecycle/admission_test.go @@ -40,24 +40,21 @@ func TestAdmission(t *testing.T) { }, } - reactFunc := func(action testclient.Action) (runtime.Object, error) { - switch { - case action.Matches("get", "namespaces"): - if getAction, ok := action.(testclient.GetAction); ok && getAction.GetName() == namespaceObj.Name { - return namespaceObj, nil - } - case action.Matches("list", "namespaces"): - return &api.NamespaceList{Items: []api.Namespace{*namespaceObj}}, nil - - } - - return nil, fmt.Errorf("No result for action %v", action) - } - store := cache.NewStore(cache.MetaNamespaceKeyFunc) store.Add(namespaceObj) fakeWatch := watch.NewFake() - mockClient := &testclient.Fake{Watch: fakeWatch, ReactFn: reactFunc} + mockClient := &testclient.Fake{} + mockClient.AddWatchReactor("*", testclient.DefaultWatchReactor(fakeWatch, nil)) + mockClient.AddReactor("get", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) { + if getAction, ok := action.(testclient.GetAction); ok && getAction.GetName() == namespaceObj.Name { + return true, namespaceObj, nil + } + return true, nil, fmt.Errorf("No result for action %v", action) + }) + mockClient.AddReactor("list", "namespaces", func(action testclient.Action) (bool, runtime.Object, error) { + return true, &api.NamespaceList{Items: []api.Namespace{*namespaceObj}}, nil + }) + lfhandler := NewLifecycle(mockClient).(*lifecycle) lfhandler.store = store handler := admission.NewChainHandler(lfhandler)