github.com/midokura/kubeedge@v1.2.0-mido.0/tests/e2e/utils/pod.go (about)

     1  /*
     2  Copyright 2019 The KubeEdge Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8     http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package utils
    18  
    19  import (
    20  	"encoding/json"
    21  	"io/ioutil"
    22  	"net/http"
    23  	"strings"
    24  	"time"
    25  
    26  	. "github.com/onsi/gomega"
    27  	v1 "k8s.io/api/core/v1"
    28  	"k8s.io/apimachinery/pkg/fields"
    29  	"k8s.io/client-go/kubernetes"
    30  	"k8s.io/client-go/tools/cache"
    31  	"k8s.io/client-go/tools/clientcmd"
    32  )
    33  
    34  const (
    35  	podLabelSelector = "?fieldSelector=spec.nodeName="
    36  )
    37  
    38  //GetPods function to get the pods from Edged
    39  func GetPods(apiserver, label string) (v1.PodList, error) {
    40  	var pods v1.PodList
    41  	var resp *http.Response
    42  	var err error
    43  
    44  	if len(label) > 0 {
    45  		err, resp = SendHttpRequest(http.MethodGet, apiserver+podLabelSelector+label)
    46  	} else {
    47  		err, resp = SendHttpRequest(http.MethodGet, apiserver)
    48  	}
    49  	if err != nil {
    50  		Fatalf("Frame HTTP request failed: %v", err)
    51  		return pods, nil
    52  	}
    53  	defer resp.Body.Close()
    54  	contents, err := ioutil.ReadAll(resp.Body)
    55  	if err != nil {
    56  		Fatalf("HTTP Response reading has failed: %v", err)
    57  		return pods, nil
    58  	}
    59  	err = json.Unmarshal(contents, &pods)
    60  	if err != nil {
    61  		Fatalf("Unmarshal HTTP Response has failed: %v", err)
    62  		return pods, nil
    63  	}
    64  	return pods, nil
    65  }
    66  
    67  //GetPodState function to get the pod status and response code
    68  func GetPodState(apiserver string) (string, int) {
    69  	var pod v1.Pod
    70  
    71  	err, resp := SendHttpRequest(http.MethodGet, apiserver)
    72  	if err != nil {
    73  		Fatalf("GetPodState :SenHttpRequest failed: %v", err)
    74  	}
    75  	defer resp.Body.Close()
    76  
    77  	if resp.StatusCode != http.StatusNotFound {
    78  		contents, err := ioutil.ReadAll(resp.Body)
    79  		if err != nil {
    80  			Fatalf("HTTP Response reading has failed: %v", err)
    81  		}
    82  		err = json.Unmarshal(contents, &pod)
    83  		if err != nil {
    84  			Fatalf("Unmarshal HTTP Response has failed: %v", err)
    85  		}
    86  		return string(pod.Status.Phase), resp.StatusCode
    87  	}
    88  
    89  	return "", resp.StatusCode
    90  }
    91  
    92  //DeletePods function to get the pod status and response code
    93  func DeletePods(apiserver string) (string, int) {
    94  	var pod v1.Pod
    95  	err, resp := SendHttpRequest(http.MethodDelete, apiserver)
    96  	if err != nil {
    97  		Fatalf("GetPodState :SenHttpRequest failed: %v", err)
    98  	}
    99  	defer resp.Body.Close()
   100  
   101  	if resp.StatusCode != http.StatusNotFound {
   102  		contents, err := ioutil.ReadAll(resp.Body)
   103  		if err != nil {
   104  			Fatalf("HTTP Response reading has failed: %v", err)
   105  		}
   106  		err = json.Unmarshal(contents, &pod)
   107  		if err != nil {
   108  			Fatalf("Unmarshal HTTP Response has failed: %v", err)
   109  		}
   110  		return string(pod.Status.Phase), resp.StatusCode
   111  	}
   112  
   113  	return "", resp.StatusCode
   114  }
   115  
   116  //CheckPodRunningState function to check the Pod state
   117  func CheckPodRunningState(apiserver string, podlist v1.PodList) {
   118  	Eventually(func() int {
   119  		var count int
   120  		for _, pod := range podlist.Items {
   121  			state, _ := GetPodState(apiserver + "/" + pod.Name)
   122  			Infof("PodName: %s PodStatus: %s", pod.Name, state)
   123  			if state == "Running" {
   124  				count++
   125  			}
   126  		}
   127  		return count
   128  	}, "600s", "2s").Should(Equal(len(podlist.Items)), "Application deployment is Unsuccessfull, Pod has not come to Running State")
   129  
   130  }
   131  
   132  //CheckPodDeleteState function to check the Pod state
   133  func CheckPodDeleteState(apiserver string, podlist v1.PodList) {
   134  	var count int
   135  	//skip the edgecore/cloudcore deployment pods and count only application pods deployed on KubeEdge edgen node
   136  	for _, pod := range podlist.Items {
   137  		if strings.Contains(pod.Name, "deployment-") {
   138  			count++
   139  		}
   140  	}
   141  	podCount := len(podlist.Items) - count
   142  	Eventually(func() int {
   143  		var count int
   144  		for _, pod := range podlist.Items {
   145  			status, statusCode := GetPodState(apiserver + "/" + pod.Name)
   146  			Infof("PodName: %s status: %s StatusCode: %d", pod.Name, status, statusCode)
   147  			if statusCode == 404 {
   148  				count++
   149  			}
   150  		}
   151  		return count
   152  	}, "600s", "4s").Should(Equal(podCount), "Delete Application deployment is Unsuccessfull, Pods are not deleted within the time")
   153  
   154  }
   155  
   156  //CheckDeploymentPodDeleteState function to check the Pod state
   157  func CheckDeploymentPodDeleteState(apiserver string, podlist v1.PodList) {
   158  	var count int
   159  	//count the edgecore/cloudcore deployment pods and count only application pods deployed on KubeEdge edgen node
   160  	for _, pod := range podlist.Items {
   161  		if strings.Contains(pod.Name, "deployment-") {
   162  			count++
   163  		}
   164  	}
   165  	//podCount := len(podlist.Items) - count
   166  	Eventually(func() int {
   167  		var count int
   168  		for _, pod := range podlist.Items {
   169  			status, statusCode := GetPodState(apiserver + "/" + pod.Name)
   170  			Infof("PodName: %s status: %s StatusCode: %d", pod.Name, status, statusCode)
   171  			if statusCode == 404 {
   172  				count++
   173  			}
   174  		}
   175  		return count
   176  	}, "240s", "4s").Should(Equal(count), "Delete Application deployment is Unsuccessfull, Pods are not deleted within the time")
   177  
   178  }
   179  
   180  // NewKubeClient creates kube client from config
   181  func NewKubeClient(kubeConfigPath string) *kubernetes.Clientset {
   182  	kubeConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
   183  	if err != nil {
   184  		Fatalf("Get kube config failed with error: %v", err)
   185  		return nil
   186  	}
   187  	kubeConfig.QPS = 5
   188  	kubeConfig.Burst = 10
   189  	kubeConfig.ContentType = "application/vnd.kubernetes.protobuf"
   190  	kubeClient, err := kubernetes.NewForConfig(kubeConfig)
   191  	if err != nil {
   192  		Fatalf("Get kube client failed with error: %v", err)
   193  		return nil
   194  	}
   195  	return kubeClient
   196  }
   197  
   198  // WaitforPodsRunning waits util all pods are in running status or timeout
   199  func WaitforPodsRunning(kubeConfigPath string, podlist v1.PodList, timout time.Duration) {
   200  	if len(podlist.Items) == 0 {
   201  		Fatalf("podlist should not be empty")
   202  	}
   203  
   204  	podRunningCount := 0
   205  	for _, pod := range podlist.Items {
   206  		if pod.Status.Phase == v1.PodRunning {
   207  			podRunningCount++
   208  		}
   209  	}
   210  	if podRunningCount == len(podlist.Items) {
   211  		Infof("All pods come into running status")
   212  		return
   213  	}
   214  
   215  	// new kube client
   216  	kubeClient := NewKubeClient(kubeConfigPath)
   217  	// define signal
   218  	signal := make(chan struct{})
   219  	// define list watcher
   220  	listWatcher := cache.NewListWatchFromClient(
   221  		kubeClient.CoreV1().RESTClient(),
   222  		"pods",
   223  		v1.NamespaceAll,
   224  		fields.Everything())
   225  	// new controller
   226  	_, controller := cache.NewInformer(
   227  		listWatcher,
   228  		&v1.Pod{},
   229  		time.Second*0,
   230  		cache.ResourceEventHandlerFuncs{
   231  			// receive update events
   232  			UpdateFunc: func(oldObj, newObj interface{}) {
   233  				// check update obj
   234  				p, ok := newObj.(*v1.Pod)
   235  				if !ok {
   236  					Fatalf("Failed to cast observed object to pod")
   237  				}
   238  				// calculate the pods in running status
   239  				count := 0
   240  				for i := range podlist.Items {
   241  					// update pod status in podlist
   242  					if podlist.Items[i].Name == p.Name {
   243  						Infof("PodName: %s PodStatus: %s", p.Name, p.Status.Phase)
   244  						podlist.Items[i].Status = p.Status
   245  					}
   246  					// check if the pod is in running status
   247  					if podlist.Items[i].Status.Phase == v1.PodRunning {
   248  						count++
   249  					}
   250  				}
   251  				// send an end signal when all pods are in running status
   252  				if len(podlist.Items) == count {
   253  					signal <- struct{}{}
   254  				}
   255  			},
   256  		},
   257  	)
   258  
   259  	// run controoler
   260  	podChan := make(chan struct{})
   261  	go controller.Run(podChan)
   262  	defer close(podChan)
   263  
   264  	// wait for a signal or timeout
   265  	select {
   266  	case <-signal:
   267  		Infof("All pods come into running status")
   268  	case <-time.After(timout):
   269  		Fatalf("Wait for pods come into running status timeout: %v", timout)
   270  	}
   271  }