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 }