golang实现kubectl apply和kubectl delete

如何使用golang在docker内或集群内实现kubectl apply -fkubectl delete -f命令?在网上找了一圈没找到,自己研究了下。

package main

import (
	"bytes"
	"context"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	appsv1 "k8s.io/api/apps/v1"
	apiv1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/yaml"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"strings"
)

const (
	Create = "create"
	Delete = "delete"
)

type yamlItem struct {
	APIVersion string      `json:"apiVersion"`
	Kind       string      `json:"kind"`
	MetaData   interface{} `json:"metadata"`
}


var RestClient *kubernetes.Clientset

func Init() {

	var kubeConfig = "./config"
	config, err := clientcmd.BuildConfigFromFlags("192.168.101.4:443", kubeConfig)
	if err != nil {
		panic(err.Error())
	}
	RestClient, err = kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("RestClient: %v", RestClient)
}

func HandleStatefulSet(config *appsv1.StatefulSet, operation string) error {
	ns := "default"
	if config.Namespace != "" {
		ns = config.Namespace
	}
	var err error
	client := RestClient.AppsV1().StatefulSets(ns)
	switch operation {
	case Create:
		_, err = client.Create(context.Background(), config, metav1.CreateOptions{})
	case Delete:
		err = client.Delete(context.Background(), config.Name, metav1.DeleteOptions{})
	}
	if err == nil {
		fmt.Printf("%s service name: %s, namespace: %s", operation, config.Name, ns)
	}
	return err
}

func HandleService(config *apiv1.Service, operation string) error {
	ns := "default"
	if config.Namespace != "" {
		ns = config.Namespace
	}
	var err error
	client := RestClient.CoreV1().Services(ns)
	switch operation {
	case Create:
		_, err = client.Create(context.Background(), config, metav1.CreateOptions{})
	case Delete:
		err = client.Delete(context.Background(), config.Name, metav1.DeleteOptions{})
	}
	if err == nil {
		fmt.Printf("%s service name: %s, namespace: %s", operation, config.Name, ns)
	}
	return err
}

func HandleDeployment(config *appsv1.Deployment, operation string) error {
	ns := "default"
	if config.Namespace != "" {
		ns = config.Namespace
	}
	var err error
	client := RestClient.AppsV1().Deployments(ns)
	switch operation {
	case Create:
		_, err = client.Create(context.Background(), config, metav1.CreateOptions{})
	case Delete:
		err = client.Delete(context.Background(), config.Name, metav1.DeleteOptions{})
	}
	if err == nil {
		fmt.Printf("%s deployment name: %s, namespace: %s", operation, config.Name, ns)
	}
	return err
}

func HandleConfigMap(config *apiv1.ConfigMap, operation string) error {
	ns := "default"
	if config.Namespace != "" {
		ns = config.Namespace
	}
	var err error
	client := RestClient.CoreV1().ConfigMaps(ns)
	switch operation {
	case Create:
		_, err = client.Create(context.Background(), config, metav1.CreateOptions{})
	case Delete:
		err = client.Delete(context.Background(), config.Name, metav1.DeleteOptions{})
	}
	if err == nil {
		fmt.Printf("%s configMap name: %s, namespace: %s", operation, config.Name, ns)
	}
	return err
}

func HandleAppConfig(path string) ([]interface{}, error) {
	configs := make([]interface{}, 0)
	fileByte, err := ioutil.ReadFile(path)
	items := strings.Split(string(fileByte), "---")
	if err != nil {
		return nil, err
	}
	for _, item := range items {
		if item == "" {
			continue
		}
		var y yamlItem
		dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(item)), 10000)
		if err := dec.Decode(&y); err != nil {
			return nil, err
		}
		switch y.Kind {
		case "StatefulSet":
			statefulSetSchema := &appsv1.StatefulSet{}
			dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(item)), 1000)
			if err := dec.Decode(&statefulSetSchema); err != nil {
				return nil, err
			}
			configs = append(configs, statefulSetSchema)
		case "Service":
			serviceSchema := &apiv1.Service{}
			dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(item)), 1000)
			if err := dec.Decode(&serviceSchema); err != nil {
				return nil, err
			}
			configs = append(configs, serviceSchema)
		case "ConfigMap":
			configMapSchema := &apiv1.ConfigMap{}
			dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(item)), 1000)
			if err := dec.Decode(&configMapSchema); err != nil {
				return nil, err
			}
			configs = append(configs, configMapSchema)
		case "Deployment":
			deploymentSchema := &appsv1.Deployment{}
			dec := yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(item)), 1000)
			if err := dec.Decode(&deploymentSchema); err != nil {
				return nil, err
			}
			configs = append(configs, deploymentSchema)
		}
	}
	return configs, nil
}

// operation指操作类型,delete or create
func HandleK8sApp(path string, operation string) error {
	var err error
	if RestClient == nil {
		return errors.New("RestClient is nil")
	}
	configs, err := HandleAppConfig(path)
	if err != nil {
		return err
	}

	for _, item := range configs {
		switch item.(type){
		case *appsv1.StatefulSet:
			err = HandleStatefulSet(item.(*appsv1.StatefulSet), operation)
		case *apiv1.Service:
			err = HandleService(item.(*apiv1.Service), operation)
		case *apiv1.ConfigMap:
			err = HandleConfigMap(item.(*apiv1.ConfigMap), operation)
		case *appsv1.Deployment:
			err = HandleDeployment(item.(*appsv1.Deployment), operation)
		}
	}
	return err
}

func main() {
	var n string
	Init() //初始化k8s client
	flag.StringVar(&n, "operation", "create", "操作")
	if n == Create {
		err := HandleK8sApp("adapter.yaml", Create)
		if err != nil {
			fmt.Println(err)
		}
	}else {
		err := HandleK8sApp("adapter.yaml", Delete)
		if err != nil {
			fmt.Println(err)
		}
	}
}

最后附上实现kubectl get pod -o wide的代码:


func HandleListPod() ([][]interface{}, error) {
	var err error
	podList := make([][]interface{}, 0)
	podList = append(podList, []interface{}{"NAME", "READY", "STATUS", "RESTARTS", "AGE", "IP", "NODE", "NOMINATED NODE", "READINESS GATES"})
	if RestClient == nil {
		return nil, errors.New("RestClient is nil")
	}
	pods, err := RestClient.CoreV1().Pods("default").List(context.Background(), metav1.ListOptions{})
	if err != nil {
		log.Errorf("Get pod err: %s", err.Error())
		return nil, err
	}
	for _, pod := range pods.Items {
		var readinessGates  interface{}
		nominatedNodeName := ""
		restartCount := 0
		readyCount := 0
		for _, status := range pod.Status.ContainerStatuses {
			restartCount += int(status.RestartCount)
			if status.Ready {
				//fmt.Println(count.State.Running.StartedAt.UnixNano())
				readyCount ++
			}
		}
		if pod.Spec.ReadinessGates == nil {
			readinessGates = "<none>"
		}else {
			readinessGates = pod.Spec.ReadinessGates
		}
		if pod.Status.NominatedNodeName == "" {
			pod.Status.NominatedNodeName = "<none>"
		}
		if pod.Status.PodIP == "" {
			pod.Status.PodIP = "<node>"
		}
		if pod.Spec.NodeName == "" {
			pod.Spec.NodeName = "<node>"
		}
		var startTime int64
		if pod.Status.StartTime == nil {
			startTime = pod.CreationTimestamp.Unix()
		}else {
			startTime = pod.Status.StartTime.Unix()
		}
		podList = append(podList, []interface{}{
			pod.Name, fmt.Sprintf("%d/%d", readyCount, len(pod.Status.ContainerStatuses)),
			string(pod.Status.Phase), strconv.Itoa(restartCount), handleTimeTrans(time.Now().Unix()-
				startTime), pod.Status.PodIP, pod.Spec.NodeName, readinessGates,
			nominatedNodeName,
		})
	}
	return podList, nil
}


func handleTimeTrans(timeDiff int64) string {
	if timeDiff < 60 {
		return fmt.Sprintf("%ds", timeDiff)
	}
	if timeDiff < 3600 {
		return fmt.Sprintf("%dm%ds", timeDiff / 60, 320 % 60)
	}
	if timeDiff < 3600 * 24 {
		return fmt.Sprintf("%dh%dm", timeDiff / 3600, (timeDiff % 3600) / 60)
	}
	return fmt.Sprintf("%dd%dh", timeDiff / (3600 * 24), (timeDiff % (3600 * 24)) / 3600)
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值