瀏覽代碼

Wait for expected pod status on `compose up`

Signed-off-by: aiordache <[email protected]>
aiordache 4 年之前
父節點
當前提交
9ec5af76cd
共有 3 個文件被更改,包括 117 次插入12 次删除
  1. 70 11
      kube/client/client.go
  2. 43 0
      kube/client/utils.go
  3. 4 1
      kube/compose.go

+ 70 - 11
kube/client/client.go

@@ -22,6 +22,7 @@ import (
 	"context"
 	"fmt"
 	"io"
+	"time"
 
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/utils"
@@ -83,16 +84,6 @@ func (kc KubeClient) GetContainers(ctx context.Context, projectName string, all
 	return result, nil
 }
 
-func podToContainerSummary(pod corev1.Pod) compose.ContainerSummary {
-	return compose.ContainerSummary{
-		ID:      pod.GetObjectMeta().GetName(),
-		Name:    pod.GetObjectMeta().GetName(),
-		Service: pod.GetObjectMeta().GetLabels()[compose.ServiceTag],
-		State:   string(pod.Status.Phase),
-		Project: pod.GetObjectMeta().GetLabels()[compose.ProjectTag],
-	}
-}
-
 // GetLogs retrieves pod logs
 func (kc *KubeClient) GetLogs(ctx context.Context, projectName string, consumer compose.LogConsumer, follow bool) error {
 	pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{
@@ -111,13 +102,81 @@ func (kc *KubeClient) GetLogs(ctx context.Context, projectName string, consumer
 
 		eg.Go(func() error {
 			r, err := request.Stream(ctx)
-			defer r.Close() // nolint errcheck
 			if err != nil {
 				return err
 			}
+
+			defer r.Close() // nolint errcheck
 			_, err = io.Copy(w, r)
 			return err
 		})
 	}
 	return eg.Wait()
 }
+
+// WaitForRunningPodState blocks until pods are in running state
+func (kc KubeClient) WaitForPodState(ctx context.Context, projectName string, services []string, status string, timeout int) error {
+
+	if timeout > 0 {
+		var t time.Duration
+		t = time.Duration(timeout) * time.Second
+		fmt.Println("Timeout ", t)
+	}
+
+	selector := fmt.Sprintf("%s=%s", compose.ProjectTag, projectName)
+
+	waitingForPhase := corev1.PodRunning
+
+	switch status {
+	case compose.STARTING:
+		waitingForPhase = corev1.PodPending
+	case compose.UNKNOWN:
+		waitingForPhase = corev1.PodUnknown
+	}
+
+	//fieldSelector := "status.phase=Running"
+	for {
+		time.Sleep(time.Duration(1) * time.Second)
+		timeout = timeout - 1
+		if timeout <= 0 {
+			return fmt.Errorf("Deployment time out. Pods did not reach expected state.")
+		}
+
+		pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{
+			LabelSelector: selector,
+		})
+		if err != nil {
+			return err
+		}
+
+		servicePods := 0
+		stateReached := true
+		for _, pod := range pods.Items {
+
+			if status == compose.REMOVING {
+				if contains(services, pod.Labels[compose.ServiceTag]) {
+					servicePods = servicePods + 1
+				}
+
+				continue
+			}
+
+			if pod.Status.Phase != waitingForPhase {
+				stateReached = false
+
+			}
+		}
+
+		if status == compose.REMOVING {
+			if len(pods.Items) > 0 {
+				continue
+			}
+			return nil
+		}
+
+		if !stateReached {
+			continue
+		}
+		return nil
+	}
+}

+ 43 - 0
kube/client/utils.go

@@ -0,0 +1,43 @@
+// +build kube
+
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package client
+
+import (
+	"github.com/docker/compose-cli/api/compose"
+	corev1 "k8s.io/api/core/v1"
+)
+
+func podToContainerSummary(pod corev1.Pod) compose.ContainerSummary {
+	return compose.ContainerSummary{
+		ID:      pod.GetObjectMeta().GetName(),
+		Name:    pod.GetObjectMeta().GetName(),
+		Service: pod.GetObjectMeta().GetLabels()[compose.ServiceTag],
+		State:   string(pod.Status.Phase),
+		Project: pod.GetObjectMeta().GetLabels()[compose.ProjectTag],
+	}
+}
+
+func contains(slice []string, item string) bool {
+	for _, v := range slice {
+		if v == item {
+			return true
+		}
+	}
+	return false
+}

+ 4 - 1
kube/compose.go

@@ -91,7 +91,10 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
 	})
 
 	w.Event(progress.NewEvent(eventName, progress.Done, ""))
-	return err
+
+	eventName = "Wait for pods to be running"
+
+	return s.client.WaitForPodState(ctx, project.Name, project.ServiceNames(), compose.RUNNING, 10)
 }
 
 // Down executes the equivalent to a `compose down`