github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/checker/node_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 "fmt" 19 "text/template" 20 21 corev1 "k8s.io/api/core/v1" 22 23 "github.com/sirupsen/logrus" 24 25 "github.com/sealerio/sealer/common" 26 "github.com/sealerio/sealer/pkg/client/k8s" 27 v2 "github.com/sealerio/sealer/types/api/v2" 28 ) 29 30 const ( 31 ReadyNodeStatus = "Ready" 32 NotReadyNodeStatus = "NotReady" 33 ) 34 35 type NodeChecker struct { 36 client *k8s.Client 37 } 38 39 type NodeClusterStatus struct { 40 ReadyCount uint32 41 NotReadyCount uint32 42 NodeCount uint32 43 NotReadyNodeList []string 44 } 45 46 func (n *NodeChecker) Check(cluster *v2.Cluster, phase string) error { 47 if phase != PhasePost { 48 return nil 49 } 50 // checker if all the node is ready 51 c, err := k8s.NewK8sClient() 52 if err != nil { 53 return err 54 } 55 n.client = c 56 nodes, err := n.client.ListNodes() 57 if err != nil { 58 return err 59 } 60 var notReadyNodeList []string 61 var readyCount uint32 62 var nodeCount uint32 63 var notReadyCount uint32 64 for _, node := range nodes.Items { 65 nodeIP, nodePhase := getNodeStatus(node) 66 if nodePhase != ReadyNodeStatus { 67 notReadyCount++ 68 notReadyNodeList = append(notReadyNodeList, nodeIP) 69 } else { 70 readyCount++ 71 } 72 } 73 nodeCount = notReadyCount + readyCount 74 nodeClusterStatus := NodeClusterStatus{ 75 ReadyCount: readyCount, 76 NotReadyCount: notReadyCount, 77 NodeCount: nodeCount, 78 NotReadyNodeList: notReadyNodeList, 79 } 80 err = n.Output(nodeClusterStatus) 81 if err != nil { 82 return err 83 } 84 if notReadyCount != 0 { 85 return fmt.Errorf("check node %v not ready", notReadyNodeList) 86 } 87 return nil 88 } 89 90 func (n *NodeChecker) Output(nodeCLusterStatus NodeClusterStatus) error { 91 //t1, err := template.ParseFiles("templates/node_checker.tpl") 92 t := template.New("node_checker") 93 t, err := t.Parse( 94 `Cluster Node Status 95 ReadyNode: {{ .ReadyCount }}/{{ .NodeCount }} 96 {{ if (gt .NotReadyCount 0 ) -}} 97 Not Ready Node List: 98 {{- range .NotReadyNodeList }} 99 NodeIP: {{ . }} 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, nodeCLusterStatus) 108 if err != nil { 109 logrus.Errorf("failed to execute node checkers template: %s", err) 110 return err 111 } 112 return nil 113 } 114 115 func getNodeStatus(node corev1.Node) (IP string, Phase string) { 116 if len(node.Status.Addresses) < 1 { 117 return "", "" 118 } 119 for _, address := range node.Status.Addresses { 120 if address.Type == "InternalIP" { 121 IP = address.Address 122 } 123 } 124 if IP == "" { 125 IP = node.Status.Addresses[0].Address 126 } 127 Phase = NotReadyNodeStatus 128 for _, condition := range node.Status.Conditions { 129 if condition.Type == ReadyNodeStatus { 130 if condition.Status == "True" { 131 Phase = ReadyNodeStatus 132 } else { 133 Phase = NotReadyNodeStatus 134 } 135 } 136 } 137 return IP, Phase 138 } 139 140 func NewNodeChecker() Interface { 141 return &NodeChecker{} 142 }