github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/deployments.go (about)

     1  package kube
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/jenkins-x/jx-logging/pkg/log"
    11  	appsv1 "k8s.io/api/apps/v1"
    12  	v1 "k8s.io/api/core/v1"
    13  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	"k8s.io/apimachinery/pkg/util/wait"
    15  	"k8s.io/apimachinery/pkg/watch"
    16  	"k8s.io/client-go/kubernetes"
    17  	tools_watch "k8s.io/client-go/tools/watch"
    18  )
    19  
    20  // GetDeployments get deployments in the given namespace
    21  func GetDeployments(kubeClient kubernetes.Interface, ns string) (map[string]appsv1.Deployment, error) {
    22  	answer := map[string]appsv1.Deployment{}
    23  	deps, err := kubeClient.AppsV1().Deployments(ns).List(metav1.ListOptions{})
    24  	if err != nil {
    25  		return answer, err
    26  	}
    27  	for _, d := range deps.Items {
    28  		answer[d.Name] = d
    29  	}
    30  	return answer, nil
    31  }
    32  
    33  // GetDeploymentNames get deployment names in the given namespace with filter
    34  func GetDeploymentNames(client kubernetes.Interface, ns string, filter string) ([]string, error) {
    35  	names := []string{}
    36  	list, err := client.AppsV1().Deployments(ns).List(metav1.ListOptions{})
    37  	if err != nil {
    38  		return names, fmt.Errorf("Failed to load Deployments %s", err)
    39  	}
    40  	for _, d := range list.Items {
    41  		name := d.Name
    42  		if filter == "" || strings.Contains(name, filter) {
    43  			names = append(names, name)
    44  		}
    45  	}
    46  	sort.Strings(names)
    47  	return names, nil
    48  }
    49  
    50  // GetDeploymentByRepo get deployment in the given namespace with repo name
    51  func GetDeploymentByRepo(client kubernetes.Interface, ns string, repoName string) (*appsv1.Deployment, error) {
    52  	deps, err := client.AppsV1().Deployments(ns).List(metav1.ListOptions{})
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	for _, d := range deps.Items {
    57  		if strings.HasPrefix(d.Name, repoName) {
    58  			return &d, nil
    59  		}
    60  	}
    61  	return nil, fmt.Errorf("no deployment found for repository name '%s'", repoName)
    62  }
    63  
    64  // IsDeploymentRunning returns whether this deployment is running
    65  func IsDeploymentRunning(client kubernetes.Interface, name, namespace string) (bool, error) {
    66  	options := metav1.GetOptions{}
    67  
    68  	d, err := client.AppsV1().Deployments(namespace).Get(name, options)
    69  	if err != nil {
    70  		return false, err
    71  	}
    72  
    73  	if d.Status.ReadyReplicas > 0 {
    74  		return true, nil
    75  	}
    76  	return false, nil
    77  }
    78  
    79  // WaitForAllDeploymentsToBeReady waits for the pods of all deployment to become ready in the given namespace
    80  func WaitForAllDeploymentsToBeReady(client kubernetes.Interface, namespace string, timeoutPerDeploy time.Duration) error {
    81  	deployList, err := client.AppsV1().Deployments(namespace).List(metav1.ListOptions{})
    82  	if err != nil {
    83  		return err
    84  	}
    85  	if deployList == nil || len(deployList.Items) == 0 {
    86  		return fmt.Errorf("no deployments found in namespace %s", namespace)
    87  	}
    88  
    89  	for _, d := range deployList.Items {
    90  		err = WaitForDeploymentToBeReady(client, d.Name, namespace, timeoutPerDeploy)
    91  		if err != nil {
    92  			log.Logger().Warnf("deployment %s failed to become ready in namespace %s", d.Name, namespace)
    93  		}
    94  	}
    95  	return nil
    96  }
    97  
    98  // WaitForDeploymentToBeCreatedAndReady waits for the pods of a deployment created and to become ready
    99  func WaitForDeploymentToBeCreatedAndReady(client kubernetes.Interface, name, namespace string, timeoutPerDeploy time.Duration) error {
   100  
   101  	options := metav1.ListOptions{FieldSelector: fmt.Sprintf("metadata.name=%s", name)}
   102  
   103  	w, err := client.AppsV1().Deployments(namespace).Watch(options)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	defer w.Stop()
   108  
   109  	condition := func(event watch.Event) (bool, error) {
   110  		running, _ := IsDeploymentRunning(client, name, namespace)
   111  		return running, nil
   112  	}
   113  	ctx, _ := context.WithTimeout(context.Background(), timeoutPerDeploy)
   114  	_, err = tools_watch.UntilWithoutRetry(ctx, w, condition)
   115  
   116  	if err == wait.ErrWaitTimeout {
   117  		return fmt.Errorf("deployment %s never became ready", name)
   118  	}
   119  	return nil
   120  }
   121  
   122  // WaitForDeploymentToBeReady waits for the pods of a deployment to become ready
   123  func WaitForDeploymentToBeReady(client kubernetes.Interface, name, namespace string, timeout time.Duration) error {
   124  	d, err := client.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	selector, err := metav1.LabelSelectorAsSelector(d.Spec.Selector)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	// Skip watching if the deployment is ready
   135  	if d.Status.Replicas != d.Status.ReadyReplicas {
   136  		options := metav1.ListOptions{LabelSelector: selector.String()}
   137  		w, err := client.CoreV1().Pods(namespace).Watch(options)
   138  
   139  		if err != nil {
   140  			return err
   141  		}
   142  		defer w.Stop()
   143  
   144  		condition := func(event watch.Event) (bool, error) {
   145  			pod := event.Object.(*v1.Pod)
   146  			return IsPodReady(pod), nil
   147  		}
   148  
   149  		ctx, _ := context.WithTimeout(context.Background(), timeout)
   150  		_, err = tools_watch.UntilWithoutRetry(ctx, w, condition)
   151  
   152  		if err == wait.ErrWaitTimeout {
   153  			return fmt.Errorf("deployment %s never became ready", name)
   154  		}
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  // DeploymentPodCount returns pod counts of deployment
   161  func DeploymentPodCount(client kubernetes.Interface, name, namespace string) (int, error) {
   162  	pods, err := GetDeploymentPods(client, name, namespace)
   163  	if err == nil {
   164  		return len(pods), err
   165  	}
   166  	return 0, err
   167  }
   168  
   169  // GetDeploymentPods returns pods of deployment
   170  func GetDeploymentPods(client kubernetes.Interface, name, namespace string) ([]v1.Pod, error) {
   171  	d, err := client.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	selector, err := metav1.LabelSelectorAsSelector(d.Spec.Selector)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	options := metav1.ListOptions{LabelSelector: selector.String()}
   182  
   183  	pods, err := client.CoreV1().Pods(namespace).List(options)
   184  
   185  	return pods.Items, err
   186  }