github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/kube/wait.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package kube // import "github.com/stefanmcshane/helm/pkg/kube"
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	"github.com/pkg/errors"
    25  	appsv1 "k8s.io/api/apps/v1"
    26  	appsv1beta1 "k8s.io/api/apps/v1beta1"
    27  	appsv1beta2 "k8s.io/api/apps/v1beta2"
    28  	batchv1 "k8s.io/api/batch/v1"
    29  	corev1 "k8s.io/api/core/v1"
    30  	extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
    31  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/apimachinery/pkg/labels"
    34  	"k8s.io/apimachinery/pkg/runtime"
    35  
    36  	"k8s.io/apimachinery/pkg/util/wait"
    37  )
    38  
    39  type waiter struct {
    40  	c       ReadyChecker
    41  	timeout time.Duration
    42  	log     func(string, ...interface{})
    43  }
    44  
    45  // waitForResources polls to get the current status of all pods, PVCs, Services and
    46  // Jobs(optional) until all are ready or a timeout is reached
    47  func (w *waiter) waitForResources(created ResourceList) error {
    48  	w.log("beginning wait for %d resources with timeout of %v", len(created), w.timeout)
    49  
    50  	ctx, cancel := context.WithTimeout(context.Background(), w.timeout)
    51  	defer cancel()
    52  
    53  	return wait.PollImmediateUntil(2*time.Second, func() (bool, error) {
    54  		for _, v := range created {
    55  			ready, err := w.c.IsReady(ctx, v)
    56  			if !ready || err != nil {
    57  				return false, err
    58  			}
    59  		}
    60  		return true, nil
    61  	}, ctx.Done())
    62  }
    63  
    64  // waitForDeletedResources polls to check if all the resources are deleted or a timeout is reached
    65  func (w *waiter) waitForDeletedResources(deleted ResourceList) error {
    66  	w.log("beginning wait for %d resources to be deleted with timeout of %v", len(deleted), w.timeout)
    67  
    68  	ctx, cancel := context.WithTimeout(context.Background(), w.timeout)
    69  	defer cancel()
    70  
    71  	return wait.PollImmediateUntil(2*time.Second, func() (bool, error) {
    72  		for _, v := range deleted {
    73  			err := v.Get()
    74  			if err == nil || !apierrors.IsNotFound(err) {
    75  				return false, err
    76  			}
    77  		}
    78  		return true, nil
    79  	}, ctx.Done())
    80  }
    81  
    82  // SelectorsForObject returns the pod label selector for a given object
    83  //
    84  // Modified version of https://github.com/kubernetes/kubernetes/blob/v1.14.1/pkg/kubectl/polymorphichelpers/helpers.go#L84
    85  func SelectorsForObject(object runtime.Object) (selector labels.Selector, err error) {
    86  	switch t := object.(type) {
    87  	case *extensionsv1beta1.ReplicaSet:
    88  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
    89  	case *appsv1.ReplicaSet:
    90  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
    91  	case *appsv1beta2.ReplicaSet:
    92  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
    93  	case *corev1.ReplicationController:
    94  		selector = labels.SelectorFromSet(t.Spec.Selector)
    95  	case *appsv1.StatefulSet:
    96  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
    97  	case *appsv1beta1.StatefulSet:
    98  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
    99  	case *appsv1beta2.StatefulSet:
   100  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   101  	case *extensionsv1beta1.DaemonSet:
   102  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   103  	case *appsv1.DaemonSet:
   104  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   105  	case *appsv1beta2.DaemonSet:
   106  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   107  	case *extensionsv1beta1.Deployment:
   108  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   109  	case *appsv1.Deployment:
   110  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   111  	case *appsv1beta1.Deployment:
   112  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   113  	case *appsv1beta2.Deployment:
   114  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   115  	case *batchv1.Job:
   116  		selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
   117  	case *corev1.Service:
   118  		if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 {
   119  			return nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name)
   120  		}
   121  		selector = labels.SelectorFromSet(t.Spec.Selector)
   122  
   123  	default:
   124  		return nil, fmt.Errorf("selector for %T not implemented", object)
   125  	}
   126  
   127  	return selector, errors.Wrap(err, "invalid label selector")
   128  }