mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Fix flakiness with kubectl wait tests (#111168)
* Prepend reactor not watch reactor This forces the object to be created first it looks like, avoiding a race condition in testing. Use PrependReactor instead of PrependWatchReactor Decrease test timeouts No need to be this long Revert use of new scheme to reuse same scheme for all tests Allow 1 to 2 actions in stale observed generation failure Allow range of test action lengths Reduce test flakiness Fix TestWaitForJSONPathCondition/handles_watch_condition_change Set delete wait options properly cherry pick original changes back into branch * Revert delete timeout setting change * Remove validateActions functions * Remove go-spew
This commit is contained in:
parent
e16ac34361
commit
dcc54dec19
@ -7,7 +7,6 @@ go 1.18
|
|||||||
require (
|
require (
|
||||||
github.com/MakeNowJust/heredoc v1.0.0
|
github.com/MakeNowJust/heredoc v1.0.0
|
||||||
github.com/chai2010/gettext-go v1.0.2
|
github.com/chai2010/gettext-go v1.0.2
|
||||||
github.com/davecgh/go-spew v1.1.1
|
|
||||||
github.com/daviddengcn/go-colortext v1.0.0
|
github.com/daviddengcn/go-colortext v1.0.0
|
||||||
github.com/docker/distribution v2.8.1+incompatible
|
github.com/docker/distribution v2.8.1+incompatible
|
||||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||||
@ -50,6 +49,7 @@ require (
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||||
github.com/go-errors/errors v1.0.1 // indirect
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
github.com/go-logr/logr v1.2.3 // indirect
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
|
@ -40,11 +40,13 @@ import (
|
|||||||
"k8s.io/cli-runtime/pkg/printers"
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
watchtools "k8s.io/client-go/tools/watch"
|
watchtools "k8s.io/client-go/tools/watch"
|
||||||
"k8s.io/client-go/util/jsonpath"
|
"k8s.io/client-go/util/jsonpath"
|
||||||
cmdget "k8s.io/kubectl/pkg/cmd/get"
|
cmdget "k8s.io/kubectl/pkg/cmd/get"
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
|
"k8s.io/kubectl/pkg/util/interrupt"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -317,70 +319,86 @@ func (o *WaitOptions) RunWait() error {
|
|||||||
|
|
||||||
// IsDeleted is a condition func for waiting for something to be deleted
|
// IsDeleted is a condition func for waiting for something to be deleted
|
||||||
func IsDeleted(info *resource.Info, o *WaitOptions) (runtime.Object, bool, error) {
|
func IsDeleted(info *resource.Info, o *WaitOptions) (runtime.Object, bool, error) {
|
||||||
endTime := time.Now().Add(o.Timeout)
|
if len(info.Name) == 0 {
|
||||||
for {
|
return info.Object, false, fmt.Errorf("resource name must be provided")
|
||||||
if len(info.Name) == 0 {
|
}
|
||||||
return info.Object, false, fmt.Errorf("resource name must be provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
nameSelector := fields.OneTermEqualSelector("metadata.name", info.Name).String()
|
gottenObj, initObjGetErr := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Get(context.Background(), info.Name, metav1.GetOptions{})
|
||||||
|
if apierrors.IsNotFound(initObjGetErr) {
|
||||||
// List with a name field selector to get the current resourceVersion to watch from (not the object's resourceVersion)
|
return info.Object, true, nil
|
||||||
gottenObjList, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: nameSelector})
|
}
|
||||||
if apierrors.IsNotFound(err) {
|
if initObjGetErr != nil {
|
||||||
return info.Object, true, nil
|
// TODO this could do something slightly fancier if we wish
|
||||||
}
|
return info.Object, false, initObjGetErr
|
||||||
if err != nil {
|
}
|
||||||
// TODO this could do something slightly fancier if we wish
|
resourceLocation := ResourceLocation{
|
||||||
return info.Object, false, err
|
GroupResource: info.Mapping.Resource.GroupResource(),
|
||||||
}
|
Namespace: gottenObj.GetNamespace(),
|
||||||
if len(gottenObjList.Items) != 1 {
|
Name: gottenObj.GetName(),
|
||||||
return info.Object, true, nil
|
}
|
||||||
}
|
if uid, ok := o.UIDMap[resourceLocation]; ok {
|
||||||
gottenObj := &gottenObjList.Items[0]
|
if gottenObj.GetUID() != uid {
|
||||||
resourceLocation := ResourceLocation{
|
return gottenObj, true, nil
|
||||||
GroupResource: info.Mapping.Resource.GroupResource(),
|
|
||||||
Namespace: gottenObj.GetNamespace(),
|
|
||||||
Name: gottenObj.GetName(),
|
|
||||||
}
|
|
||||||
if uid, ok := o.UIDMap[resourceLocation]; ok {
|
|
||||||
if gottenObj.GetUID() != uid {
|
|
||||||
return gottenObj, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchOptions := metav1.ListOptions{}
|
|
||||||
watchOptions.FieldSelector = nameSelector
|
|
||||||
watchOptions.ResourceVersion = gottenObjList.GetResourceVersion()
|
|
||||||
objWatch, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(context.TODO(), watchOptions)
|
|
||||||
if err != nil {
|
|
||||||
return gottenObj, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout := endTime.Sub(time.Now())
|
|
||||||
errWaitTimeoutWithName := extendErrWaitTimeout(wait.ErrWaitTimeout, info)
|
|
||||||
if timeout < 0 {
|
|
||||||
// we're out of time
|
|
||||||
return gottenObj, false, errWaitTimeoutWithName
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), o.Timeout)
|
|
||||||
watchEvent, err := watchtools.UntilWithoutRetry(ctx, objWatch, Wait{errOut: o.ErrOut}.IsDeleted)
|
|
||||||
cancel()
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
return watchEvent.Object, true, nil
|
|
||||||
case err == watchtools.ErrWatchClosed:
|
|
||||||
continue
|
|
||||||
case err == wait.ErrWaitTimeout:
|
|
||||||
if watchEvent != nil {
|
|
||||||
return watchEvent.Object, false, errWaitTimeoutWithName
|
|
||||||
}
|
|
||||||
return gottenObj, false, errWaitTimeoutWithName
|
|
||||||
default:
|
|
||||||
return gottenObj, false, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endTime := time.Now().Add(o.Timeout)
|
||||||
|
timeout := time.Until(endTime)
|
||||||
|
errWaitTimeoutWithName := extendErrWaitTimeout(wait.ErrWaitTimeout, info)
|
||||||
|
if o.Timeout == 0 {
|
||||||
|
// If timeout is zero check if the object exists once only
|
||||||
|
if gottenObj == nil {
|
||||||
|
return nil, true, nil
|
||||||
|
}
|
||||||
|
return gottenObj, false, fmt.Errorf("condition not met for %s", info.ObjectName())
|
||||||
|
}
|
||||||
|
if timeout < 0 {
|
||||||
|
// we're out of time
|
||||||
|
return info.Object, false, errWaitTimeoutWithName
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), o.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
fieldSelector := fields.OneTermEqualSelector("metadata.name", info.Name).String()
|
||||||
|
lw := &cache.ListWatch{
|
||||||
|
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||||
|
options.FieldSelector = fieldSelector
|
||||||
|
return o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).List(context.TODO(), options)
|
||||||
|
},
|
||||||
|
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
options.FieldSelector = fieldSelector
|
||||||
|
return o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(context.TODO(), options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function is used to refresh the cache to prevent timeout waits on resources that have disappeared
|
||||||
|
preconditionFunc := func(store cache.Store) (bool, error) {
|
||||||
|
_, exists, err := store.Get(&metav1.ObjectMeta{Namespace: info.Namespace, Name: info.Name})
|
||||||
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
// since we're looking for it to disappear we just return here if it no longer exists
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
intr := interrupt.New(nil, cancel)
|
||||||
|
err := intr.Run(func() error {
|
||||||
|
_, err := watchtools.UntilWithSync(ctx, lw, &unstructured.Unstructured{}, preconditionFunc, Wait{errOut: o.ErrOut}.IsDeleted)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if err == wait.ErrWaitTimeout {
|
||||||
|
return gottenObj, false, errWaitTimeoutWithName
|
||||||
|
}
|
||||||
|
return gottenObj, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gottenObj, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait has helper methods for handling watches, including error handling.
|
// Wait has helper methods for handling watches, including error handling.
|
||||||
@ -410,68 +428,85 @@ type checkCondFunc func(obj *unstructured.Unstructured) (bool, error)
|
|||||||
// getObjAndCheckCondition will make a List query to the API server to get the object and check if the condition is met using check function.
|
// getObjAndCheckCondition will make a List query to the API server to get the object and check if the condition is met using check function.
|
||||||
// If the condition is not met, it will make a Watch query to the server and pass in the condMet function
|
// If the condition is not met, it will make a Watch query to the server and pass in the condMet function
|
||||||
func getObjAndCheckCondition(info *resource.Info, o *WaitOptions, condMet isCondMetFunc, check checkCondFunc) (runtime.Object, bool, error) {
|
func getObjAndCheckCondition(info *resource.Info, o *WaitOptions, condMet isCondMetFunc, check checkCondFunc) (runtime.Object, bool, error) {
|
||||||
|
if len(info.Name) == 0 {
|
||||||
|
return info.Object, false, fmt.Errorf("resource name must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
endTime := time.Now().Add(o.Timeout)
|
endTime := time.Now().Add(o.Timeout)
|
||||||
for {
|
timeout := time.Until(endTime)
|
||||||
if len(info.Name) == 0 {
|
errWaitTimeoutWithName := extendErrWaitTimeout(wait.ErrWaitTimeout, info)
|
||||||
return info.Object, false, fmt.Errorf("resource name must be provided")
|
if o.Timeout == 0 {
|
||||||
|
// If timeout is zero we will fetch the object(s) once only and check
|
||||||
|
gottenObj, initObjGetErr := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Get(context.Background(), info.Name, metav1.GetOptions{})
|
||||||
|
if initObjGetErr != nil {
|
||||||
|
return nil, false, initObjGetErr
|
||||||
}
|
}
|
||||||
|
if gottenObj == nil {
|
||||||
nameSelector := fields.OneTermEqualSelector("metadata.name", info.Name).String()
|
return nil, false, fmt.Errorf("condition not met for %s", info.ObjectName())
|
||||||
|
|
||||||
var gottenObj *unstructured.Unstructured
|
|
||||||
// List with a name field selector to get the current resourceVersion to watch from (not the object's resourceVersion)
|
|
||||||
gottenObjList, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: nameSelector})
|
|
||||||
|
|
||||||
resourceVersion := ""
|
|
||||||
switch {
|
|
||||||
case err != nil:
|
|
||||||
return info.Object, false, err
|
|
||||||
case len(gottenObjList.Items) != 1:
|
|
||||||
resourceVersion = gottenObjList.GetResourceVersion()
|
|
||||||
default:
|
|
||||||
gottenObj = &gottenObjList.Items[0]
|
|
||||||
conditionMet, err := check(gottenObj)
|
|
||||||
if conditionMet {
|
|
||||||
return gottenObj, true, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return gottenObj, false, err
|
|
||||||
}
|
|
||||||
resourceVersion = gottenObjList.GetResourceVersion()
|
|
||||||
}
|
}
|
||||||
|
conditionCheck, err := check(gottenObj)
|
||||||
watchOptions := metav1.ListOptions{}
|
|
||||||
watchOptions.FieldSelector = nameSelector
|
|
||||||
watchOptions.ResourceVersion = resourceVersion
|
|
||||||
objWatch, err := o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(context.TODO(), watchOptions)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gottenObj, false, err
|
return gottenObj, false, err
|
||||||
}
|
}
|
||||||
|
if conditionCheck == false {
|
||||||
timeout := endTime.Sub(time.Now())
|
return gottenObj, false, fmt.Errorf("condition not met for %s", info.ObjectName())
|
||||||
errWaitTimeoutWithName := extendErrWaitTimeout(wait.ErrWaitTimeout, info)
|
|
||||||
if timeout < 0 {
|
|
||||||
// we're out of time
|
|
||||||
return gottenObj, false, errWaitTimeoutWithName
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), o.Timeout)
|
|
||||||
watchEvent, err := watchtools.UntilWithoutRetry(ctx, objWatch, watchtools.ConditionFunc(condMet))
|
|
||||||
cancel()
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
return watchEvent.Object, true, nil
|
|
||||||
case err == watchtools.ErrWatchClosed:
|
|
||||||
continue
|
|
||||||
case err == wait.ErrWaitTimeout:
|
|
||||||
if watchEvent != nil {
|
|
||||||
return watchEvent.Object, false, errWaitTimeoutWithName
|
|
||||||
}
|
|
||||||
return gottenObj, false, errWaitTimeoutWithName
|
|
||||||
default:
|
|
||||||
return gottenObj, false, err
|
|
||||||
}
|
}
|
||||||
|
return gottenObj, true, nil
|
||||||
}
|
}
|
||||||
|
if timeout < 0 {
|
||||||
|
// we're out of time
|
||||||
|
return info.Object, false, errWaitTimeoutWithName
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), o.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
mapping := info.ResourceMapping() // used to pass back meaningful errors if object disappears
|
||||||
|
fieldSelector := fields.OneTermEqualSelector("metadata.name", info.Name).String()
|
||||||
|
lw := &cache.ListWatch{
|
||||||
|
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||||
|
options.FieldSelector = fieldSelector
|
||||||
|
return o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).List(context.TODO(), options)
|
||||||
|
},
|
||||||
|
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||||
|
options.FieldSelector = fieldSelector
|
||||||
|
return o.DynamicClient.Resource(info.Mapping.Resource).Namespace(info.Namespace).Watch(context.TODO(), options)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function is used to refresh the cache to prevent timeout waits on resources that have disappeared
|
||||||
|
preconditionFunc := func(store cache.Store) (bool, error) {
|
||||||
|
_, exists, err := store.Get(&metav1.ObjectMeta{Namespace: info.Namespace, Name: info.Name})
|
||||||
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return true, apierrors.NewNotFound(mapping.Resource.GroupResource(), info.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result runtime.Object
|
||||||
|
intr := interrupt.New(nil, cancel)
|
||||||
|
err := intr.Run(func() error {
|
||||||
|
ev, err := watchtools.UntilWithSync(ctx, lw, &unstructured.Unstructured{}, preconditionFunc, watchtools.ConditionFunc(condMet))
|
||||||
|
if ev != nil {
|
||||||
|
result = ev.Object
|
||||||
|
}
|
||||||
|
if err == context.DeadlineExceeded {
|
||||||
|
return errWaitTimeoutWithName
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if err == wait.ErrWaitTimeout {
|
||||||
|
return result, false, errWaitTimeoutWithName
|
||||||
|
}
|
||||||
|
return result, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConditionalWait hold information to check an API status condition
|
// ConditionalWait hold information to check an API status condition
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
@ -253,8 +252,7 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
uidMap UIDMap
|
uidMap UIDMap
|
||||||
|
|
||||||
expectedErr string
|
expectedErr string
|
||||||
validateActions func(t *testing.T, actions []clienttesting.Action)
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "missing on get",
|
name: "missing on get",
|
||||||
@ -271,15 +269,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
return dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
return dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 1 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles no infos",
|
name: "handles no infos",
|
||||||
@ -289,12 +278,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
expectedErr: errNoMatchingResources.Error(),
|
expectedErr: errNoMatchingResources.Error(),
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 0 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "uid conflict on get",
|
name: "uid conflict on get",
|
||||||
@ -318,7 +301,7 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
count++
|
count++
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
fakeWatch := watch.NewRaceFreeFake()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(1 * time.Second)
|
||||||
fakeWatch.Stop()
|
fakeWatch.Stop()
|
||||||
}()
|
}()
|
||||||
return true, fakeWatch, nil
|
return true, fakeWatch, nil
|
||||||
@ -333,15 +316,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
ResourceLocation{Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-UID-value"),
|
ResourceLocation{Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-UID-value"),
|
||||||
ResourceLocation{GroupResource: schema.GroupResource{Group: "group", Resource: "theresource"}, Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-nonmatching-UID-value"),
|
ResourceLocation{GroupResource: schema.GroupResource{Group: "group", Resource: "theresource"}, Namespace: "ns-foo", Name: "name-foo"}: types.UID("some-nonmatching-UID-value"),
|
||||||
},
|
},
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 1 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "times out",
|
name: "times out",
|
||||||
@ -356,6 +330,9 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
})
|
})
|
||||||
@ -364,17 +341,56 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
timeout: 1 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
},
|
||||||
if len(actions) != 2 {
|
{
|
||||||
t.Fatal(spew.Sdump(actions))
|
name: "delete for existing resource with no timeout",
|
||||||
}
|
infos: []*resource.Info{
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
{
|
||||||
t.Error(spew.Sdump(actions))
|
Mapping: &meta.RESTMapping{
|
||||||
}
|
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"},
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
},
|
||||||
t.Error(spew.Sdump(actions))
|
Name: "name-foo",
|
||||||
}
|
Namespace: "ns-foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
return fakeClient
|
||||||
|
},
|
||||||
|
timeout: 0 * time.Second,
|
||||||
|
|
||||||
|
expectedErr: "condition not met for theresource/name-foo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete for nonexisting resource with no timeout",
|
||||||
|
infos: []*resource.Info{
|
||||||
|
{
|
||||||
|
Mapping: &meta.RESTMapping{
|
||||||
|
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thenonexistentresource"},
|
||||||
|
},
|
||||||
|
Name: "name-foo",
|
||||||
|
Namespace: "ns-foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
return fakeClient
|
||||||
|
},
|
||||||
|
timeout: 0 * time.Second,
|
||||||
|
|
||||||
|
expectedErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch close out",
|
name: "handles watch close out",
|
||||||
@ -389,6 +405,13 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
unstructuredObj := newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")
|
||||||
|
unstructuredObj.SetResourceVersion("123")
|
||||||
|
unstructuredList := newUnstructuredList(unstructuredObj)
|
||||||
|
unstructuredList.SetResourceVersion("234")
|
||||||
|
return true, unstructuredList, nil
|
||||||
|
})
|
||||||
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
unstructuredObj := newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")
|
unstructuredObj := newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")
|
||||||
unstructuredObj.SetResourceVersion("123")
|
unstructuredObj.SetResourceVersion("123")
|
||||||
@ -402,7 +425,7 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
count++
|
count++
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
fakeWatch := watch.NewRaceFreeFake()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(1 * time.Second)
|
||||||
fakeWatch.Stop()
|
fakeWatch.Stop()
|
||||||
}()
|
}()
|
||||||
return true, fakeWatch, nil
|
return true, fakeWatch, nil
|
||||||
@ -415,23 +438,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
timeout: 3 * time.Second,
|
timeout: 3 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") || actions[1].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") || actions[3].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch delete",
|
name: "handles watch delete",
|
||||||
@ -457,18 +463,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch delete multiple",
|
name: "handles watch delete multiple",
|
||||||
@ -509,18 +503,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource-1") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("list", "theresource-2") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ignores watch error",
|
name: "ignores watch error",
|
||||||
@ -558,24 +540,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,8 +568,6 @@ func TestWaitForDeletion(t *testing.T) {
|
|||||||
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test.validateActions(t, fakeClient.Actions())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -622,8 +584,7 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
fakeClient func() *dynamicfakeclient.FakeDynamicClient
|
fakeClient func() *dynamicfakeclient.FakeDynamicClient
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
|
|
||||||
expectedErr string
|
expectedErr string
|
||||||
validateActions func(t *testing.T, actions []clienttesting.Action)
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "present on get",
|
name: "present on get",
|
||||||
@ -647,15 +608,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 1 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles no infos",
|
name: "handles no infos",
|
||||||
@ -665,12 +617,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
expectedErr: errNoMatchingResources.Error(),
|
expectedErr: errNoMatchingResources.Error(),
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 0 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles empty object name",
|
name: "handles empty object name",
|
||||||
@ -687,12 +633,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
expectedErr: "resource name must be provided",
|
expectedErr: "resource name must be provided",
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 0 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "times out",
|
name: "times out",
|
||||||
@ -717,18 +657,57 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 1 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: `theresource.group "name-foo" not found`,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
},
|
||||||
if len(actions) != 2 {
|
{
|
||||||
t.Fatal(spew.Sdump(actions))
|
name: "for nonexisting resource with no timeout",
|
||||||
}
|
infos: []*resource.Info{
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
{
|
||||||
t.Error(spew.Sdump(actions))
|
Mapping: &meta.RESTMapping{
|
||||||
}
|
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thenonexistingresource"},
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
},
|
||||||
t.Error(spew.Sdump(actions))
|
Name: "name-foo",
|
||||||
}
|
Namespace: "ns-foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
return fakeClient
|
||||||
|
},
|
||||||
|
timeout: 0 * time.Second,
|
||||||
|
|
||||||
|
expectedErr: "thenonexistingresource.group \"name-foo\" not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "for existing resource with no timeout",
|
||||||
|
infos: []*resource.Info{
|
||||||
|
{
|
||||||
|
Mapping: &meta.RESTMapping{
|
||||||
|
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "theresource"},
|
||||||
|
},
|
||||||
|
Name: "name-foo",
|
||||||
|
Namespace: "ns-foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
|
fakeClient.PrependReactor("get", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
||||||
|
})
|
||||||
|
return fakeClient
|
||||||
|
},
|
||||||
|
timeout: 0 * time.Second,
|
||||||
|
|
||||||
|
expectedErr: "condition not met for theresource/name-foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch close out",
|
name: "handles watch close out",
|
||||||
@ -756,7 +735,7 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
count++
|
count++
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
fakeWatch := watch.NewRaceFreeFake()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(1 * time.Second)
|
||||||
fakeWatch.Stop()
|
fakeWatch.Stop()
|
||||||
}()
|
}()
|
||||||
return true, fakeWatch, nil
|
return true, fakeWatch, nil
|
||||||
@ -769,23 +748,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
timeout: 3 * time.Second,
|
timeout: 3 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") || actions[1].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") || actions[3].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch condition change",
|
name: "handles watch condition change",
|
||||||
@ -814,18 +776,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch created",
|
name: "handles watch created",
|
||||||
@ -840,29 +790,15 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
return true, newUnstructuredList(addCondition(
|
||||||
fakeWatch.Action(watch.Added, addCondition(
|
|
||||||
newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
|
newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||||
"the-condition", "status-value",
|
"the-condition", "status-value",
|
||||||
))
|
)), nil
|
||||||
return true, fakeWatch, nil
|
|
||||||
})
|
})
|
||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ignores watch error",
|
name: "ignores watch error",
|
||||||
@ -903,24 +839,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "times out due to stale .status.conditions[0].observedGeneration",
|
name: "times out due to stale .status.conditions[0].observedGeneration",
|
||||||
@ -945,18 +863,7 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 1 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: `theresource.group "name-foo" not found`,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch .status.conditions[0].observedGeneration change",
|
name: "handles watch .status.conditions[0].observedGeneration change",
|
||||||
@ -985,18 +892,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "times out due to stale .status.observedGeneration",
|
name: "times out due to stale .status.observedGeneration",
|
||||||
@ -1022,18 +917,7 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 1 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/name-foo",
|
expectedErr: `theresource.group "name-foo" not found`,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch .status.observedGeneration change",
|
name: "handles watch .status.observedGeneration change",
|
||||||
@ -1067,18 +951,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=name-foo" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1106,8 +978,6 @@ func TestWaitForCondition(t *testing.T) {
|
|||||||
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test.validateActions(t, fakeClient.Actions())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1305,7 +1175,7 @@ func TestWaitForDifferentJSONPathExpression(t *testing.T) {
|
|||||||
o := &WaitOptions{
|
o := &WaitOptions{
|
||||||
ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(infos...),
|
ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(infos...),
|
||||||
DynamicClient: fakeClient,
|
DynamicClient: fakeClient,
|
||||||
Timeout: 1 * time.Millisecond,
|
Timeout: 1 * time.Second,
|
||||||
|
|
||||||
Printer: printers.NewDiscardingPrinter(),
|
Printer: printers.NewDiscardingPrinter(),
|
||||||
ConditionFn: JSONPathWait{
|
ConditionFn: JSONPathWait{
|
||||||
@ -1348,8 +1218,7 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
jsonPathExp string
|
jsonPathExp string
|
||||||
jsonPathCond string
|
jsonPathCond string
|
||||||
|
|
||||||
expectedErr string
|
expectedErr string
|
||||||
validateActions func(t *testing.T, actions []clienttesting.Action)
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "present on get",
|
name: "present on get",
|
||||||
@ -1375,14 +1244,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
||||||
|
|
||||||
expectedErr: None,
|
expectedErr: None,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 1 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles no infos",
|
name: "handles no infos",
|
||||||
@ -1392,12 +1253,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
expectedErr: errNoMatchingResources.Error(),
|
expectedErr: errNoMatchingResources.Error(),
|
||||||
|
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 0 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles empty object name",
|
name: "handles empty object name",
|
||||||
@ -1415,11 +1270,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
timeout: 10 * time.Second,
|
timeout: 10 * time.Second,
|
||||||
|
|
||||||
expectedErr: "resource name must be provided",
|
expectedErr: "resource name must be provided",
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 0 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "times out",
|
name: "times out",
|
||||||
@ -1441,18 +1291,7 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
timeout: 1 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/foo-b6699dcfb-rnv7t",
|
expectedErr: `theresource.group "foo-b6699dcfb-rnv7t" not found`,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch close out",
|
name: "handles watch close out",
|
||||||
@ -1480,7 +1319,7 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
count++
|
count++
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
fakeWatch := watch.NewRaceFreeFake()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(1 * time.Second)
|
||||||
fakeWatch.Stop()
|
fakeWatch.Stop()
|
||||||
}()
|
}()
|
||||||
return true, fakeWatch, nil
|
return true, fakeWatch, nil
|
||||||
@ -1495,23 +1334,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
jsonPathCond: "foo", // use incorrect name so it'll keep waiting
|
jsonPathCond: "foo", // use incorrect name so it'll keep waiting
|
||||||
|
|
||||||
expectedErr: "timed out waiting for the condition on theresource/foo-b6699dcfb-rnv7t",
|
expectedErr: "timed out waiting for the condition on theresource/foo-b6699dcfb-rnv7t",
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") || actions[1].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") || actions[3].(clienttesting.WatchAction).GetWatchRestrictions().ResourceVersion != "234" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch condition change",
|
name: "handles watch condition change",
|
||||||
@ -1529,12 +1351,11 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
unstructuredObj := createUnstructured(t, podYAML)
|
unstructuredObj := createUnstructured(t, podYAML)
|
||||||
unstructuredObj.SetName("foo")
|
unstructuredObj.SetName("foo")
|
||||||
return true, newUnstructuredList(), nil
|
return true, newUnstructuredList(unstructuredObj), nil
|
||||||
})
|
})
|
||||||
fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
unstructuredObj := createUnstructured(t, podYAML)
|
||||||
fakeWatch.Action(watch.Modified, createUnstructured(t, podYAML))
|
return true, newUnstructuredList(unstructuredObj), nil
|
||||||
return true, fakeWatch, nil
|
|
||||||
})
|
})
|
||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
@ -1543,17 +1364,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
||||||
|
|
||||||
expectedErr: None,
|
expectedErr: None,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "handles watch created",
|
name: "handles watch created",
|
||||||
@ -1568,29 +1378,17 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
},
|
},
|
||||||
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
fakeWatch := watch.NewRaceFreeFake()
|
return true, newUnstructuredList(
|
||||||
fakeWatch.Action(watch.Added, createUnstructured(t, podYAML))
|
createUnstructured(t, podYAML)), nil
|
||||||
return true, fakeWatch, nil
|
|
||||||
})
|
})
|
||||||
return fakeClient
|
return fakeClient
|
||||||
},
|
},
|
||||||
timeout: 10 * time.Second,
|
timeout: 1 * time.Second,
|
||||||
jsonPathExp: "{.spec.containers[0].image}",
|
jsonPathExp: "{.spec.containers[0].image}",
|
||||||
jsonPathCond: "nginx",
|
jsonPathCond: "nginx",
|
||||||
|
|
||||||
expectedErr: None,
|
expectedErr: None,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 2 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ignores watch error",
|
name: "ignores watch error",
|
||||||
@ -1606,7 +1404,7 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
fakeClient: func() *dynamicfakeclient.FakeDynamicClient {
|
||||||
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
fakeClient := dynamicfakeclient.NewSimpleDynamicClientWithCustomListKinds(scheme, listMapping)
|
||||||
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
fakeClient.PrependReactor("list", "theresource", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "ns-foo", "name-foo")), nil
|
return true, newUnstructuredList(newUnstructured("group/version", "TheKind", "default", "foo-b6699dcfb-rnv7t")), nil
|
||||||
})
|
})
|
||||||
count := 0
|
count := 0
|
||||||
fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
|
fakeClient.PrependWatchReactor("theresource", func(action clienttesting.Action) (handled bool, ret watch.Interface, err error) {
|
||||||
@ -1632,23 +1430,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
jsonPathCond: "foo-b6699dcfb-rnv7t",
|
||||||
|
|
||||||
expectedErr: None,
|
expectedErr: None,
|
||||||
validateActions: func(t *testing.T, actions []clienttesting.Action) {
|
|
||||||
if len(actions) != 4 {
|
|
||||||
t.Fatal(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[0].Matches("list", "theresource") || actions[0].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[1].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[2].Matches("list", "theresource") || actions[2].(clienttesting.ListAction).GetListRestrictions().Fields.String() != "metadata.name=foo-b6699dcfb-rnv7t" {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
if !actions[3].Matches("watch", "theresource") {
|
|
||||||
t.Error(spew.Sdump(actions))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@ -1680,8 +1461,6 @@ func TestWaitForJSONPathCondition(t *testing.T) {
|
|||||||
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
t.Fatalf("expected %q, got %q", test.expectedErr, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test.validateActions(t, fakeClient.Actions())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user