github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/client/k8s/client.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 k8s 16 17 import ( 18 "context" 19 "path/filepath" 20 21 "github.com/pkg/errors" 22 v1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/version" 25 "k8s.io/client-go/kubernetes" 26 "k8s.io/client-go/tools/clientcmd" 27 "k8s.io/client-go/util/homedir" 28 29 "github.com/alibaba/sealer/common" 30 ) 31 32 type Client struct { 33 client *kubernetes.Clientset 34 } 35 36 type NamespacePod struct { 37 Namespace v1.Namespace 38 PodList *v1.PodList 39 } 40 41 type NamespaceSvc struct { 42 Namespace v1.Namespace 43 ServiceList *v1.ServiceList 44 } 45 46 func Newk8sClient() (*Client, error) { 47 kubeconfig := filepath.Join(common.DefaultKubeConfigDir(), "config") 48 if home := homedir.HomeDir(); home != "" { 49 kubeconfig = filepath.Join(home, ".kube", "config") 50 } 51 52 // use the current context in kubeconfig 53 config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) 54 if err != nil { 55 return nil, errors.Wrap(err, "failed to build kube config") 56 } 57 58 clientSet, err := kubernetes.NewForConfig(config) 59 if err != nil { 60 return nil, err 61 } 62 63 return &Client{ 64 client: clientSet, 65 }, nil 66 } 67 68 func (c *Client) ListNodes() (*v1.NodeList, error) { 69 nodes, err := c.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) 70 if err != nil { 71 return nil, errors.Wrapf(err, "failed to get cluster nodes") 72 } 73 return nodes, nil 74 } 75 76 func (c *Client) UpdateNode(node v1.Node) (*v1.Node, error) { 77 n, err := c.client.CoreV1().Nodes().Update(context.TODO(), &node, metav1.UpdateOptions{}) 78 if err != nil { 79 return nil, errors.Wrapf(err, "failed to update cluster node") 80 } 81 return n, nil 82 } 83 84 func (c *Client) DeleteNode(name string) error { 85 if err := c.client.CoreV1().Nodes().Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil { 86 return errors.Wrapf(err, "failed to delete cluster node %s", name) 87 } 88 return nil 89 } 90 91 func (c *Client) listNamespaces() (*v1.NamespaceList, error) { 92 namespaceList, err := c.client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) 93 if err != nil { 94 return nil, errors.Wrapf(err, "failed to get namespaces") 95 } 96 return namespaceList, nil 97 } 98 99 func (c *Client) ListNodesByLabel(label string) (*v1.NodeList, error) { 100 nodes, err := c.client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: label}) 101 if err != nil { 102 return nil, errors.Wrapf(err, "failed to get cluster nodes") 103 } 104 return nodes, nil 105 } 106 107 func (c *Client) ListNodeIPByLabel(label string) ([]string, error) { 108 var ips []string 109 nodes, err := c.ListNodesByLabel(label) 110 if err != nil { 111 return nil, err 112 } 113 for _, node := range nodes.Items { 114 for _, v := range node.Status.Addresses { 115 if v.Type == v1.NodeInternalIP { 116 ips = append(ips, v.Address) 117 } 118 } 119 } 120 return ips, nil 121 } 122 123 func (c *Client) ListAllNamespacesPods() ([]*NamespacePod, error) { 124 namespaceList, err := c.listNamespaces() 125 if err != nil { 126 return nil, err 127 } 128 var namespacePodList []*NamespacePod 129 for _, ns := range namespaceList.Items { 130 pods, err := c.client.CoreV1().Pods(ns.Name).List(context.TODO(), metav1.ListOptions{}) 131 if err != nil { 132 return nil, errors.Wrapf(err, "failed to get all namespace pods") 133 } 134 namespacePod := NamespacePod{ 135 Namespace: ns, 136 PodList: pods, 137 } 138 namespacePodList = append(namespacePodList, &namespacePod) 139 } 140 141 return namespacePodList, nil 142 } 143 144 func (c *Client) ListAllNamespacesSvcs() ([]*NamespaceSvc, error) { 145 namespaceList, err := c.listNamespaces() 146 if err != nil { 147 return nil, err 148 } 149 var namespaceSvcList []*NamespaceSvc 150 for _, ns := range namespaceList.Items { 151 svcs, err := c.client.CoreV1().Services(ns.Name).List(context.TODO(), metav1.ListOptions{}) 152 if err != nil { 153 return nil, errors.Wrapf(err, "failed to get all namespace pods") 154 } 155 namespaceSvc := NamespaceSvc{ 156 Namespace: ns, 157 ServiceList: svcs, 158 } 159 namespaceSvcList = append(namespaceSvcList, &namespaceSvc) 160 } 161 return namespaceSvcList, nil 162 } 163 164 func (c *Client) GetEndpointsList(namespace string) (*v1.EndpointsList, error) { 165 endpointsList, err := c.client.CoreV1().Endpoints(namespace).List(context.TODO(), metav1.ListOptions{}) 166 if err != nil { 167 return nil, errors.Wrapf(err, "failed to get endpoint in namespace %s", namespace) 168 } 169 return endpointsList, nil 170 } 171 172 func (c *Client) ListSvcs(namespace string) (*v1.ServiceList, error) { 173 svcs, err := c.client.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{}) 174 if err != nil { 175 return nil, errors.Wrapf(err, "failed to get all namespace pods") 176 } 177 return svcs, nil 178 } 179 180 func (c *Client) GetClusterVersion() (*version.Info, error) { 181 info, err := c.client.Discovery().ServerVersion() 182 if err != nil { 183 return nil, err 184 } 185 return info, nil 186 } 187 188 func (c *Client) ListKubeSystemPodsStatus() (bool, error) { 189 pods, err := c.client.CoreV1().Pods("kube-system").List(context.TODO(), metav1.ListOptions{}) 190 if err != nil { 191 return false, errors.Wrapf(err, "failed to get kube-system namespace pods") 192 } 193 // pods.Items maybe nil 194 if len(pods.Items) == 0 { 195 return false, nil 196 } 197 for _, pod := range pods.Items { 198 // pod.Status.ContainerStatus == nil because of pod contain initcontainer 199 if len(pod.Status.ContainerStatuses) == 0 { 200 continue 201 } 202 if !pod.Status.ContainerStatuses[0].Ready { 203 return false, nil 204 } 205 } 206 return true, nil 207 }