Rainbond/api/handler/get_namespace_resource_name.go

531 lines
18 KiB
Go
Raw Normal View History

2022-07-21 16:03:08 +08:00
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)
2022-07-21 16:03:08 +08:00
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)
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
if err != nil {
logrus.Errorf("Failed to get Job list:%v", err)
return nil, cmMap, secretMap
}
for _, dm := range resources.Items {
if dm.OwnerReferences != nil {
if dm.OwnerReferences[0].Kind == model.CronJob {
continue
}
}
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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"
2022-07-21 16:03:08 +08:00
}
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{})
2022-07-21 16:03:08 +08:00
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"
2022-07-21 16:03:08 +08:00
}
//如果是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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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{})
2022-07-21 16:03:08 +08:00
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
}