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  }