github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/pkg/clients/common/pod.go (about) 1 package common 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 . "github.com/onsi/ginkgo/v2" 9 "github.com/redhat-appstudio/e2e-tests/pkg/logs" 10 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 11 corev1 "k8s.io/api/core/v1" 12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 "k8s.io/apimachinery/pkg/labels" 14 "k8s.io/apimachinery/pkg/util/wait" 15 ) 16 17 // GetPod returns the pod object from a given namespace and pod name 18 func (s *SuiteController) GetPod(namespace, podName string) (*corev1.Pod, error) { 19 return s.KubeInterface().CoreV1().Pods(namespace).Get(context.Background(), podName, metav1.GetOptions{}) 20 } 21 22 func (s *SuiteController) IsPodRunning(podName, namespace string) wait.ConditionFunc { 23 return func() (bool, error) { 24 pod, err := s.GetPod(namespace, podName) 25 if err != nil { 26 return false, nil 27 } 28 switch pod.Status.Phase { 29 case corev1.PodRunning: 30 return true, nil 31 case corev1.PodFailed, corev1.PodSucceeded: 32 return false, fmt.Errorf("pod %q ran to completion", pod.Name) 33 } 34 return false, nil 35 } 36 } 37 38 // Checks phases of a given pod name in a given namespace 39 func (s *SuiteController) IsPodSuccessful(podName, namespace string) wait.ConditionFunc { 40 return func() (bool, error) { 41 pod, err := s.GetPod(namespace, podName) 42 if err != nil { 43 return false, nil 44 } 45 switch pod.Status.Phase { 46 case corev1.PodSucceeded: 47 return true, nil 48 case corev1.PodFailed: 49 return false, fmt.Errorf("pod %q has failed", pod.Name) 50 } 51 return false, nil 52 } 53 } 54 55 // ListPods return a list of pods from a namespace by labels and selection limits 56 func (s *SuiteController) ListPods(namespace, labelKey, labelValue string, selectionLimit int64) (*corev1.PodList, error) { 57 labelSelector := metav1.LabelSelector{MatchLabels: map[string]string{labelKey: labelValue}} 58 listOptions := metav1.ListOptions{ 59 LabelSelector: labels.Set(labelSelector.MatchLabels).String(), 60 Limit: selectionLimit, 61 } 62 return s.KubeInterface().CoreV1().Pods(namespace).List(context.Background(), listOptions) 63 } 64 65 // wait for a pod based on a condition. cond can be IsPodSuccessful for example 66 func (s *SuiteController) WaitForPod(cond wait.ConditionFunc, timeout int) error { 67 if err := utils.WaitUntil(cond, time.Duration(timeout)*time.Second); err != nil { 68 return err 69 } 70 return nil 71 } 72 73 // Wait for a pod selector until exists 74 func (s *SuiteController) WaitForPodSelector( 75 fn func(podName, namespace string) wait.ConditionFunc, namespace, labelKey string, labelValue string, 76 timeout int, selectionLimit int64) error { 77 podList, err := s.ListPods(namespace, labelKey, labelValue, selectionLimit) 78 if err != nil { 79 return err 80 } 81 if len(podList.Items) == 0 { 82 return fmt.Errorf("no pods in %s with label key %s and label value %s", namespace, labelKey, labelValue) 83 } 84 85 for i := range podList.Items { 86 if err := utils.WaitUntil(fn(podList.Items[i].Name, namespace), time.Duration(timeout)*time.Second); err != nil { 87 return err 88 } 89 } 90 return nil 91 } 92 93 // ListAllPods returns a list of all pods in a namespace. 94 func (s *SuiteController) ListAllPods(namespace string) (*corev1.PodList, error) { 95 return s.KubeInterface().CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{}) 96 } 97 98 func (s *SuiteController) GetPodLogs(pod *corev1.Pod) map[string][]byte { 99 podLogs := make(map[string][]byte) 100 101 var containers []corev1.Container 102 containers = append(containers, pod.Spec.InitContainers...) 103 containers = append(containers, pod.Spec.Containers...) 104 for _, c := range containers { 105 log, err := utils.GetContainerLogs(s.KubeInterface(), pod.Name, c.Name, pod.Namespace) 106 if err != nil { 107 GinkgoWriter.Printf("error getting logs for pod/container %s/%s: %v\n", pod.Name, c.Name, err.Error()) 108 continue 109 } 110 111 podLogs["pod-"+pod.Name+"-"+c.Name+".log"] = []byte(log) 112 } 113 114 return podLogs 115 } 116 117 // StorePod stores a given pod as an artifact. 118 func (s *SuiteController) StorePod(pod *corev1.Pod) error { 119 podLogs := s.GetPodLogs(pod) 120 return logs.StoreArtifacts(podLogs) 121 } 122 123 // StoreAllPods stores all pods in a given namespace. 124 func (s *SuiteController) StoreAllPods(namespace string) error { 125 podList, err := s.ListAllPods(namespace) 126 if err != nil { 127 return err 128 } 129 130 for _, pod := range podList.Items { 131 if err := s.StorePod(&pod); err != nil { 132 return err 133 } 134 } 135 return nil 136 } 137 138 func (s *SuiteController) DeletePod(podName string, namespace string) error { 139 if err := s.KubeInterface().CoreV1().Pods(namespace).Delete(context.Background(), podName, metav1.DeleteOptions{}); err != nil { 140 return fmt.Errorf("failed to restart pod '%s' in '%s' namespace: %+v", podName, namespace, err) 141 } 142 return nil 143 } 144 145 func (s *SuiteController) CreatePod(pod *corev1.Pod, namespace string) (*corev1.Pod, error) { 146 return s.KubeInterface().CoreV1().Pods(namespace).Create(context.Background(), pod, metav1.CreateOptions{}) 147 } 148 149 func (s *SuiteController) GetPodLogsByName(podName, namespace string) (map[string][]byte, error) { 150 pod, err := s.GetPod(namespace, podName) 151 if err != nil { 152 return map[string][]byte{}, err 153 } 154 logs := s.GetPodLogs(pod) 155 return logs, nil 156 }