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  }