update testclient for delegating reaction chain

pull/6/head
deads2k 2015-08-03 13:30:35 -04:00
parent 5c2c42eed8
commit 7e180c258d
33 changed files with 270 additions and 149 deletions

View File

@ -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))
}

View File

@ -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))
}

View File

@ -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.

View File

@ -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))
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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))
}

View File

@ -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 {

View File

@ -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))
}

View File

@ -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) {

View File

@ -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))
}

View File

@ -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))
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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}
}

View File

@ -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)

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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",

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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,
}

View File

@ -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{

View File

@ -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)