/
pod.go
110 lines (103 loc) · 3.39 KB
/
pod.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package opts
import (
"fmt"
"time"
"github.com/jenkins-x/jx-logging/pkg/log"
"github.com/jenkins-x/jx/v2/pkg/kube"
"github.com/jenkins-x/jx/v2/pkg/util"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
)
// WaitForReadyPodForDeployment waits for a pod of a deployment to be ready
func (o *CommonOptions) WaitForReadyPodForDeployment(c kubernetes.Interface, ns string, name string, names []string, readyOnly bool) (string, error) {
deployment, err := c.AppsV1().Deployments(ns).Get(name, metav1.GetOptions{})
if err != nil || deployment == nil {
return "", util.InvalidArg(name, names)
}
selector := deployment.Spec.Selector
if selector == nil {
return "", fmt.Errorf("No selector defined on Deployment %s in namespace %s", name, ns)
}
labels := selector.MatchLabels
if labels == nil {
return "", fmt.Errorf("No MatchLabels defined on the Selector of Deployment %s in namespace %s", name, ns)
}
return o.WaitForReadyPodForSelectorLabels(c, ns, labels, readyOnly)
}
// WaitForReadyPodForSelectorLabels waits for a pod selected by the given labels to be ready
func (o *CommonOptions) WaitForReadyPodForSelectorLabels(c kubernetes.Interface, ns string, labels map[string]string, readyOnly bool) (string, error) {
selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: labels})
if err != nil {
return "", err
}
return o.WaitForReadyPodForSelector(c, ns, selector, readyOnly)
}
// WaitForReadyPodForSelector waits for a pod to which the selector applies to be ready
func (o *CommonOptions) WaitForReadyPodForSelector(c kubernetes.Interface, ns string, selector labels.Selector, readyOnly bool) (string, error) {
log.Logger().Warnf("Waiting for a running pod in namespace %s with labels %v", ns, selector.String())
lastPod := ""
for {
pods, err := c.CoreV1().Pods(ns).List(metav1.ListOptions{
LabelSelector: selector.String(),
})
if err != nil {
return "", err
}
name := ""
loggedContainerIdx := -1
var latestPod *corev1.Pod
lastTime := time.Time{}
for _, p := range pods.Items {
pod := p
phase := pod.Status.Phase
if phase == corev1.PodRunning || phase == corev1.PodPending {
if !readyOnly {
created := pod.CreationTimestamp
if name == "" || created.After(lastTime) {
lastTime = created.Time
name = pod.Name
latestPod = &pod
}
}
}
}
if latestPod != nil && name != "" {
if name != lastPod {
lastPod = name
loggedContainerIdx = -1
log.Logger().Warnf("Found newest pod: %s", name)
}
if kube.IsPodReady(latestPod) {
return name, nil
}
_, containerStatuses, _ := kube.GetContainersWithStatusAndIsInit(latestPod)
for idx, ic := range containerStatuses {
if isContainerStarted(&ic.State) && idx > loggedContainerIdx {
loggedContainerIdx = idx
containerName := ic.Name
log.Logger().Warnf("Container on pod: %s is: %s", name, containerName)
err = o.TailLogs(ns, name, containerName)
if err != nil {
break
}
}
}
}
// TODO replace with a watch flavour
time.Sleep(time.Second)
}
}
func isContainerStarted(state *corev1.ContainerState) bool {
if state == nil {
return false
}
if state.Running != nil {
return !state.Running.StartedAt.IsZero()
}
if state != nil && state.Terminated != nil {
return !state.Terminated.StartedAt.IsZero()
}
return false
}