diff options
Diffstat (limited to 'clover/cloverctl/src/cloverkube/main.go')
-rw-r--r-- | clover/cloverctl/src/cloverkube/main.go | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/clover/cloverctl/src/cloverkube/main.go b/clover/cloverctl/src/cloverkube/main.go new file mode 100644 index 0000000..bcda990 --- /dev/null +++ b/clover/cloverctl/src/cloverkube/main.go @@ -0,0 +1,459 @@ +// Copyright (c) Authors of Clover +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Apache License, Version 2.0 +// which accompanies this distribution, and is available at +// http://www.apache.org/licenses/LICENSE-2.0 + +package cloverkube + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "io/ioutil" + "io" + "bytes" + "github.com/ghodss/yaml" + "encoding/json" + + appsv1 "k8s.io/api/apps/v1" + v1beta1 "k8s.io/api/apps/v1beta1" + v1beta1ext "k8s.io/api/extensions/v1beta1" + apiv1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +func setClient() kubernetes.Interface { + kubeconfig := filepath.Join( + os.Getenv("HOME"), ".kube", "config", + ) + config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) + if err != nil { + panic(err.Error()) + } + + // create the clientset + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) + } + return clientset +} + +// Create various K8s resources +func CreateResource(input_yaml string, resource_type string, + image string, namespace string) { + if namespace == "" { + namespace = "clover-system" + } + // Check path from cloverctl first + exe_path, err := os.Executable() + abs_input_yaml := strings.Replace(exe_path, "cloverctl", "", -1) + + "/yaml/" + input_yaml + if _, err := os.Stat(abs_input_yaml); !os.IsNotExist(err) { + input_yaml = abs_input_yaml + } + in, err := ioutil.ReadFile(input_yaml) + if err != nil { + fmt.Println("Please specify a valid manifest yaml file") + return + } + out_json, err := yaml.YAMLToJSON(in) + if err != nil { + panic(err.Error()) + } + + switch resource_type { + case "deployment": + deploy := v1beta1.Deployment{} + err = json.Unmarshal(out_json, &deploy) + deploy.Spec.Template.Spec.Containers[0].Image = image + CreateDeployment(&deploy, namespace) + fmt.Printf("Image: %s\n", + deploy.Spec.Template.Spec.Containers[0].Image) + case "service": + service := apiv1.Service{} + err = json.Unmarshal(out_json, &service) + CreateService(&service, namespace) + case "serviceaccount": + sa := apiv1.ServiceAccount{} + err = json.Unmarshal(out_json, &sa) + CreateServiceAccount(&sa, namespace) + case "clusterrolebinding": + clusterrolebinding := rbacv1.ClusterRoleBinding{} + err = json.Unmarshal(out_json, &clusterrolebinding) + CreateCRB(&clusterrolebinding) + case "statefulset": + statefulset := appsv1.StatefulSet{} + err = json.Unmarshal(out_json, &statefulset) + CreateStatefulSet(&statefulset, namespace) + case "pod": + pod := apiv1.Pod{} + err = json.Unmarshal(out_json, &pod) + CreatePod(&pod, namespace) + case "daemonset": + daemon := v1beta1ext.DaemonSet{} + err = json.Unmarshal(out_json, &daemon) + daemon.Spec.Template.Spec.Containers[0].Image = image + CreateDaemonSet(&daemon, namespace) + fmt.Printf("Image: %s\n", + daemon.Spec.Template.Spec.Containers[0].Image) + + default: + fmt.Println("No resource selected") + } +} + +// Delete K8s resources +func DeleteResource(deploy_name string, resource_type string, + namespace string) { + clientset := setClient() + deletePolicy := metav1.DeletePropagationForeground + + switch resource_type { + case "deployment": + deploymentsClient := clientset.AppsV1().Deployments(namespace) + if err := deploymentsClient.Delete(deploy_name, + &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "service": + servicesClient := clientset.CoreV1().Services(namespace) + if err := servicesClient.Delete(deploy_name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "serviceaccount": + saClient := clientset.CoreV1().ServiceAccounts(namespace) + if err := saClient.Delete(deploy_name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "clusterrolebinding": + crbClient := clientset.RbacV1().ClusterRoleBindings() + if err := crbClient.Delete(deploy_name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "statefulset": + statefulClient := clientset.AppsV1().StatefulSets(namespace) + if err := statefulClient.Delete(deploy_name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "pod": + podClient := clientset.CoreV1().Pods(namespace) + if err := podClient.Delete(deploy_name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + case "daemonset": + daemonsClient := clientset.AppsV1().DaemonSets(namespace) + if err := daemonsClient.Delete(deploy_name, + &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting %v: %v\n", resource_type, err) + return + } + } + fmt.Printf("Deleted %s %s\n", deploy_name, resource_type) +} + +// Create ServiceAccount +func CreateServiceAccount(sa *apiv1.ServiceAccount, namespace string) { + clientset := setClient() + saClient := clientset.CoreV1().ServiceAccounts(namespace) + result, err := saClient.Create(sa) + if err != nil { + fmt.Printf("Error creating serviceaccount: %v\n", err); return + } + fmt.Printf("Created serviceaccount %q.\n", + result.GetObjectMeta().GetName()) +} + +// Create ClusterRoleBinding +func CreateCRB(sa *rbacv1.ClusterRoleBinding) { + clientset := setClient() + crbClient := clientset.RbacV1().ClusterRoleBindings() + result, err := crbClient.Create(sa) + if err != nil { + fmt.Printf("Error creating clusterrolebinding: %v\n", err); return + } + fmt.Printf("Created clusterrolebinding %q.\n", + result.GetObjectMeta().GetName()) +} + +// Create DaemonSet +func CreateDaemonSet(daemonset *v1beta1ext.DaemonSet, namespace string) { + clientset := setClient() + daemonsClient := clientset.ExtensionsV1beta1().DaemonSets(namespace) + result, err := daemonsClient.Create(daemonset) + if err != nil { + fmt.Printf("Error creating daemonset: %v\n", err); return + } + fmt.Printf("Created daemonset %q.\n", result.GetObjectMeta().GetName()) +} + +// Create Deployment +func CreateDeployment(deployment *v1beta1.Deployment, namespace string) { + clientset := setClient() + deploymentsClient := clientset.AppsV1beta1().Deployments(namespace) + result, err := deploymentsClient.Create(deployment) + if err != nil { + fmt.Printf("Error creating deployment: %v\n", err); return + } + fmt.Printf("Created deployment %q.\n", result.GetObjectMeta().GetName()) +} + +// Create StatefulSet +func CreateStatefulSet(statefulset *appsv1.StatefulSet, namespace string) { + clientset := setClient() + statefulsetClient := clientset.AppsV1().StatefulSets(namespace) + result, err := statefulsetClient.Create(statefulset) + if err != nil { + fmt.Printf("Error creating statefulset: %v\n", err); return + } + fmt.Printf("Created statefulset %q.\n", result.GetObjectMeta().GetName()) +} + +// Create Pod +func CreatePod(pod *apiv1.Pod, namespace string) { + clientset := setClient() + podClient := clientset.CoreV1().Pods(namespace) + result, err := podClient.Create(pod) + if err != nil { + fmt.Printf("Error creating pod: %v\n", err); return + panic(err) + } + fmt.Printf("Created pod %q.\n", result.GetObjectMeta().GetName()) +} + +// Create Service +func CreateService(service *apiv1.Service, namespace string) { + clientset := setClient() + servicesClient := clientset.CoreV1().Services(namespace) + + result1, err := servicesClient.Create(service) + if err != nil { + fmt.Printf("Error creating service: %v\n", err); return + } + fmt.Printf("Created service %q\n", result1.GetObjectMeta().GetName()) +} + +// Create or delete namespace +func ConfigNamespace (name string, action string) { + clientset := setClient() + nameClient := clientset.CoreV1().Namespaces() + + if action == "create" { + namespace := &apiv1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + nameClient.Create(namespace) + fmt.Printf("Created %s namespace\n", name) + } else if action == "delete" { + deletePolicy := metav1.DeletePropagationForeground + if err := nameClient.Delete(name, &metav1.DeleteOptions{ + PropagationPolicy: &deletePolicy, + }); err != nil { + fmt.Printf("Error deleting namespace: %v\n", err); return + } + fmt.Printf("Deleted %s namespace\n", name) + } +} + +func GetServices() *apiv1.ServiceList { + + clientset := setClient() + services, err := clientset.Core().Services("").List(metav1.ListOptions{}) + for _, service := range services.Items { + if err != nil { + panic(err.Error()) + } + fmt.Printf(" * SERVICE Name: %s\n", service.GetName()) + fmt.Printf("Kind: %s\n", service.Kind) + fmt.Printf("Labels: %s\n", service.GetLabels()) + fmt.Printf("Type: %s\n", service.Spec.Type) + fmt.Printf("Cluster IP: %s\n", service.Spec.ClusterIP) + + for _, port := range service.Spec.Ports { + fmt.Printf("Port Name: %s, Port# %d, NodePort: %d\n", + port.Name, port.Port, port.NodePort) + } + for _, ip := range service.Status.LoadBalancer.Ingress { + fmt.Printf("LB IP: %s \n", ip.IP) + } + } + return services +} + +func GetDeployments(namespace string) []appsv1.Deployment { + clientset := setClient() + + deploymentsClient := clientset.AppsV1().Deployments(namespace) + list, err := deploymentsClient.List(metav1.ListOptions{}) + if err != nil { + panic(err) + } + for _, d := range list.Items { + fmt.Printf(" * %s (%d replicas)\n", d.Name, *d.Spec.Replicas) + } + return list.Items +} + +func GetServicesPortIP(service_name string) (int32, string) { + clientset := setClient() + services, err := clientset.Core().Services("").List(metav1.ListOptions{}) + var nodeport int32 + var ipaddress string + nodeport = 0 + ipaddress = "" + for _, service := range services.Items { + if err != nil { + panic(err.Error()) + } + if service.GetName() == service_name { + for _, port := range service.Spec.Ports { + if port.NodePort > 0 { + nodeport = port.NodePort + } + } + for _, ip := range service.Status.LoadBalancer.Ingress { + ipaddress = ip.IP + } + } + } + return nodeport, ipaddress +} + +func GetPodsIP(pod_name string, namespace string) []string { + + clientset := setClient() + + var ips []string + pods, err := clientset.CoreV1().Pods(namespace).List(metav1.ListOptions{}) + if err != nil { + panic(err) + } + for _, pod := range pods.Items { + if strings.Contains(pod.Name, pod_name) { + fmt.Println(pod.Name, pod.Status.PodIP) + ips = append(ips, pod.Status.PodIP) + } + } + + return ips +} + +func CopyFileToPod(src, dest string) error { + + // dest must be "namespace/podname/containername:<your path>" + pSplit := strings.Split(dest, ":") + pathPrefix := pSplit[0] + pathToCopy := pSplit[1] + + buffer, err := ioutil.ReadFile(src) + if err != nil { + fmt.Print(err) + } + + dir, _ := filepath.Split(pathToCopy) + command := "mkdir -p " + dir + _, stderr, err := Exec(pathPrefix, command, nil) + + if err != nil { + fmt.Print(err) + fmt.Print(stderr) + return err + } + + command = "cp /dev/stdin " + pathToCopy + stdin := bytes.NewReader(buffer) + _, stderr, err = Exec(pathPrefix, command, stdin) + + if err != nil { + fmt.Print(err) + fmt.Print(stderr) + return err + } + + return nil +} + + +func Exec(pathPrefix, command string, stdin io.Reader) ([]byte, []byte, error) { + clientset := setClient() + kubeconfig := filepath.Join( + os.Getenv("HOME"), ".kube", "config", + ) + config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) + if err != nil { + panic(err.Error()) + } + + prefixSplit := strings.Split(pathPrefix, "/") + namespace := prefixSplit[0] + podName := prefixSplit[1] + containerName := prefixSplit[2] + + req := clientset.Core().RESTClient().Post(). + Resource("pods"). + Name(podName). + Namespace(namespace). + SubResource("exec") + scheme := runtime.NewScheme() + if err := apiv1.AddToScheme(scheme); err != nil { + return nil, nil, fmt.Errorf("error adding to scheme: %v", err) + } + + parameterCodec := runtime.NewParameterCodec(scheme) + req.VersionedParams(&apiv1.PodExecOptions{ + Command: strings.Fields(command), + Container: containerName, + Stdin: stdin != nil, + Stdout: true, + Stderr: true, + TTY: false, + }, parameterCodec) + + exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) + if err != nil { + return nil, nil, fmt.Errorf("error while creating Executor: %v", err) + } + + var stdout, stderr bytes.Buffer + err = exec.Stream(remotecommand.StreamOptions{ + Stdin: stdin, + Stdout: &stdout, + Stderr: &stderr, + Tty: false, + }) + if err != nil { + return nil, nil, fmt.Errorf("error in Stream: %v", err) + } + + return stdout.Bytes(), stderr.Bytes(), nil +} |