-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
pod.go
174 lines (157 loc) · 6.32 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package k8s
import (
"context"
"fmt"
"time"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/gruntwork-io/terratest/modules/retry"
"github.com/gruntwork-io/terratest/modules/testing"
)
// ListPods will look for pods in the given namespace that match the given filters and return them. This will fail the
// test if there is an error.
func ListPods(t testing.TestingT, options *KubectlOptions, filters metav1.ListOptions) []corev1.Pod {
pods, err := ListPodsE(t, options, filters)
require.NoError(t, err)
return pods
}
// ListPodsE will look for pods in the given namespace that match the given filters and return them.
func ListPodsE(t testing.TestingT, options *KubectlOptions, filters metav1.ListOptions) ([]corev1.Pod, error) {
clientset, err := GetKubernetesClientFromOptionsE(t, options)
if err != nil {
return nil, err
}
resp, err := clientset.CoreV1().Pods(options.Namespace).List(context.Background(), filters)
if err != nil {
return nil, err
}
return resp.Items, nil
}
// GetPod returns a Kubernetes pod resource in the provided namespace with the given name. This will
// fail the test if there is an error.
func GetPod(t testing.TestingT, options *KubectlOptions, podName string) *corev1.Pod {
pod, err := GetPodE(t, options, podName)
require.NoError(t, err)
return pod
}
// GetPodE returns a Kubernetes pod resource in the provided namespace with the given name.
func GetPodE(t testing.TestingT, options *KubectlOptions, podName string) (*corev1.Pod, error) {
clientset, err := GetKubernetesClientFromOptionsE(t, options)
if err != nil {
return nil, err
}
return clientset.CoreV1().Pods(options.Namespace).Get(context.Background(), podName, metav1.GetOptions{})
}
// WaitUntilNumPodsCreated waits until the desired number of pods are created that match the provided filter. This will
// retry the check for the specified amount of times, sleeping for the provided duration between each try. This will
// fail the test if the retry times out.
func WaitUntilNumPodsCreated(
t testing.TestingT,
options *KubectlOptions,
filters metav1.ListOptions,
desiredCount int,
retries int,
sleepBetweenRetries time.Duration,
) {
require.NoError(t, WaitUntilNumPodsCreatedE(t, options, filters, desiredCount, retries, sleepBetweenRetries))
}
// WaitUntilNumPodsCreatedE waits until the desired number of pods are created that match the provided filter. This will
// retry the check for the specified amount of times, sleeping for the provided duration between each try.
func WaitUntilNumPodsCreatedE(
t testing.TestingT,
options *KubectlOptions,
filters metav1.ListOptions,
desiredCount int,
retries int,
sleepBetweenRetries time.Duration,
) error {
statusMsg := fmt.Sprintf("Wait for num pods created to match desired count %d.", desiredCount)
message, err := retry.DoWithRetryE(
t,
statusMsg,
retries,
sleepBetweenRetries,
func() (string, error) {
pods, err := ListPodsE(t, options, filters)
if err != nil {
return "", err
}
if len(pods) != desiredCount {
return "", DesiredNumberOfPodsNotCreated{Filter: filters, DesiredCount: desiredCount}
}
return "Desired number of Pods created", nil
},
)
if err != nil {
options.Logger.Logf(t, "Timedout waiting for the desired number of Pods to be created: %s", err)
return err
}
options.Logger.Logf(t, message)
return nil
}
// WaitUntilPodAvailable waits until all of the containers within the pod are ready and started, retrying the check for the specified amount of times, sleeping
// for the provided duration between each try. This will fail the test if there is an error or if the check times out.
func WaitUntilPodAvailable(t testing.TestingT, options *KubectlOptions, podName string, retries int, sleepBetweenRetries time.Duration) {
require.NoError(t, WaitUntilPodAvailableE(t, options, podName, retries, sleepBetweenRetries))
}
// WaitUntilPodAvailableE waits until all of the containers within the pod are ready and started, retrying the check for the specified amount of times, sleeping
// for the provided duration between each try.
func WaitUntilPodAvailableE(t testing.TestingT, options *KubectlOptions, podName string, retries int, sleepBetweenRetries time.Duration) error {
statusMsg := fmt.Sprintf("Wait for pod %s to be provisioned.", podName)
message, err := retry.DoWithRetryE(
t,
statusMsg,
retries,
sleepBetweenRetries,
func() (string, error) {
pod, err := GetPodE(t, options, podName)
if err != nil {
return "", err
}
if !IsPodAvailable(pod) {
return "", NewPodNotAvailableError(pod)
}
return "Pod is now available", nil
},
)
if err != nil {
options.Logger.Logf(t, "Timedout waiting for Pod to be provisioned: %s", err)
return err
}
options.Logger.Logf(t, message)
return nil
}
// IsPodAvailable returns true if the all of the containers within the pod are ready and started
func IsPodAvailable(pod *corev1.Pod) bool {
for _, containerStatus := range pod.Status.ContainerStatuses {
isContainerStarted := containerStatus.Started
isContainerReady := containerStatus.Ready
if !isContainerReady || (isContainerStarted != nil && *isContainerStarted == false) {
return false
}
}
return pod.Status.Phase == corev1.PodRunning
}
// GetPodLogsE returns the logs of a Pod at the time when the function was called. Pass container name if there are more containers in the Pod or set to "" if there is only one.
// If the Pod is not running an Error is returned.
// If the provided containerName is not the name of a container in the Pod an Error is returned.
func GetPodLogsE(t testing.TestingT, options *KubectlOptions, pod *corev1.Pod, containerName string) (string, error) {
var output string
var err error
if containerName == "" {
output, err = RunKubectlAndGetOutputE(t, options, "logs", pod.Name)
} else {
output, err = RunKubectlAndGetOutputE(t, options, "logs", pod.Name, fmt.Sprintf("-c%s", containerName))
}
if err != nil {
return "", err
}
return output, nil
}
// GetPodLogsE returns the logs of a Pod at the time when the function was called. Pass container name if there are more containers in the Pod or set to "" if there is only one.
func GetPodLogs(t testing.TestingT, options *KubectlOptions, pod *corev1.Pod, containerName string) string {
logs, err := GetPodLogsE(t, options, pod, containerName)
require.NoError(t, err)
return logs
}