package handler import ( "fmt" "github.com/goodrain/rainbond/api/model" "github.com/goodrain/rainbond/api/util" dbmodel "github.com/goodrain/rainbond/db/model" "github.com/sirupsen/logrus" "golang.org/x/net/context" v1 "k8s.io/api/autoscaling/v1" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "strings" ) // ConvertResource 处理资源 func (c *clusterAction) ConvertResource(ctx context.Context, namespace string, lr map[string]model.LabelResource) (map[string]model.ApplicationResource, *util.APIHandleError) { logrus.Infof("ConvertResource function begin") appsServices := make(map[string]model.ApplicationResource) for label, resource := range lr { c.workloadHandle(ctx, appsServices, resource, namespace, label) } logrus.Infof("ConvertResource function end") return appsServices, nil } func (c *clusterAction) workloadHandle(ctx context.Context, cr map[string]model.ApplicationResource, lr model.LabelResource, namespace string, label string) { app := label deployResource := c.workloadDeployments(lr.Workloads.Deployments, namespace) stsResource := c.workloadStateFulSets(lr.Workloads.StateFulSets, namespace) jobResource := c.workloadJobs(lr.Workloads.Jobs, namespace) cjResource := c.workloadCronJobs(lr.Workloads.CronJobs, namespace) convertResource := append(deployResource, stsResource...) convertResource = append(convertResource, jobResource...) convertResource = append(convertResource, cjResource...) k8sResources := c.getAppKubernetesResources(ctx, lr.Others, namespace) cr[app] = model.ApplicationResource{ ConvertResource: convertResource, KubernetesResources: k8sResources, } } func (c *clusterAction) workloadDeployments(dmNames []string, namespace string) []model.ConvertResource { var componentsCR []model.ConvertResource for _, dmName := range dmNames { resources, err := c.clientset.AppsV1().Deployments(namespace).Get(context.Background(), dmName, metav1.GetOptions{}) if err != nil { logrus.Errorf("Failed to get Deployment %v:%v", dmName, err) return nil } if len(resources.Spec.Template.Spec.Containers) == 0 { logrus.Errorf("Deployment %v has no containers, skipping", dmName) continue } memory, cpu := resources.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().Value(), resources.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() if memory == 0 { memory = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() } if cpu == 0 { cpu = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().MilliValue() } //BasicManagement basic := model.BasicManagement{ ResourceType: model.Deployment, Replicas: resources.Spec.Replicas, Memory: memory / 1024 / 1024, CPU: cpu, Image: resources.Spec.Template.Spec.Containers[0].Image, Cmd: strings.Join(append(resources.Spec.Template.Spec.Containers[0].Command, resources.Spec.Template.Spec.Containers[0].Args...), " "), } parameter := model.YamlResourceParameter{ ComponentsCR: &componentsCR, Basic: basic, Template: resources.Spec.Template, Namespace: namespace, Name: dmName, RsLabel: resources.Labels, } PodTemplateSpecResource(parameter, nil, c.clientset) } return componentsCR } func (c *clusterAction) workloadStateFulSets(stsNames []string, namespace string) []model.ConvertResource { var componentsCR []model.ConvertResource for _, stsName := range stsNames { resources, err := c.clientset.AppsV1().StatefulSets(namespace).Get(context.Background(), stsName, metav1.GetOptions{}) if err != nil { logrus.Errorf("Failed to get Deployment %v:%v", stsName, err) return nil } if len(resources.Spec.Template.Spec.Containers) == 0 { logrus.Errorf("StatefulSet %v has no containers, skipping", stsName) continue } memory, cpu := resources.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().Value(), resources.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() if memory == 0 { memory = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() } if cpu == 0 { cpu = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().MilliValue() } //BasicManagement basic := model.BasicManagement{ ResourceType: model.StateFulSet, Replicas: resources.Spec.Replicas, Memory: memory / 1024 / 1024, CPU: cpu, Image: resources.Spec.Template.Spec.Containers[0].Image, Cmd: strings.Join(append(resources.Spec.Template.Spec.Containers[0].Command, resources.Spec.Template.Spec.Containers[0].Args...), " "), } parameter := model.YamlResourceParameter{ ComponentsCR: &componentsCR, Basic: basic, Template: resources.Spec.Template, Namespace: namespace, Name: stsName, RsLabel: resources.Labels, } PodTemplateSpecResource(parameter, resources.Spec.VolumeClaimTemplates, c.clientset) } return componentsCR } func (c *clusterAction) workloadJobs(jobNames []string, namespace string) []model.ConvertResource { var componentsCR []model.ConvertResource for _, jobName := range jobNames { resources, err := c.clientset.BatchV1().Jobs(namespace).Get(context.Background(), jobName, metav1.GetOptions{}) if err != nil { logrus.Errorf("Failed to get Deployment %v:%v", jobName, err) return nil } if len(resources.Spec.Template.Spec.Containers) == 0 { logrus.Errorf("Job %v has no containers, skipping", jobName) continue } var BackoffLimit, Parallelism, ActiveDeadlineSeconds, Completions string if resources.Spec.BackoffLimit != nil { BackoffLimit = fmt.Sprintf("%v", *resources.Spec.BackoffLimit) } if resources.Spec.Parallelism != nil { Parallelism = fmt.Sprintf("%v", *resources.Spec.Parallelism) } if resources.Spec.ActiveDeadlineSeconds != nil { ActiveDeadlineSeconds = fmt.Sprintf("%v", *resources.Spec.ActiveDeadlineSeconds) } if resources.Spec.Completions != nil { Completions = fmt.Sprintf("%v", *resources.Spec.Completions) } job := model.JobStrategy{ Schedule: resources.Spec.Template.Spec.SchedulerName, BackoffLimit: BackoffLimit, Parallelism: Parallelism, ActiveDeadlineSeconds: ActiveDeadlineSeconds, Completions: Completions, } memory, cpu := resources.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().Value(), resources.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() if memory == 0 { memory = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() } if cpu == 0 { cpu = resources.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().MilliValue() } //BasicManagement basic := model.BasicManagement{ ResourceType: model.Job, Replicas: resources.Spec.Completions, Memory: memory / 1024 / 1024, CPU: cpu, Image: resources.Spec.Template.Spec.Containers[0].Image, Cmd: strings.Join(append(resources.Spec.Template.Spec.Containers[0].Command, resources.Spec.Template.Spec.Containers[0].Args...), " "), JobStrategy: job, } parameter := model.YamlResourceParameter{ ComponentsCR: &componentsCR, Basic: basic, Template: resources.Spec.Template, Namespace: namespace, Name: jobName, RsLabel: resources.Labels, } PodTemplateSpecResource(parameter, nil, c.clientset) } return componentsCR } func (c *clusterAction) workloadCronJobs(cjNames []string, namespace string) []model.ConvertResource { var componentsCR []model.ConvertResource for _, cjName := range cjNames { resources, err := c.clientset.BatchV1beta1().CronJobs(namespace).Get(context.Background(), cjName, metav1.GetOptions{}) if err != nil { logrus.Errorf("Failed to get Deployment %v:%v", cjName, err) return nil } if len(resources.Spec.JobTemplate.Spec.Template.Spec.Containers) == 0 { logrus.Errorf("CronJob %v has no containers, skipping", cjName) continue } BackoffLimit, Parallelism, ActiveDeadlineSeconds, Completions := "", "", "", "" if resources.Spec.JobTemplate.Spec.BackoffLimit != nil { BackoffLimit = fmt.Sprintf("%v", *resources.Spec.JobTemplate.Spec.BackoffLimit) } if resources.Spec.JobTemplate.Spec.Parallelism != nil { Parallelism = fmt.Sprintf("%v", *resources.Spec.JobTemplate.Spec.Parallelism) } if resources.Spec.JobTemplate.Spec.ActiveDeadlineSeconds != nil { ActiveDeadlineSeconds = fmt.Sprintf("%v", *resources.Spec.JobTemplate.Spec.ActiveDeadlineSeconds) } if resources.Spec.JobTemplate.Spec.Completions != nil { Completions = fmt.Sprintf("%v", *resources.Spec.JobTemplate.Spec.Completions) } job := model.JobStrategy{ Schedule: resources.Spec.Schedule, BackoffLimit: BackoffLimit, Parallelism: Parallelism, ActiveDeadlineSeconds: ActiveDeadlineSeconds, Completions: Completions, } memory, cpu := resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().Value(), resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() if memory == 0 { memory = resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() } if cpu == 0 { cpu = resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().MilliValue() } //BasicManagement basic := model.BasicManagement{ ResourceType: model.CronJob, Replicas: resources.Spec.JobTemplate.Spec.Completions, Memory: memory / 1024 / 1024, CPU: cpu, Image: resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Image, Cmd: strings.Join(append(resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Command, resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Args...), " "), JobStrategy: job, } parameter := model.YamlResourceParameter{ ComponentsCR: &componentsCR, Basic: basic, Template: resources.Spec.JobTemplate.Spec.Template, Namespace: namespace, Name: cjName, RsLabel: resources.Labels, } PodTemplateSpecResource(parameter, nil, c.clientset) } return componentsCR } func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others model.OtherResource, namespace string) []dbmodel.K8sResource { var k8sResources []dbmodel.K8sResource servicesMap := make(map[string]corev1.Service) servicesList, err := c.clientset.CoreV1().Services(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get services error:%v", namespace, err) } if len(others.Services) != 0 && err == nil { for _, services := range servicesList.Items { servicesMap[services.Name] = services } for _, servicesName := range others.Services { services, _ := servicesMap[servicesName] services.Kind = model.Service services.Status = corev1.ServiceStatus{} services.APIVersion = "v1" services.ManagedFields = []metav1.ManagedFieldsEntry{} kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", services) if err != nil { logrus.Errorf("namespace:%v service:%v error: %v", namespace, services.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: services.Name, Kind: model.Service, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } pvcMap := make(map[string]corev1.PersistentVolumeClaim) pvcList, err := c.clientset.CoreV1().PersistentVolumeClaims(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get pvc error:%v", namespace, err) } if len(others.PVC) != 0 && err == nil { for _, pvc := range pvcList.Items { pvcMap[pvc.Name] = pvc } for _, pvcName := range others.PVC { pvc, _ := pvcMap[pvcName] pvc.Status = corev1.PersistentVolumeClaimStatus{} pvc.ManagedFields = []metav1.ManagedFieldsEntry{} pvc.Kind = model.PVC pvc.APIVersion = "v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", pvc) if err != nil { logrus.Errorf("namespace:%v pvc:%v error: %v", namespace, pvc.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: pvc.Name, Kind: model.PVC, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } ingressMap := make(map[string]networkingv1.Ingress) ingressList, err := c.clientset.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get ingresses error:%v", namespace, err) } if len(others.Ingresses) != 0 && err == nil { for _, ingress := range ingressList.Items { ingressMap[ingress.Name] = ingress } for _, ingressName := range others.Ingresses { ingresses, _ := ingressMap[ingressName] ingresses.Status = networkingv1.IngressStatus{} ingresses.ManagedFields = []metav1.ManagedFieldsEntry{} ingresses.Kind = model.Ingress ingresses.APIVersion = "networking.k8s.io/v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", ingresses) if err != nil { logrus.Errorf("namespace:%v ingresses:%v error: %v", namespace, ingresses.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: ingresses.Name, Kind: model.Ingress, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } networkPoliciesMap := make(map[string]networkingv1.NetworkPolicy) networkPoliciesList, err := c.clientset.NetworkingV1().NetworkPolicies(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get NetworkPolicies error:%v", namespace, err) } if len(others.NetworkPolicies) != 0 && err == nil { for _, networkPolicies := range networkPoliciesList.Items { networkPoliciesMap[networkPolicies.Name] = networkPolicies } for _, networkPoliciesName := range others.NetworkPolicies { networkPolicies, _ := networkPoliciesMap[networkPoliciesName] networkPolicies.ManagedFields = []metav1.ManagedFieldsEntry{} networkPolicies.Kind = model.NetworkPolicy networkPolicies.APIVersion = "networking.k8s.io/v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", networkPolicies) if err != nil { logrus.Errorf("namespace:%v NetworkPolicies:%v error: %v", namespace, networkPolicies.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: networkPolicies.Name, Kind: model.NetworkPolicy, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } cmMap := make(map[string]corev1.ConfigMap) cmList, err := c.clientset.CoreV1().ConfigMaps(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get ConfigMaps error:%v", namespace, err) } if len(others.ConfigMaps) != 0 && err == nil { for _, cm := range cmList.Items { cmMap[cm.Name] = cm } for _, configMapsName := range others.ConfigMaps { configMaps, _ := cmMap[configMapsName] configMaps.ManagedFields = []metav1.ManagedFieldsEntry{} configMaps.Kind = model.ConfigMap configMaps.APIVersion = "v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", configMaps) if err != nil { logrus.Errorf("namespace:%v ConfigMaps:%v error: %v", namespace, configMaps.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: configMaps.Name, Kind: model.ConfigMap, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } secretsMap := make(map[string]corev1.Secret) secretsList, err := c.clientset.CoreV1().Secrets(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get Secrets error:%v", namespace, err) } if len(others.Secrets) != 0 && err == nil { for _, secrets := range secretsList.Items { secretsMap[secrets.Name] = secrets } for _, secretsName := range others.Secrets { secrets, _ := secretsMap[secretsName] secrets.ManagedFields = []metav1.ManagedFieldsEntry{} secrets.Kind = model.Secret secrets.APIVersion = "v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", secrets) if err != nil { logrus.Errorf("namespace:%v Secrets:%v error: %v", namespace, secrets.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: secrets.Name, Kind: model.Secret, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } serviceAccountsMap := make(map[string]corev1.ServiceAccount) serviceAccountsList, err := c.clientset.CoreV1().ServiceAccounts(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get ServiceAccounts error:%v", namespace, err) } if len(others.ServiceAccounts) != 0 && err == nil { for _, serviceAccounts := range serviceAccountsList.Items { serviceAccountsMap[serviceAccounts.Name] = serviceAccounts } for _, serviceAccountsName := range others.ServiceAccounts { serviceAccounts, _ := serviceAccountsMap[serviceAccountsName] serviceAccounts.ManagedFields = []metav1.ManagedFieldsEntry{} serviceAccounts.Kind = model.ServiceAccount serviceAccounts.APIVersion = "v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", serviceAccounts) if err != nil { logrus.Errorf("namespace:%v ServiceAccounts:%v error: %v", namespace, serviceAccounts.Name, err) continue } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: serviceAccounts.Name, Kind: model.ServiceAccount, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } roleBindingsMap := make(map[string]rbacv1.RoleBinding) roleBindingsList, _ := c.clientset.RbacV1().RoleBindings(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get RoleBindings error:%v", namespace, err) } if len(others.RoleBindings) != 0 && err == nil { for _, roleBindings := range roleBindingsList.Items { roleBindingsMap[roleBindings.Name] = roleBindings } for _, roleBindingsName := range others.RoleBindings { roleBindings, _ := roleBindingsMap[roleBindingsName] roleBindings.ManagedFields = []metav1.ManagedFieldsEntry{} roleBindings.Kind = model.RoleBinding roleBindings.APIVersion = "rbac.authorization.k8s.io/v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", roleBindings) if err != nil { logrus.Errorf("namespace:%v RoleBindings:%v error: %v", namespace, roleBindings.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: roleBindings.Name, Kind: model.RoleBinding, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } hpaMap := make(map[string]v1.HorizontalPodAutoscaler) hpaList, _ := c.clientset.AutoscalingV1().HorizontalPodAutoscalers(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get HorizontalPodAutoscalers error:%v", namespace, err) } if len(others.HorizontalPodAutoscalers) != 0 && err == nil { for _, hpa := range hpaList.Items { hpaMap[hpa.Name] = hpa } for _, hpaName := range others.HorizontalPodAutoscalers { hpa, _ := hpaMap[hpaName] hpa.Status = v1.HorizontalPodAutoscalerStatus{} hpa.ManagedFields = []metav1.ManagedFieldsEntry{} hpa.Kind = model.HorizontalPodAutoscaler hpa.APIVersion = "autoscaling/v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", hpa) if err != nil { logrus.Errorf("namespace:%v HorizontalPodAutoscalers:%v error: %v", namespace, hpa.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: hpa.Name, Kind: model.HorizontalPodAutoscaler, Content: kubernetesResourcesYAML, State: 1, ErrorOverview: "创建成功", }) } } rolesMap := make(map[string]rbacv1.Role) rolesList, err := c.clientset.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{}) if err != nil { logrus.Errorf("namespace:%v get roles error:%v", namespace, err) } if len(others.Roles) != 0 && err == nil { for _, roles := range rolesList.Items { rolesMap[roles.Name] = roles } for _, rolesName := range others.Roles { roles, _ := rolesMap[rolesName] roles.Kind = model.Role roles.APIVersion = "rbac.authorization.k8s.io/v1" kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", roles) if err != nil { logrus.Errorf("namespace:%v roles:%v error: %v", namespace, roles.Name, err) } k8sResources = append(k8sResources, dbmodel.K8sResource{ Name: roles.Name, Kind: model.Role, Content: kubernetesResourcesYAML, ErrorOverview: "创建成功", State: 1, }) } } return k8sResources }