mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-02 03:37:46 +08:00
61dd996806
* perf(api): optimized k8s processing mode * perf(api): change cornjob to cronjob
526 lines
18 KiB
Go
526 lines
18 KiB
Go
package handler
|
||
|
||
import (
|
||
"github.com/goodrain/rainbond/api/model"
|
||
"github.com/goodrain/rainbond/api/util"
|
||
"github.com/sirupsen/logrus"
|
||
"golang.org/x/net/context"
|
||
corev1 "k8s.io/api/core/v1"
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||
)
|
||
|
||
//GetNamespaceSource Get all resources in the current namespace
|
||
func (c *clusterAction) GetNamespaceSource(ctx context.Context, content string, namespace string) (map[string]model.LabelResource, *util.APIHandleError) {
|
||
logrus.Infof("GetNamespaceSource function begin")
|
||
//存储workloads们的ConfigMap
|
||
cmsMap := make(map[string][]string)
|
||
//存储workloads们的secrets
|
||
secretsMap := make(map[string][]string)
|
||
deployments, cmMap, secretMap := c.getResourceName(context.Background(), namespace, content, model.Deployment)
|
||
if len(cmsMap) != 0 {
|
||
cmsMap = MergeMap(cmMap, cmsMap)
|
||
}
|
||
if len(secretMap) != 0 {
|
||
secretsMap = MergeMap(secretMap, secretsMap)
|
||
}
|
||
jobs, cmMap, secretMap := c.getResourceName(ctx, namespace, content, model.Job)
|
||
if len(cmsMap) != 0 {
|
||
cmsMap = MergeMap(cmMap, cmsMap)
|
||
}
|
||
if len(secretMap) != 0 {
|
||
secretsMap = MergeMap(secretMap, secretsMap)
|
||
}
|
||
cronJobs, cmMap, secretMap := c.getResourceName(ctx, namespace, content, model.CronJob)
|
||
if len(cmsMap) != 0 {
|
||
cmsMap = MergeMap(cmMap, cmsMap)
|
||
}
|
||
if len(secretMap) != 0 {
|
||
secretsMap = MergeMap(secretMap, secretsMap)
|
||
}
|
||
stateFulSets, cmMap, secretMap := c.getResourceName(ctx, namespace, content, model.StateFulSet)
|
||
if len(cmsMap) != 0 {
|
||
cmsMap = MergeMap(cmMap, cmsMap)
|
||
}
|
||
if len(secretMap) != 0 {
|
||
secretsMap = MergeMap(secretMap, secretsMap)
|
||
}
|
||
processWorkloads := model.LabelWorkloadsResourceProcess{
|
||
Deployments: deployments,
|
||
Jobs: jobs,
|
||
CronJobs: cronJobs,
|
||
StateFulSets: stateFulSets,
|
||
}
|
||
services, _, _ := c.getResourceName(ctx, namespace, content, model.Service)
|
||
pvc, _, _ := c.getResourceName(ctx, namespace, content, model.PVC)
|
||
ingresses, _, _ := c.getResourceName(ctx, namespace, content, model.Ingress)
|
||
networkPolicies, _, _ := c.getResourceName(ctx, namespace, content, model.NetworkPolicy)
|
||
cms, _, _ := c.getResourceName(ctx, namespace, content, model.ConfigMap)
|
||
secrets, _, _ := c.getResourceName(ctx, namespace, content, model.Secret)
|
||
serviceAccounts, _, _ := c.getResourceName(ctx, namespace, content, model.ServiceAccount)
|
||
roleBindings, _, _ := c.getResourceName(ctx, namespace, content, model.RoleBinding)
|
||
horizontalPodAutoscalers, _, _ := c.getResourceName(ctx, namespace, content, model.HorizontalPodAutoscaler)
|
||
roles, _, _ := c.getResourceName(ctx, namespace, content, model.Role)
|
||
processOthers := model.LabelOthersResourceProcess{
|
||
Services: services,
|
||
PVC: pvc,
|
||
Ingresses: ingresses,
|
||
NetworkPolicies: networkPolicies,
|
||
ConfigMaps: MergeMap(cmsMap, cms),
|
||
Secrets: MergeMap(secretsMap, secrets),
|
||
ServiceAccounts: serviceAccounts,
|
||
RoleBindings: roleBindings,
|
||
HorizontalPodAutoscalers: horizontalPodAutoscalers,
|
||
Roles: roles,
|
||
}
|
||
labelResource := resourceProcessing(processWorkloads, processOthers)
|
||
logrus.Infof("GetNamespaceSource function end")
|
||
return labelResource, nil
|
||
}
|
||
|
||
//resourceProcessing 将处理好的资源类型数据格式再加工成可作为返回值的数据。
|
||
func resourceProcessing(processWorkloads model.LabelWorkloadsResourceProcess, processOthers model.LabelOthersResourceProcess) map[string]model.LabelResource {
|
||
labelResource := make(map[string]model.LabelResource)
|
||
for label, deployments := range processWorkloads.Deployments {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Workloads.Deployments = deployments
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Workloads: model.WorkLoadsResource{
|
||
Deployments: deployments,
|
||
},
|
||
}
|
||
}
|
||
for label, jobs := range processWorkloads.Jobs {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Workloads.Jobs = jobs
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Workloads: model.WorkLoadsResource{
|
||
Jobs: jobs,
|
||
},
|
||
}
|
||
|
||
}
|
||
for label, cronJobs := range processWorkloads.CronJobs {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Workloads.CronJobs = cronJobs
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Workloads: model.WorkLoadsResource{
|
||
CronJobs: cronJobs,
|
||
},
|
||
}
|
||
}
|
||
for label, stateFulSets := range processWorkloads.StateFulSets {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Workloads.StateFulSets = stateFulSets
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Workloads: model.WorkLoadsResource{
|
||
StateFulSets: stateFulSets,
|
||
},
|
||
}
|
||
}
|
||
for label, service := range processOthers.Services {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.Services = service
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
Services: service,
|
||
},
|
||
}
|
||
|
||
}
|
||
for label, pvc := range processOthers.PVC {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.PVC = pvc
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
PVC: pvc,
|
||
},
|
||
}
|
||
|
||
}
|
||
for label, ingresses := range processOthers.Ingresses {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.Ingresses = ingresses
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
Ingresses: ingresses,
|
||
},
|
||
}
|
||
}
|
||
for label, networkPolicies := range processOthers.NetworkPolicies {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.NetworkPolicies = networkPolicies
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
NetworkPolicies: networkPolicies,
|
||
},
|
||
}
|
||
}
|
||
for label, configMaps := range processOthers.ConfigMaps {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.ConfigMaps = configMaps
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
ConfigMaps: configMaps,
|
||
},
|
||
}
|
||
}
|
||
for label, secrets := range processOthers.Secrets {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.Secrets = secrets
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
Secrets: secrets,
|
||
},
|
||
}
|
||
}
|
||
for label, serviceAccounts := range processOthers.ServiceAccounts {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.ServiceAccounts = serviceAccounts
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
ServiceAccounts: serviceAccounts,
|
||
},
|
||
}
|
||
}
|
||
for label, roleBindings := range processOthers.RoleBindings {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.RoleBindings = roleBindings
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
RoleBindings: roleBindings,
|
||
},
|
||
}
|
||
}
|
||
for label, horizontalPodAutoscalers := range processOthers.HorizontalPodAutoscalers {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.HorizontalPodAutoscalers = horizontalPodAutoscalers
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
HorizontalPodAutoscalers: horizontalPodAutoscalers,
|
||
},
|
||
}
|
||
}
|
||
for label, roles := range processOthers.Roles {
|
||
if val, ok := labelResource[label]; ok {
|
||
val.Others.Roles = roles
|
||
labelResource[label] = val
|
||
continue
|
||
}
|
||
labelResource[label] = model.LabelResource{
|
||
Others: model.OtherResource{
|
||
Roles: roles,
|
||
},
|
||
}
|
||
}
|
||
return labelResource
|
||
}
|
||
|
||
//Resource -
|
||
type Resource struct {
|
||
ObjectMeta metav1.ObjectMeta
|
||
Template corev1.PodTemplateSpec
|
||
}
|
||
|
||
//getResourceName 将指定资源类型按照【label名】:[]{资源名...}处理后返回
|
||
func (c *clusterAction) getResourceName(ctx context.Context, namespace string, content string, resourcesType string) (map[string][]string, map[string][]string, map[string][]string) {
|
||
resourceName := make(map[string][]string)
|
||
var tempResources []*Resource
|
||
isWorkloads := false
|
||
cmMap := make(map[string][]string)
|
||
secretMap := make(map[string][]string)
|
||
switch resourcesType {
|
||
case model.Deployment:
|
||
resources, err := c.clientset.AppsV1().Deployments(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Deployment list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta, Template: dm.Spec.Template})
|
||
}
|
||
isWorkloads = true
|
||
case model.Job:
|
||
resources, err := c.clientset.BatchV1().Jobs(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Job list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta, Template: dm.Spec.Template})
|
||
}
|
||
isWorkloads = true
|
||
case model.CronJob:
|
||
resources, err := c.clientset.BatchV1beta1().CronJobs(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get CronJob list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta, Template: dm.Spec.JobTemplate.Spec.Template})
|
||
}
|
||
isWorkloads = true
|
||
case model.StateFulSet:
|
||
resources, err := c.clientset.AppsV1().StatefulSets(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get StateFulSets list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta, Template: dm.Spec.Template})
|
||
}
|
||
isWorkloads = true
|
||
case model.Service:
|
||
resources, err := c.clientset.CoreV1().Services(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Services list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.PVC:
|
||
resources, err := c.clientset.CoreV1().PersistentVolumeClaims(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get PersistentVolumeClaims list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.Ingress:
|
||
resources, err := c.clientset.NetworkingV1().Ingresses(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Ingresses list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.NetworkPolicy:
|
||
resources, err := c.clientset.NetworkingV1().NetworkPolicies(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get NetworkPolicies list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.ConfigMap:
|
||
resources, err := c.clientset.CoreV1().ConfigMaps(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get ConfigMaps list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.Secret:
|
||
resources, err := c.clientset.CoreV1().Secrets(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Secrets list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.ServiceAccount:
|
||
resources, err := c.clientset.CoreV1().ServiceAccounts(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get ServiceAccounts list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.RoleBinding:
|
||
resources, err := c.clientset.RbacV1().RoleBindings(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get RoleBindings list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
case model.HorizontalPodAutoscaler:
|
||
resources, err := c.clientset.AutoscalingV1().HorizontalPodAutoscalers(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get HorizontalPodAutoscalers list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, hpa := range resources.Items {
|
||
rbdResource := false
|
||
labels := make(map[string]string)
|
||
switch hpa.Spec.ScaleTargetRef.Kind {
|
||
case model.Deployment:
|
||
deploy, err := c.clientset.AppsV1().Deployments(namespace).Get(context.Background(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("The bound deployment does not exist:%v", err)
|
||
}
|
||
if hpa.ObjectMeta.Labels["creator"] == "Rainbond" {
|
||
rbdResource = true
|
||
}
|
||
labels = deploy.ObjectMeta.Labels
|
||
case model.StateFulSet:
|
||
ss, err := c.clientset.AppsV1().StatefulSets(namespace).Get(context.Background(), hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("The bound deployment does not exist:%v", err)
|
||
}
|
||
if hpa.ObjectMeta.Labels["creator"] == "Rainbond" {
|
||
rbdResource = true
|
||
}
|
||
labels = ss.ObjectMeta.Labels
|
||
}
|
||
var app string
|
||
if content == "unmanaged" && rbdResource {
|
||
continue
|
||
}
|
||
app = labels["app"]
|
||
if labels["app.kubernetes.io/name"] != "" {
|
||
app = labels["app.kubernetes.io/name"]
|
||
}
|
||
if app == "" {
|
||
app = "unclassified"
|
||
}
|
||
if _, ok := resourceName[app]; ok {
|
||
resourceName[app] = append(resourceName[app], hpa.Name)
|
||
} else {
|
||
resourceName[app] = []string{hpa.Name}
|
||
}
|
||
}
|
||
return resourceName, nil, nil
|
||
case model.Role:
|
||
resources, err := c.clientset.RbacV1().Roles(namespace).List(context.Background(), metav1.ListOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Roles list:%v", err)
|
||
return nil, cmMap, secretMap
|
||
}
|
||
for _, dm := range resources.Items {
|
||
tempResources = append(tempResources, &Resource{ObjectMeta: dm.ObjectMeta})
|
||
}
|
||
}
|
||
//这一块是统一处理资源,按label划分出来
|
||
for _, rs := range tempResources {
|
||
if content == "unmanaged" && rs.ObjectMeta.Labels["creator"] == "Rainbond" {
|
||
continue
|
||
}
|
||
app := rs.ObjectMeta.Labels["app"]
|
||
if rs.ObjectMeta.Labels["app.kubernetes.io/name"] != "" {
|
||
app = rs.ObjectMeta.Labels["app.kubernetes.io/name"]
|
||
}
|
||
if app == "" {
|
||
app = "unclassified"
|
||
}
|
||
//如果是Workloads类型的资源需要检查其内部configmap、secret、PVC(防止没有这三种资源没有label但是用到了)
|
||
if isWorkloads {
|
||
cmList, secretList := c.replenishLabel(ctx, rs, namespace, app)
|
||
if _, ok := cmMap[app]; ok {
|
||
cmMap[app] = append(cmMap[app], cmList...)
|
||
} else {
|
||
cmMap[app] = cmList
|
||
}
|
||
if _, ok := secretMap[app]; ok {
|
||
secretMap[app] = append(secretMap[app], secretList...)
|
||
} else {
|
||
secretMap[app] = secretList
|
||
}
|
||
}
|
||
if _, ok := resourceName[app]; ok {
|
||
resourceName[app] = append(resourceName[app], rs.ObjectMeta.Name)
|
||
} else {
|
||
resourceName[app] = []string{rs.ObjectMeta.Name}
|
||
}
|
||
}
|
||
return resourceName, cmMap, secretMap
|
||
}
|
||
|
||
//replenishLabel 获取workloads资源上携带的ConfigMap和secret,以及把pvc加上标签。
|
||
func (c *clusterAction) replenishLabel(ctx context.Context, resource *Resource, namespace string, app string) ([]string, []string) {
|
||
var cmList []string
|
||
var secretList []string
|
||
resourceVolume := resource.Template.Spec.Volumes
|
||
for _, volume := range resourceVolume {
|
||
if pvc := volume.PersistentVolumeClaim; pvc != nil {
|
||
PersistentVolumeClaims, err := c.clientset.CoreV1().PersistentVolumeClaims(namespace).Get(context.Background(), pvc.ClaimName, metav1.GetOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get PersistentVolumeClaims %s/%s:%v", namespace, pvc.ClaimName, err)
|
||
}
|
||
if PersistentVolumeClaims.Labels == nil {
|
||
PersistentVolumeClaims.Labels = make(map[string]string)
|
||
}
|
||
if _, ok := PersistentVolumeClaims.Labels["app"]; !ok {
|
||
if _, ok := PersistentVolumeClaims.Labels["app.kubernetes.io/name"]; !ok {
|
||
PersistentVolumeClaims.Labels["app"] = app
|
||
}
|
||
}
|
||
_, err = c.clientset.CoreV1().PersistentVolumeClaims(namespace).Update(context.Background(), PersistentVolumeClaims, metav1.UpdateOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("PersistentVolumeClaims label update error:%v", err)
|
||
}
|
||
continue
|
||
}
|
||
if cm := volume.ConfigMap; cm != nil {
|
||
cm, err := c.clientset.CoreV1().ConfigMaps(namespace).Get(context.Background(), cm.Name, metav1.GetOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get ConfigMap:%v", err)
|
||
}
|
||
if _, ok := cm.Labels["app"]; !ok {
|
||
if _, ok := cm.Labels["app.kubernetes.io/name"]; !ok {
|
||
cmList = append(cmList, cm.Name)
|
||
}
|
||
}
|
||
}
|
||
if secret := volume.Secret; secret != nil {
|
||
secret, err := c.clientset.CoreV1().Secrets(namespace).Get(context.Background(), secret.SecretName, metav1.GetOptions{})
|
||
if err != nil {
|
||
logrus.Errorf("Failed to get Scret:%v", err)
|
||
}
|
||
if _, ok := secret.Labels["app"]; !ok {
|
||
if _, ok := secret.Labels["app.kubernetes.io/name"]; !ok {
|
||
cmList = append(cmList, secret.Name)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return cmList, secretList
|
||
}
|