github.com/dmvolod/operator-sdk@v0.8.2/pkg/test/e2eutil/wait_util.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package e2eutil 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/operator-framework/operator-sdk/pkg/test" 23 24 apierrors "k8s.io/apimachinery/pkg/api/errors" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/util/wait" 28 "k8s.io/client-go/kubernetes" 29 "sigs.k8s.io/controller-runtime/pkg/client" 30 ) 31 32 // WaitForDeployment checks to see if a given deployment has a certain number of available replicas after a specified amount of time 33 // If the deployment does not have the required number of replicas after 5 * retries seconds, the function returns an error 34 // This can be used in multiple ways, like verifying that a required resource is ready before trying to use it, or to test 35 // failure handling, like simulated in SimulatePodFail. 36 func WaitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration) error { 37 return waitForDeployment(t, kubeclient, namespace, name, replicas, retryInterval, timeout, false) 38 } 39 40 // WaitForOperatorDeployment has the same functionality as WaitForDeployment but will no wait for the deployment if the 41 // test was run with a locally run operator (--up-local flag) 42 func WaitForOperatorDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration) error { 43 return waitForDeployment(t, kubeclient, namespace, name, replicas, retryInterval, timeout, true) 44 } 45 46 func waitForDeployment(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, replicas int, retryInterval, timeout time.Duration, isOperator bool) error { 47 if isOperator && test.Global.LocalOperator { 48 t.Log("Operator is running locally; skip waitForDeployment") 49 return nil 50 } 51 err := wait.Poll(retryInterval, timeout, func() (done bool, err error) { 52 deployment, err := kubeclient.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{IncludeUninitialized: true}) 53 if err != nil { 54 if apierrors.IsNotFound(err) { 55 t.Logf("Waiting for availability of %s deployment\n", name) 56 return false, nil 57 } 58 return false, err 59 } 60 61 if int(deployment.Status.AvailableReplicas) == replicas { 62 return true, nil 63 } 64 t.Logf("Waiting for full availability of %s deployment (%d/%d)\n", name, deployment.Status.AvailableReplicas, replicas) 65 return false, nil 66 }) 67 if err != nil { 68 return err 69 } 70 t.Logf("Deployment available (%d/%d)\n", replicas, replicas) 71 return nil 72 } 73 74 func WaitForDeletion(t *testing.T, dynclient client.Client, obj runtime.Object, retryInterval, timeout time.Duration) error { 75 key, err := client.ObjectKeyFromObject(obj) 76 if err != nil { 77 return err 78 } 79 80 kind := obj.GetObjectKind().GroupVersionKind().Kind 81 ctx, cancel := context.WithTimeout(context.Background(), timeout) 82 defer cancel() 83 err = wait.Poll(retryInterval, timeout, func() (done bool, err error) { 84 err = dynclient.Get(ctx, key, obj) 85 if apierrors.IsNotFound(err) { 86 return true, nil 87 } 88 if err != nil { 89 return false, err 90 } 91 t.Logf("Waiting for %s %s to be deleted\n", kind, key) 92 return false, nil 93 }) 94 if err != nil { 95 return err 96 } 97 t.Logf("%s %s was deleted\n", kind, key) 98 return nil 99 }