From 62aacec7bb21854e26cf619e49a9a0e533e5c10f Mon Sep 17 00:00:00 2001 From: cheliequan <liequanche@126.com> Date: 星期一, 22 五月 2023 14:17:19 +0800 Subject: [PATCH] 创建、删除和测试函数在一个文件中 --- src/main/main.go | 523 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 523 insertions(+), 0 deletions(-) diff --git a/src/main/main.go b/src/main/main.go new file mode 100644 index 0000000..006d1a5 --- /dev/null +++ b/src/main/main.go @@ -0,0 +1,523 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "math/rand" + "os" + "path/filepath" + "time" + + appsv1 "k8s.io/api/apps/v1" + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" +) + +var ( + replicas int32 = 3 + port int32 = 9081 + usedNodePorts = make(map[int32]bool) + namespaces = []string{"guangsheng", "geruimi", "tongsheng"} +) + +func main() { + createCmd := flag.NewFlagSet("create", flag.ExitOnError) + deleteCmd := flag.NewFlagSet("delete", flag.ExitOnError) + testCmd := flag.NewFlagSet("test", flag.ExitOnError) + + createNamespace := createCmd.String("ns", "", "Namespace name") + createDeployment := createCmd.String("deployment", "", "Deployment name") + createService := createCmd.String("service", "", "Service name") + + deleteNamespace := deleteCmd.String("ns", "", "Namespace name") + deleteDeployment := deleteCmd.String("deployment", "", "Deployment name") + deleteService := deleteCmd.String("service", "", "Service name") + + if len(os.Args) < 2 { + fmt.Println("create/delete/test command is required") + os.Exit(1) + } + + switch os.Args[1] { + case "create": + createCmd.Parse(os.Args[2:]) + case "delete": + deleteCmd.Parse(os.Args[2:]) + case "test": + testCmd.Parse(os.Args[2:]) + default: + flag.PrintDefaults() + os.Exit(1) + } + + // 閰嶇疆 Kubernetes 闆嗙兢鐨� kubeconfig 璺緞 + kubeconfig := flag.String("kubeconfig", filepath.Join(homeDir(), ".kube", "config"), "kubeconfig file") + flag.Parse() + + // 鍒涘缓 Kubernetes 瀹㈡埛绔� + config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) + if err != nil { + panic(err.Error()) + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) + } + + // 鎵ц create 鍛戒护 + if createCmd.Parsed() { + if *createNamespace == "" || *createDeployment == "" || *createService == "" { + fmt.Println("Namespace, Deployment, and Service names are required") + createCmd.PrintDefaults() + os.Exit(1) + } + + err := CreateDeploymentAndService(clientset, *createNamespace, *createDeployment, *createService) + if err != nil { + panic(err) + } + + nodeport, err := GetServiceNodePort(clientset, *createNamespace, *createService) + if err != nil { + panic(err) + } + + log.Printf("Service NodePort: %d\n", nodeport) + } + + // 鎵ц delete 鍛戒护 + if deleteCmd.Parsed() { + if *deleteNamespace == "" || *deleteDeployment == "" || *deleteService == "" { + fmt.Println("Namespace, Deployment, and Service names are required") + deleteCmd.PrintDefaults() + os.Exit(1) + } + + err := DeleteResources(clientset, *deleteNamespace, *deleteDeployment, *deleteService) + if err != nil { + panic(err) + } + + fmt.Println("Resources deleted.") + } + + // 鎵ц鍒涘缓鍜屽垹闄ゆ祴璇� + if testCmd.Parsed() { + fmt.Println("\033[97;40mRunning create and delete tests...\033[0m") + + // 鍒涘缓娴嬭瘯 + fmt.Println("\033[97;40m--- Create Test ---\033[0m") + for _, ns := range namespaces { + deploymentName := ns + serviceName := ns + err := CreateDeploymentAndService(clientset, ns, deploymentName, serviceName) + if err != nil { + log.Printf("\033[97;41mFailed to create resources in namespace %s: %v\033[0m\n", ns, err) + } else { + nodeport, err := GetServiceNodePort(clientset, ns, ns) + if err != nil { + panic(err) + } + + log.Printf("Service NodePort: %d\n", nodeport) + log.Printf("\033[97;42mSuccessfully created resources in namespace %s\033[0m\n", ns) + } + } + + // 寤惰繜 1000 绉掑悗鍒犻櫎鍒涘缓鐨勮祫婧� + time.Sleep(1000 * time.Second) + + // 鍒犻櫎娴嬭瘯 + fmt.Println("\033[97;40m--- Delete Test ---\033[0m") + + // 鍒犻櫎澶氫釜 Namespace 涓嬬殑鐩稿悓鍚嶇О鐨� Deployment 鍜� Service + for _, ns := range namespaces { + err = DeleteResources(clientset, ns, ns, ns) + if err != nil { + panic(err) + } + } + + fmt.Println("Resources deleted.") + } + +} + +// CheckAndDeleteResources 妫�娴嬪苟鍒犻櫎鎸囧畾鐨� Namespace銆丏eployment 鍜� Service +func CheckAndDeleteResources(clientset *kubernetes.Clientset, namespace, deploymentName, serviceName string) error { + fmt.Println("\033[1;37;40mChecking and deleting resources in Namespace:", namespace, "\033[0m") + + // 妫�鏌ュ苟鍒犻櫎 Deployment + err := deleteDeploymentIfExists(clientset, namespace, deploymentName) + if err != nil { + return err + } + + // 妫�鏌ュ苟鍒犻櫎 Service + err = deleteServiceIfExists(clientset, namespace, serviceName) + if err != nil { + return err + } + + return nil +} + +// deleteDeploymentIfExists 妫�鏌ュ苟鍒犻櫎鎸囧畾鐨� Deployment锛堝鏋滃瓨鍦級 +func deleteDeploymentIfExists(clientset *kubernetes.Clientset, namespace, deploymentName string) error { + fmt.Println("\033[1;37;40mChecking and deleting Deployment:", deploymentName, "\033[0m") + + err := clientset.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Printf("Deployment %s not found in Namespace %s\n", deploymentName, namespace) + } else { + return fmt.Errorf("failed to delete Deployment: %v", err) + } + } else { + fmt.Printf("Deployment %s deleted from Namespace %s\n", deploymentName, namespace) + } + + return nil +} + +// deleteServiceIfExists 妫�鏌ュ苟鍒犻櫎鎸囧畾鐨� Service锛堝鏋滃瓨鍦級 +func deleteServiceIfExists(clientset *kubernetes.Clientset, namespace, serviceName string) error { + fmt.Println("\033[1;37;40mChecking and deleting Service:", serviceName, "\033[0m") + + err := clientset.CoreV1().Services(namespace).Delete(context.TODO(), serviceName, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Printf("Service %s not found in Namespace %s\n", serviceName, namespace) + } else { + return fmt.Errorf("failed to delete Service: %v", err) + } + } else { + fmt.Printf("Service %s deleted from Namespace %s\n", serviceName, namespace) + } + + return nil +} + +func CreateDeploymentAndService(clientset *kubernetes.Clientset, namespace, deploymentName, serviceName string) error { + fmt.Println("\033[1;37;40mCreating resources in Namespace:", namespace, "\033[0m") + + // 妫�娴嬪苟鍒犻櫎宸插瓨鍦ㄧ殑 Deployment 鍜� Service + err := CheckAndDeleteResources(clientset, namespace, deploymentName, serviceName) + if err != nil { + return err + } + + // 鍒涘缓 Namespace + err = createNamespace(clientset, namespace) + if err != nil { + return err + } + + // 鍒涘缓 Deployment + err = createDeployment(clientset, namespace, deploymentName) + if err != nil { + return err + } + + // 鍒涘缓 Service + err = createService(clientset, namespace, serviceName) + if err != nil { + return err + } + + return nil +} + +// createNamespace 鍒涘缓鎸囧畾鐨� Namespace +func createNamespace(clientset *kubernetes.Clientset, namespace string) error { + log.Printf("Creating Namespace: %s\n", namespace) + + ns := &apiv1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + + _, err := clientset.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{}) + if err != nil { + if !errors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create Namespace: %w", err) + } + log.Printf("Namespace %s already exists\n", namespace) + } else { + log.Printf("Namespace %s created\n", namespace) + } + + return nil +} + +func createDeployment(clientset *kubernetes.Clientset, namespace, deploymentName string) error { + fmt.Println("\033[1;37;40mCreating Deployment:", deploymentName, "\033[0m") + + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: deploymentName, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "cid": namespace, + }, + }, + Template: apiv1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "cid": namespace, + }, + }, + Spec: apiv1.PodSpec{ + TopologySpreadConstraints: []apiv1.TopologySpreadConstraint{ + { + MaxSkew: 1, + TopologyKey: "kubernetes.io/hostname", + WhenUnsatisfiable: apiv1.DoNotSchedule, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "cid": namespace, + }, + }, + }, + }, + Containers: []apiv1.Container{ + { + Name: namespace, + Image: "192.168.20.119/apsserver/apsserver:v0.2", + Env: []apiv1.EnvVar{ + { + Name: "NODE_ID", + Value: namespace, + }, + }, + }, + }, + }, + }, + }, + } + + _, err := clientset.AppsV1().Deployments(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{}) + if err != nil { + if !errors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create Deployment: %v", err) + } + fmt.Printf("Deployment %s already exists in Namespace %s\n", deploymentName, namespace) + } else { + fmt.Printf("Deployment %s created in Namespace %s\n", deploymentName, namespace) + } + + return nil +} + +// createService 鍒涘缓鎸囧畾鐨� Service +func createService(clientset *kubernetes.Clientset, namespace, serviceName string) error { + fmt.Println("\033[1;37;40mCreating Service:", serviceName, "\033[0m") + + nodePort, err := getRandomNodePort(clientset) + if err != nil { + return err + } + + service := &apiv1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + }, + Spec: apiv1.ServiceSpec{ + Selector: map[string]string{ + "cid": namespace, + }, + Type: apiv1.ServiceTypeNodePort, + Ports: []apiv1.ServicePort{ + { + Name: "http", + Protocol: apiv1.ProtocolTCP, + Port: port, + TargetPort: intstr.FromInt(int(port)), + NodePort: nodePort, + }, + }, + }, + } + + _, err = clientset.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) + if err != nil { + if !errors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create Service: %v", err) + } + fmt.Printf("Service %s already exists in Namespace %s\n", serviceName, namespace) + } else { + fmt.Printf("Service %s created in Namespace %s\n", serviceName, namespace) + } + + return nil +} + +// getRandomNodePort 鑾峰彇涓�涓湭浣跨敤鐨勯殢鏈� NodePort +func getRandomNodePort(clientset *kubernetes.Clientset) (int32, error) { + // 鑾峰彇涓�涓殢鏈虹殑 NodePort + nodePort := int32(0) + for { + // 鐢熸垚涓�涓殢鏈虹殑 NodePort + nodePort = generateRandomNodePort() + + // 妫�鏌ヨ NodePort 鏄惁宸茶浣跨敤 + used, err := isNodePortUsed(clientset, nodePort) + if err != nil { + return 0, err + + } + + // 濡傛灉鏈浣跨敤锛屽垯鏍囪涓哄凡浣跨敤锛屽苟閫�鍑哄惊鐜� + if !used { + usedNodePorts[nodePort] = true + break + } + } + + return nodePort, nil +} + +// generateRandomNodePort 鐢熸垚涓�涓殢鏈虹殑 NodePort +func generateRandomNodePort() int32 { + // 鍦ㄨ寖鍥� 30000-32767 涓敓鎴愰殢鏈烘暟浣滀负 NodePort + return int32(rand.Intn(32767-30000+1) + 30000) +} + +// isNodePortUsed 妫�鏌ユ寚瀹氱殑 NodePort 鏄惁宸茶浣跨敤 +func isNodePortUsed(clientset *kubernetes.Clientset, nodePort int32) (bool, error) { + // 鑾峰彇鎵�鏈� Service + services, err := clientset.CoreV1().Services("").List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return false, err + } + + // 妫�鏌ユ瘡涓� Service 鐨� NodePort 鏄惁涓庢寚瀹氱殑 NodePort 鐩稿悓 + for _, svc := range services.Items { + for _, port := range svc.Spec.Ports { + if port.NodePort == nodePort { + return true, nil + } + } + } + + return false, nil +} + +// DeleteResources 鍒犻櫎鎸囧畾鐨� Namespace銆丏eployment 鍜� Service +func DeleteResources(clientset *kubernetes.Clientset, namespace, deploymentName, serviceName string) error { + fmt.Println("\033[1;37;40mDeleting resources in Namespace:", namespace, "\033[0m") + + // 鍒犻櫎 Deployment + err := deleteDeployment(clientset, namespace, deploymentName) + if err != nil { + return err + } + + // 鍒犻櫎 Service + err = deleteService(clientset, namespace, serviceName) + if err != nil { + return err + } + + // 鍒犻櫎 Namespace + err = deleteNamespace(clientset, namespace) + if err != nil { + return err + } + + return nil +} + +// deleteDeployment 鍒犻櫎鎸囧畾鐨� Deployment +func deleteDeployment(clientset *kubernetes.Clientset, namespace, deploymentName string) error { + fmt.Println("\033[1;37;40mDeleting Deployment:", deploymentName, "\033[0m") + + err := clientset.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Printf("Deployment %s not found in Namespace %s\n", deploymentName, namespace) + } else { + return fmt.Errorf("failed to delete Deployment: %v", err) + } + } else { + fmt.Printf("Deployment %s deleted from Namespace %s\n", deploymentName, namespace) + } + + return nil +} + +// deleteService 鍒犻櫎鎸囧畾鐨� Service +func deleteService(clientset *kubernetes.Clientset, namespace, serviceName string) error { + fmt.Println("\033[1;37;40mDeleting Service:", serviceName, "\033[0m") + + err := clientset.CoreV1().Services(namespace).Delete(context.TODO(), serviceName, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Printf("Service %s not found in Namespace %s\n", serviceName, namespace) + } else { + return fmt.Errorf("failed to delete Service: %v", err) + } + } else { + fmt.Printf("Service %s deleted from Namespace %s\n", serviceName, namespace) + } + + return nil +} + +// deleteNamespace 鍒犻櫎鎸囧畾鐨� Namespace +func deleteNamespace(clientset *kubernetes.Clientset, namespace string) error { + fmt.Println("\033[1;37;40mDeleting Namespace:", namespace, "\033[0m") + + err := clientset.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Printf("Namespace %s not found\n", namespace) + } else { + return fmt.Errorf("failed to delete Namespace: %v", err) + } + } else { + fmt.Printf("Namespace %s deleted\n", namespace) + } + + return nil +} + +// homeDir 鑾峰彇褰撳墠鐢ㄦ埛鐨勫鐩綍璺緞 +func homeDir() string { + if h := os.Getenv("HOME"); h != "" { + return h + } + return os.Getenv("USERPROFILE") // Windows 鐜涓嬭幏鍙栫敤鎴风洰褰� +} + +// GetServiceNodePort 鑾峰彇鎸囧畾 Service 鐨� NodePort +func GetServiceNodePort(clientset *kubernetes.Clientset, namespace, serviceName string) (int32, error) { + svc, err := clientset.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{}) + if err != nil { + return 0, fmt.Errorf("failed to get Service: %v", err) + } + + // 妫�鏌� Service 绫诲瀷鏄惁涓� NodePort + if svc.Spec.Type != apiv1.ServiceTypeNodePort { + return 0, fmt.Errorf("Service %s is not of type NodePort", serviceName) + } + + // 鑾峰彇绗竴涓鍙g殑 NodePort + if len(svc.Spec.Ports) > 0 { + return svc.Spec.Ports[0].NodePort, nil + } + + return 0, fmt.Errorf("no ports defined for Service %s", serviceName) +} -- Gitblit v1.8.0