github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/checker/pod_checker.go (about)

     1  // Copyright © 2021 Alibaba Group Holding Ltd.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package checker
    16  
    17  import (
    18  	"text/template"
    19  
    20  	corev1 "k8s.io/api/core/v1"
    21  
    22  	"github.com/sirupsen/logrus"
    23  
    24  	"github.com/sealerio/sealer/common"
    25  	"github.com/sealerio/sealer/pkg/client/k8s"
    26  	v2 "github.com/sealerio/sealer/types/api/v2"
    27  )
    28  
    29  type PodChecker struct {
    30  	client *k8s.Client
    31  }
    32  
    33  type PodNamespaceStatus struct {
    34  	NamespaceName     string
    35  	RunningCount      uint32
    36  	NotRunningCount   uint32
    37  	PodCount          uint32
    38  	NotRunningPodList []*corev1.Pod
    39  }
    40  
    41  var PodNamespaceStatusList []PodNamespaceStatus
    42  
    43  func (n *PodChecker) Check(cluster *v2.Cluster, phase string) error {
    44  	if phase != PhasePost {
    45  		return nil
    46  	}
    47  	c, err := k8s.NewK8sClient()
    48  	if err != nil {
    49  		return err
    50  	}
    51  	n.client = c
    52  
    53  	namespacePodList, err := n.client.ListAllNamespacesPods()
    54  	if err != nil {
    55  		return err
    56  	}
    57  	for _, podNamespace := range namespacePodList {
    58  		var runningCount uint32
    59  		var notRunningCount uint32
    60  		var podCount uint32
    61  		var notRunningPodList []*corev1.Pod
    62  		for _, pod := range podNamespace.PodList.Items {
    63  			if err := getPodReadyStatus(pod); err != nil {
    64  				notRunningCount++
    65  				newPod := pod
    66  				notRunningPodList = append(notRunningPodList, &newPod)
    67  			} else {
    68  				runningCount++
    69  			}
    70  		}
    71  		podCount = runningCount + notRunningCount
    72  		podNamespaceStatus := PodNamespaceStatus{
    73  			NamespaceName:     podNamespace.Namespace.Name,
    74  			RunningCount:      runningCount,
    75  			NotRunningCount:   notRunningCount,
    76  			PodCount:          podCount,
    77  			NotRunningPodList: notRunningPodList,
    78  		}
    79  		PodNamespaceStatusList = append(PodNamespaceStatusList, podNamespaceStatus)
    80  	}
    81  	err = n.Output(PodNamespaceStatusList)
    82  	if err != nil {
    83  		return err
    84  	}
    85  	return nil
    86  }
    87  
    88  func (n *PodChecker) Output(podNamespaceStatusList []PodNamespaceStatus) error {
    89  	t := template.New("pod_checker")
    90  	t, err := t.Parse(
    91  		`Cluster Pod Status
    92    {{ range . -}}
    93    Namespace: {{ .NamespaceName }}
    94    RunningPod: {{ .RunningCount }}/{{ .PodCount }}
    95    {{ if (gt .NotRunningCount 0) -}}
    96    Not Running Pod List:
    97      {{- range .NotRunningPodList }}
    98      PodName: {{ .Name }}
    99      {{- end }}
   100    {{ end }}
   101    {{- end }}
   102  `)
   103  	if err != nil {
   104  		panic(err)
   105  	}
   106  	t = template.Must(t, err)
   107  	err = t.Execute(common.StdOut, podNamespaceStatusList)
   108  	if err != nil {
   109  		logrus.Errorf("pod checkers template can not execute %s", err)
   110  		return err
   111  	}
   112  	return nil
   113  }
   114  
   115  func getPodReadyStatus(pod corev1.Pod) error {
   116  	for _, condition := range pod.Status.Conditions {
   117  		if condition.Type == "Ready" {
   118  			if condition.Status == "True" {
   119  				return nil
   120  			}
   121  		}
   122  	}
   123  	return &NotFindReadyTypeError{}
   124  }
   125  
   126  func NewPodChecker() Interface {
   127  	return &PodChecker{}
   128  }