feat: yaml file resource processing (#1263)

* perf(api): optimized k8s processing mode

* perf(api): change cornjob to cronjob

* feat(api): yaml file resource processing
This commit is contained in:
张启航 2022-08-03 13:41:36 +08:00 committed by GitHub
parent 7d20f254f2
commit 9eae69eb00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1263 additions and 536 deletions

View File

@ -37,7 +37,9 @@ type ClusterInterface interface {
AddResource(w http.ResponseWriter, r *http.Request)
DeleteResource(w http.ResponseWriter, r *http.Request)
UpdateResource(w http.ResponseWriter, r *http.Request)
//YamlResourceName(w http.ResponseWriter, r *http.Request)
YamlResourceName(w http.ResponseWriter, r *http.Request)
YamlResourceDetailed(w http.ResponseWriter, r *http.Request)
YamlResourceImport(w http.ResponseWriter, r *http.Request)
}
//TenantInterface interface

View File

@ -101,8 +101,9 @@ func (v2 *V2) clusterRouter() chi.Router {
r.Post("/k8s-resource", controller.GetManager().AddResource)
r.Delete("/k8s-resource", controller.GetManager().DeleteResource)
r.Put("/k8s-resource", controller.GetManager().UpdateResource)
//r.Get("/yaml_resource_name", controller.GetManager().YamlResourceName)
r.Get("/yaml_resource_name", controller.GetManager().YamlResourceName)
r.Get("/yaml_resource_detailed", controller.GetManager().YamlResourceDetailed)
r.Post("/yaml_resource_import", controller.GetManager().YamlResourceImport)
return r
}

View File

@ -209,15 +209,48 @@ func (t *ClusterController) DeleteResource(w http.ResponseWriter, r *http.Reques
}
//YamlResourceName -
//func (t *ClusterController) YamlResourceName(w http.ResponseWriter, r *http.Request) {
// var yr model.YamlResource
// if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
// return
// }
// h, err := handler.GetClusterHandler().AppYamlResourceName(yr)
// if err != nil {
// err.Handle(r, w)
// return
// }
// httputil.ReturnSuccess(r, w, h)
//}
func (t *ClusterController) YamlResourceName(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
h, err := handler.GetClusterHandler().AppYamlResourceName(yr)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, h)
}
//YamlResourceDetailed -
func (t *ClusterController) YamlResourceDetailed(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
h, err := handler.GetClusterHandler().AppYamlResourceDetailed(yr, false)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, h)
}
//YamlResourceImport -
func (t *ClusterController) YamlResourceImport(w http.ResponseWriter, r *http.Request) {
var yr model.YamlResource
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &yr, nil); !ok {
return
}
ar, err := handler.GetClusterHandler().AppYamlResourceDetailed(yr, true)
if err != nil {
err.Handle(r, w)
return
}
ac, err := handler.GetClusterHandler().AppYamlResourceImport(yr, ar)
if err != nil {
err.Handle(r, w)
return
}
httputil.ReturnSuccess(r, w, ac)
}

View File

@ -37,7 +37,9 @@ type ClusterHandler interface {
AddAppK8SResource(ctx context.Context, namespace string, appID string, resourceYaml string) ([]*dbmodel.K8sResource, *util.APIHandleError)
DeleteAppK8SResource(ctx context.Context, namespace, appID, name, yaml, kind string) *util.APIHandleError
UpdateAppK8SResource(ctx context.Context, namespace, appID, name, resourceYaml, kind string) (dbmodel.K8sResource, *util.APIHandleError)
//AppYamlResourceName(yamlResource model.YamlResource) (map[string]model.LabelResource, *util.APIHandleError)
AppYamlResourceName(yamlResource model.YamlResource) (map[string]model.LabelResource, *util.APIHandleError)
AppYamlResourceDetailed(yamlResource model.YamlResource, yamlImport bool) (model.ApplicationResource, *util.APIHandleError)
AppYamlResourceImport(yamlResource model.YamlResource, components model.ApplicationResource) (model.AppComponent, *util.APIHandleError)
}
// NewClusterHandler -

View File

@ -1,7 +1,6 @@
package handler
import (
"encoding/json"
"fmt"
"github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/api/util"
@ -13,8 +12,6 @@ import (
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"path"
"strconv"
"strings"
)
@ -51,6 +48,7 @@ func (c *clusterAction) workloadDeployments(dmNames []string, namespace string)
logrus.Errorf("Failed to get Deployment %v:%v", dmName, err)
return nil
}
//BasicManagement
basic := model.BasicManagement{
ResourceType: model.Deployment,
@ -60,7 +58,15 @@ func (c *clusterAction) workloadDeployments(dmNames []string, namespace string)
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...), " "),
}
c.podTemplateSpecResource(&componentsCR, basic, resources.Spec.Template, namespace, dmName, resources.Labels)
parameter := model.YamlResourceParameter{
ComponentsCR: &componentsCR,
Basic: basic,
Template: resources.Spec.Template,
Namespace: namespace,
Name: dmName,
RsLabel: resources.Labels,
}
c.PodTemplateSpecResource(parameter)
}
return componentsCR
}
@ -83,7 +89,15 @@ func (c *clusterAction) workloadStateFulSets(sfsNames []string, namespace string
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...), " "),
}
c.podTemplateSpecResource(&componentsCR, basic, resources.Spec.Template, namespace, sfsName, resources.Labels)
parameter := model.YamlResourceParameter{
ComponentsCR: &componentsCR,
Basic: basic,
Template: resources.Spec.Template,
Namespace: namespace,
Name: sfsName,
RsLabel: resources.Labels,
}
c.PodTemplateSpecResource(parameter)
}
return componentsCR
}
@ -126,7 +140,15 @@ func (c *clusterAction) workloadJobs(jobNames []string, namespace string) []mode
Cmd: strings.Join(append(resources.Spec.Template.Spec.Containers[0].Command, resources.Spec.Template.Spec.Containers[0].Args...), " "),
JobStrategy: job,
}
c.podTemplateSpecResource(&componentsCR, basic, resources.Spec.Template, namespace, jobName, resources.Labels)
parameter := model.YamlResourceParameter{
ComponentsCR: &componentsCR,
Basic: basic,
Template: resources.Spec.Template,
Namespace: namespace,
Name: jobName,
RsLabel: resources.Labels,
}
c.PodTemplateSpecResource(parameter)
}
return componentsCR
}
@ -169,382 +191,19 @@ func (c *clusterAction) workloadCronJobs(cjNames []string, namespace string) []m
Cmd: strings.Join(append(resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Command, resources.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Args...), " "),
JobStrategy: job,
}
c.podTemplateSpecResource(&componentsCR, basic, resources.Spec.JobTemplate.Spec.Template, namespace, cjName, resources.Labels)
parameter := model.YamlResourceParameter{
ComponentsCR: &componentsCR,
Basic: basic,
Template: resources.Spec.JobTemplate.Spec.Template,
Namespace: namespace,
Name: cjName,
RsLabel: resources.Labels,
}
c.PodTemplateSpecResource(parameter)
}
return componentsCR
}
func (c *clusterAction) podTemplateSpecResource(componentsCR *[]model.ConvertResource, basic model.BasicManagement, template corev1.PodTemplateSpec, namespace, name string, rsLabel map[string]string) {
//Port
var ps []model.PortManagement
for _, port := range template.Spec.Containers[0].Ports {
if string(port.Protocol) == "UDP" {
ps = append(ps, model.PortManagement{
Port: port.ContainerPort,
Protocol: "UDP",
Inner: false,
Outer: false,
})
continue
}
if string(port.Protocol) == "TCP" {
ps = append(ps, model.PortManagement{
Port: port.ContainerPort,
Protocol: "TCP",
Inner: false,
Outer: false,
})
continue
}
logrus.Warningf("Transport protocol type not recognized%v", port.Protocol)
}
//ENV
var envs []model.ENVManagement
for i := 0; i < len(template.Spec.Containers[0].Env); i++ {
if cm := template.Spec.Containers[0].Env[i].ValueFrom; cm == nil {
envs = append(envs, model.ENVManagement{
ENVKey: template.Spec.Containers[0].Env[i].Name,
ENVValue: template.Spec.Containers[0].Env[i].Value,
ENVExplain: "",
})
template.Spec.Containers[0].Env = append(template.Spec.Containers[0].Env[:i], template.Spec.Containers[0].Env[i+1:]...)
}
}
//Configs
var configs []model.ConfigManagement
//这一块是处理配置文件
//配置文件的名字最终都是configmap里面的key值。
//volume在被挂载后存在四种情况
//第一种是volume存在itemsvolumeMount的SubPath不等于空。路径直接是volumeMount里面的mountPath。
//第二种是volume存在itemsvolumeMount的SubPath等于空。路径则变成volumeMount里面的mountPath拼接上items里面每一个元素的key值。
//第三种是volume不存在itemsvolumeMount的SubPath不等于空。路径直接是volumeMount里面的mountPath。
//第四种是volume不存在itemsvolumeMount的SubPath等于空。路径则变成volumeMount里面的mountPath拼接上configmap资源里面每一个元素的key值
cmMap := make(map[string]corev1.ConfigMap)
cmList, err := c.clientset.CoreV1().ConfigMaps(namespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to get ConfigMap%v", err)
}
for _, volume := range template.Spec.Volumes {
for _, cm := range cmList.Items {
cmMap[cm.Name] = cm
}
if volume.ConfigMap != nil && err == nil {
cm, _ := cmMap[volume.ConfigMap.Name]
cmData := cm.Data
isLog := true
for _, volumeMount := range template.Spec.Containers[0].VolumeMounts {
if volume.Name != volumeMount.Name {
continue
}
isLog = false
if volume.ConfigMap.Items != nil {
if volumeMount.SubPath != "" {
configName := ""
var mode int32
for _, item := range volume.ConfigMap.Items {
if item.Path == volumeMount.SubPath {
configName = item.Key
mode = *item.Mode
}
}
configs = append(configs, model.ConfigManagement{
ConfigName: configName,
ConfigPath: volumeMount.MountPath,
ConfigValue: cmData[configName],
Mode: mode,
})
continue
}
p := volumeMount.MountPath
for _, item := range volume.ConfigMap.Items {
p := path.Join(p, item.Path)
var mode int32
if item.Mode != nil {
mode = *item.Mode
}
configs = append(configs, model.ConfigManagement{
ConfigName: item.Key,
ConfigPath: p,
ConfigValue: cmData[item.Key],
Mode: mode,
})
}
} else {
if volumeMount.SubPath != "" {
configs = append(configs, model.ConfigManagement{
ConfigName: volumeMount.SubPath,
ConfigPath: volumeMount.MountPath,
ConfigValue: cmData[volumeMount.SubPath],
Mode: *volume.ConfigMap.DefaultMode,
})
continue
}
mountPath := volumeMount.MountPath
for key, val := range cmData {
mountPath = path.Join(mountPath, key)
configs = append(configs, model.ConfigManagement{
ConfigName: key,
ConfigPath: mountPath,
ConfigValue: val,
Mode: *volume.ConfigMap.DefaultMode,
})
}
}
}
if isLog {
logrus.Warningf("configmap type resource %v is not mounted in volumemount", volume.ConfigMap.Name)
}
}
}
//TelescopicManagement
HPAResource, err := c.clientset.AutoscalingV1().HorizontalPodAutoscalers(namespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to get HorizontalPodAutoscalers list:%v", err)
}
var t model.TelescopicManagement
//这一块就是自动伸缩的对应解析,
//需要注意的一点是hpa的cpu和memory的阈值设置是通过Annotations["autoscaling.alpha.kubernetes.io/metrics"]字段设置
//而且它的返回值是个json字符串所以设置了一个结构体进行解析。
for _, hpa := range HPAResource.Items {
if hpa.Spec.ScaleTargetRef.Kind != model.Deployment || hpa.Spec.ScaleTargetRef.Name != name {
t.Enable = false
continue
}
t.Enable = true
t.MinReplicas = *hpa.Spec.MinReplicas
t.MaxReplicas = hpa.Spec.MaxReplicas
var cpuormemorys []*dbmodel.TenantServiceAutoscalerRuleMetrics
cpuUsage := hpa.Spec.TargetCPUUtilizationPercentage
if cpuUsage != nil {
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "utilization",
MetricTargetValue: int(*cpuUsage),
})
}
CPUAndMemoryJSON, ok := hpa.Annotations["autoscaling.alpha.kubernetes.io/metrics"]
if ok {
type com struct {
T string `json:"type"`
Resource map[string]interface{}
}
var c []com
err := json.Unmarshal([]byte(CPUAndMemoryJSON), &c)
if err != nil {
logrus.Errorf("autoscaling.alpha.kubernetes.io/metrics parsing failed%v", err)
}
for _, cpuormemory := range c {
switch cpuormemory.Resource["name"] {
case "cpu":
cpu := fmt.Sprint(cpuormemory.Resource["targetAverageValue"])
cpuUnit := cpu[len(cpu)-1:]
var cpuUsage int
if cpuUnit == "m" {
cpuUsage, _ = strconv.Atoi(cpu[:len(cpu)-1])
}
if cpuUnit == "g" || cpuUnit == "G" {
cpuUsage, _ = strconv.Atoi(cpu[:len(cpu)-1])
cpuUsage = cpuUsage * 1024
}
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "average_value",
MetricTargetValue: cpuUsage,
})
case "memory":
memory := fmt.Sprint(cpuormemory.Resource["targetAverageValue"])
memoryUnit := memory[:len(memory)-1]
var MemoryUsage int
if memoryUnit == "m" {
MemoryUsage, _ = strconv.Atoi(memory[:len(memory)-1])
}
if memoryUnit == "g" || memoryUnit == "G" {
MemoryUsage, _ = strconv.Atoi(memory[:len(memory)-1])
MemoryUsage = MemoryUsage * 1024
}
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "average_value",
MetricTargetValue: MemoryUsage,
})
}
}
}
t.CPUOrMemory = cpuormemorys
}
//HealthyCheckManagement
var hcm model.HealthyCheckManagement
livenessProbe := template.Spec.Containers[0].LivenessProbe
if livenessProbe != nil {
var httpHeaders []string
for _, httpHeader := range livenessProbe.HTTPGet.HTTPHeaders {
nv := httpHeader.Name + "=" + httpHeader.Value
httpHeaders = append(httpHeaders, nv)
}
hcm.Status = 1
hcm.DetectionMethod = strings.ToLower(string(livenessProbe.HTTPGet.Scheme))
hcm.Port = int(livenessProbe.HTTPGet.Port.IntVal)
hcm.Path = livenessProbe.HTTPGet.Path
if livenessProbe.Exec != nil {
hcm.Command = strings.Join(livenessProbe.Exec.Command, " ")
}
hcm.HTTPHeader = strings.Join(httpHeaders, ",")
hcm.Mode = "liveness"
hcm.InitialDelaySecond = int(livenessProbe.InitialDelaySeconds)
hcm.PeriodSecond = int(livenessProbe.PeriodSeconds)
hcm.TimeoutSecond = int(livenessProbe.TimeoutSeconds)
hcm.FailureThreshold = int(livenessProbe.FailureThreshold)
hcm.SuccessThreshold = int(livenessProbe.SuccessThreshold)
} else {
readinessProbe := template.Spec.Containers[0].ReadinessProbe
if readinessProbe != nil {
var httpHeaders []string
for _, httpHeader := range readinessProbe.HTTPGet.HTTPHeaders {
nv := httpHeader.Name + "=" + httpHeader.Value
httpHeaders = append(httpHeaders, nv)
}
hcm.Status = 1
hcm.DetectionMethod = strings.ToLower(string(readinessProbe.HTTPGet.Scheme))
hcm.Mode = "readiness"
hcm.Port = int(readinessProbe.HTTPGet.Port.IntVal)
hcm.Path = readinessProbe.HTTPGet.Path
if readinessProbe.Exec != nil {
hcm.Command = strings.Join(readinessProbe.Exec.Command, " ")
}
hcm.HTTPHeader = strings.Join(httpHeaders, ",")
hcm.InitialDelaySecond = int(readinessProbe.InitialDelaySeconds)
hcm.PeriodSecond = int(readinessProbe.PeriodSeconds)
hcm.TimeoutSecond = int(readinessProbe.TimeoutSeconds)
hcm.FailureThreshold = int(readinessProbe.FailureThreshold)
hcm.SuccessThreshold = int(readinessProbe.SuccessThreshold)
}
}
var attributes []*dbmodel.ComponentK8sAttributes
if template.Spec.Containers[0].Env != nil && len(template.Spec.Containers[0].Env) > 0 {
envYaml, err := ObjectToJSONORYaml("yaml", template.Spec.Containers[0].Env)
if err != nil {
logrus.Errorf("deployment:%v env %v", name, err)
}
envAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameENV,
SaveType: "yaml",
AttributeValue: envYaml,
}
attributes = append(attributes, envAttributes)
}
if template.Spec.Volumes != nil {
volumesYaml, err := ObjectToJSONORYaml("yaml", template.Spec.Volumes)
if err != nil {
logrus.Errorf("deployment:%v volumes %v", name, err)
}
volumesAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameVolumes,
SaveType: "yaml",
AttributeValue: volumesYaml,
}
attributes = append(attributes, volumesAttributes)
}
if template.Spec.Containers[0].VolumeMounts != nil {
volumeMountsYaml, err := ObjectToJSONORYaml("yaml", template.Spec.Containers[0].VolumeMounts)
if err != nil {
logrus.Errorf("deployment:%v volumeMounts %v", name, err)
}
volumeMountsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameVolumeMounts,
SaveType: "yaml",
AttributeValue: volumeMountsYaml,
}
attributes = append(attributes, volumeMountsAttributes)
}
if template.Spec.ServiceAccountName != "" {
serviceAccountAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameServiceAccountName,
SaveType: "string",
AttributeValue: template.Spec.ServiceAccountName,
}
attributes = append(attributes, serviceAccountAttributes)
}
if rsLabel != nil {
labelsJSON, err := ObjectToJSONORYaml("json", rsLabel)
if err != nil {
logrus.Errorf("deployment:%v labels %v", name, err)
}
labelsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameLabels,
SaveType: "json",
AttributeValue: labelsJSON,
}
attributes = append(attributes, labelsAttributes)
}
if template.Spec.NodeSelector != nil {
NodeSelectorJSON, err := ObjectToJSONORYaml("json", template.Spec.NodeSelector)
if err != nil {
logrus.Errorf("deployment:%v nodeSelector %v", name, err)
}
nodeSelectorAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameNodeSelector,
SaveType: "json",
AttributeValue: NodeSelectorJSON,
}
attributes = append(attributes, nodeSelectorAttributes)
}
if template.Spec.Tolerations != nil {
tolerationsYaml, err := ObjectToJSONORYaml("yaml", template.Spec.Tolerations)
if err != nil {
logrus.Errorf("deployment:%v tolerations %v", name, err)
}
tolerationsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameTolerations,
SaveType: "yaml",
AttributeValue: tolerationsYaml,
}
attributes = append(attributes, tolerationsAttributes)
}
if template.Spec.Affinity != nil {
affinityYaml, err := ObjectToJSONORYaml("yaml", template.Spec.Affinity)
if err != nil {
logrus.Errorf("deployment:%v affinity %v", name, err)
}
affinityAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameAffinity,
SaveType: "yaml",
AttributeValue: affinityYaml,
}
attributes = append(attributes, affinityAttributes)
}
if securityContext := template.Spec.Containers[0].SecurityContext; securityContext != nil && securityContext.Privileged != nil {
privilegedAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNamePrivileged,
SaveType: "string",
AttributeValue: strconv.FormatBool(*securityContext.Privileged),
}
attributes = append(attributes, privilegedAttributes)
}
*componentsCR = append(*componentsCR, model.ConvertResource{
ComponentsName: name,
BasicManagement: basic,
PortManagement: ps,
ENVManagement: envs,
ConfigManagement: configs,
TelescopicManagement: t,
HealthyCheckManagement: hcm,
ComponentK8sAttributesManagement: attributes,
})
}
func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others model.OtherResource, namespace string) []dbmodel.K8sResource {
var k8sResources []dbmodel.K8sResource
servicesMap := make(map[string]corev1.Service)
@ -567,11 +226,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: services.Name,
Kind: model.Service,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -596,11 +255,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: pvc.Name,
Kind: model.PVC,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -625,11 +284,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: ingresses.Name,
Kind: model.Ingress,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -653,11 +312,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: networkPolicies.Name,
Kind: model.NetworkPolicy,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -681,11 +340,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: configMaps.Name,
Kind: model.ConfigMap,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -709,11 +368,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: secrets.Name,
Kind: model.Secret,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -738,11 +397,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
continue
}
k8sResources = append(k8sResources, dbmodel.K8sResource{
Name: serviceAccounts.Name,
Kind: model.ServiceAccount,
Content: kubernetesResourcesYAML,
Success: 1,
Status: "创建成功",
Name: serviceAccounts.Name,
Kind: model.ServiceAccount,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -766,11 +425,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: roleBindings.Name,
Kind: model.RoleBinding,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -795,11 +454,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Success: 1,
Status: "创建成功",
Name: hpa.Name,
Kind: model.HorizontalPodAutoscaler,
Content: kubernetesResourcesYAML,
State: 1,
ErrorOverview: "创建成功",
})
}
}
@ -822,11 +481,11 @@ func (c *clusterAction) getAppKubernetesResources(ctx context.Context, others mo
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,
Status: "创建成功",
Success: 1,
Name: roles.Name,
Kind: model.Role,
Content: kubernetesResourcesYAML,
ErrorOverview: "创建成功",
State: 1,
})
}
}

View File

@ -13,7 +13,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/yaml"
yamlt "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/dynamic"
@ -27,28 +26,28 @@ func (c *clusterAction) AddAppK8SResource(ctx context.Context, namespace string,
var resourceList []*dbmodel.K8sResource
for _, resourceObject := range resourceObjects {
resource := resourceObject
if resourceObject.Success == 3 {
if resourceObject.State == 3 {
rsYaml := resourceYaml
if resourceObject.Resource != nil {
rsYaml, _ = ObjectToJSONORYaml("yaml", resourceObject.Resource)
}
resourceList = append(resourceList, &dbmodel.K8sResource{
AppID: appID,
Name: "未识别",
Kind: "未识别",
Content: rsYaml,
Status: resource.Status,
Success: resource.Success,
AppID: appID,
Name: "未识别",
Kind: "未识别",
Content: rsYaml,
ErrorOverview: resource.ErrorOverview,
State: resource.State,
})
} else {
rsYaml, _ := ObjectToJSONORYaml("yaml", resourceObject.Resource)
resourceList = append(resourceList, &dbmodel.K8sResource{
AppID: appID,
Name: resource.Resource.GetName(),
Kind: resource.Resource.GetKind(),
Content: rsYaml,
Status: resource.Status,
Success: resource.Success,
AppID: appID,
Name: resource.Resource.GetName(),
Kind: resource.Resource.GetKind(),
Content: rsYaml,
ErrorOverview: resource.ErrorOverview,
State: resource.State,
})
err := db.GetManager().K8sResourceDao().CreateK8sResourceInBatch(resourceList)
if err != nil {
@ -68,16 +67,16 @@ func (c *clusterAction) UpdateAppK8SResource(ctx context.Context, namespace, app
}
resourceObjects := c.HandleResourceYaml([]byte(resourceYaml), namespace, "update", name)
var rsYaml string
if resourceObjects[0].Success == 4 {
if resourceObjects[0].State == 4 {
rsYaml = resourceYaml
rs[0].Success = resourceObjects[0].Success
rs[0].Status = resourceObjects[0].Status
rs[0].State = resourceObjects[0].State
rs[0].ErrorOverview = resourceObjects[0].ErrorOverview
rs[0].Content = rsYaml
db.GetManager().K8sResourceDao().UpdateModel(&rs[0])
} else {
rsYaml, _ = ObjectToJSONORYaml("yaml", resourceObjects[0].Resource)
rs[0].Success = resourceObjects[0].Success
rs[0].Status = resourceObjects[0].Status
rs[0].State = resourceObjects[0].State
rs[0].ErrorOverview = resourceObjects[0].ErrorOverview
rs[0].Content = rsYaml
db.GetManager().K8sResourceDao().UpdateModel(&rs[0])
}
@ -95,43 +94,30 @@ func (c *clusterAction) DeleteAppK8SResource(ctx context.Context, namespace, app
return nil
}
//BuildResource -
type BuildResource struct {
Resource *unstructured.Unstructured
Success int
Status string
Dri dynamic.ResourceInterface
DC dynamic.Interface
GVK *schema.GroupVersionKind
}
//HandleResourceYaml -
func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string, change string, name string) []*BuildResource {
var buildResourceList []*BuildResource
var status string
var success int
func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string, change string, name string) []*model.BuildResource {
var buildResourceList []*model.BuildResource
var state int
if change == "create" {
status = "创建失败"
success = model.CreateError
state = model.CreateError
} else if change == "update" {
status = "更新失败"
success = model.UpdateError
state = model.UpdateError
}
dc, err := dynamic.NewForConfig(c.config)
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
resourceYamlByte := resourceYaml
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
@ -143,18 +129,18 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
break
}
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
obj, gvk, err := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme).Decode(rawObj.Raw, nil, nil)
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
@ -162,9 +148,9 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
@ -173,9 +159,9 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
gr, err := restmapper.GetAPIGroupResources(c.clientset.Discovery())
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = append(buildResourceList, &BuildResource{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = append(buildResourceList, &model.BuildResource{
State: state,
ErrorOverview: err.Error(),
})
continue
}
@ -183,9 +169,9 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
logrus.Errorf("%v", err)
buildResourceList = []*BuildResource{{
Success: success,
Status: fmt.Sprintf("%v%v", status, err),
buildResourceList = []*model.BuildResource{{
State: state,
ErrorOverview: err.Error(),
}}
return buildResourceList
}
@ -196,7 +182,7 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
} else {
dri = dc.Resource(mapping.Resource)
}
br := &BuildResource{
br := &model.BuildResource{
Resource: unstructuredObj,
Dri: dri,
}
@ -210,12 +196,12 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
if err != nil {
logrus.Errorf("k8s resource create error%v", err)
buildResource.Resource = unstructuredObj
buildResource.Success = success
buildResource.Status = fmt.Sprintf("%v%v", status, err)
buildResource.State = state
buildResource.ErrorOverview = err.Error()
} else {
buildResource.Resource = obj
buildResource.Success = model.CreateSuccess
buildResource.Status = fmt.Sprintf("创建成功")
buildResource.State = model.CreateSuccess
buildResource.ErrorOverview = fmt.Sprintf("创建成功")
}
case "delete":
err := buildResource.Dri.Delete(context.TODO(), name, metav1.DeleteOptions{})
@ -227,12 +213,12 @@ func (c *clusterAction) HandleResourceYaml(resourceYaml []byte, namespace string
if err != nil {
logrus.Errorf("update k8s resource error%v", err)
buildResource.Resource = unstructuredObj
buildResource.Success = success
buildResource.Status = fmt.Sprintf("%v%v", status, err)
buildResource.State = state
buildResource.ErrorOverview = err.Error()
} else {
buildResource.Resource = obj
buildResource.Success = model.UpdateSuccess
buildResource.Status = fmt.Sprintf("更新成功")
buildResource.State = model.UpdateSuccess
buildResource.ErrorOverview = fmt.Sprintf("更新成功")
}
}
}

View File

@ -14,7 +14,6 @@ import (
"github.com/sirupsen/logrus"
"github.com/twinj/uuid"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
"strings"
"time"
)
@ -433,22 +432,3 @@ func (c *clusterAction) createK8sAttributes(specials []*dbmodel.ComponentK8sAttr
logrus.Errorf("%v createSpecial creation failed:%v", component.ServiceAlias, err)
}
}
//ObjectToJSONORYaml changeType true is json / yaml
func ObjectToJSONORYaml(changeType string, data interface{}) (string, error) {
if data == nil {
return "", nil
}
dataJSON, err := json.Marshal(data)
if err != nil {
return "", fmt.Errorf("json serialization failed err:%v", err)
}
if changeType == "json" {
return string(dataJSON), nil
}
dataYaml, err := yaml.JSONToYAML(dataJSON)
if err != nil {
return "", fmt.Errorf("yaml serialization failed err:%v", err)
}
return string(dataYaml), nil
}

View File

@ -0,0 +1,416 @@
package handler
import (
"context"
"encoding/json"
"fmt"
"github.com/goodrain/rainbond/api/model"
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"path"
"sigs.k8s.io/yaml"
"strconv"
"strings"
)
func (c *clusterAction) PodTemplateSpecResource(parameter model.YamlResourceParameter) {
//Port
var ps []model.PortManagement
for _, port := range parameter.Template.Spec.Containers[0].Ports {
if string(port.Protocol) == "UDP" {
ps = append(ps, model.PortManagement{
Port: port.ContainerPort,
Protocol: "UDP",
Inner: false,
Outer: false,
})
continue
}
if string(port.Protocol) == "TCP" {
ps = append(ps, model.PortManagement{
Port: port.ContainerPort,
Protocol: "TCP",
Inner: false,
Outer: false,
})
continue
}
logrus.Warningf("Transport protocol type not recognized%v", port.Protocol)
}
//ENV
var envs []model.ENVManagement
for i := 0; i < len(parameter.Template.Spec.Containers[0].Env); i++ {
if cm := parameter.Template.Spec.Containers[0].Env[i].ValueFrom; cm == nil {
envs = append(envs, model.ENVManagement{
ENVKey: parameter.Template.Spec.Containers[0].Env[i].Name,
ENVValue: parameter.Template.Spec.Containers[0].Env[i].Value,
ENVExplain: "",
})
parameter.Template.Spec.Containers[0].Env = append(parameter.Template.Spec.Containers[0].Env[:i], parameter.Template.Spec.Containers[0].Env[i+1:]...)
}
}
//Configs
var configs []model.ConfigManagement
//这一块是处理配置文件
//配置文件的名字最终都是configmap里面的key值。
//volume在被挂载后存在四种情况
//第一种是volume存在itemsvolumeMount的SubPath不等于空。路径直接是volumeMount里面的mountPath。
//第二种是volume存在itemsvolumeMount的SubPath等于空。路径则变成volumeMount里面的mountPath拼接上items里面每一个元素的key值。
//第三种是volume不存在itemsvolumeMount的SubPath不等于空。路径直接是volumeMount里面的mountPath。
//第四种是volume不存在itemsvolumeMount的SubPath等于空。路径则变成volumeMount里面的mountPath拼接上configmap资源里面每一个元素的key值
cmMap := make(map[string]corev1.ConfigMap)
cmList, err := c.clientset.CoreV1().ConfigMaps(parameter.Namespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to get ConfigMap%v", err)
}
cmList.Items = append(cmList.Items, parameter.CMs...)
for _, volume := range parameter.Template.Spec.Volumes {
for _, cm := range cmList.Items {
cmMap[cm.Name] = cm
}
if volume.ConfigMap != nil && err == nil {
cm, _ := cmMap[volume.ConfigMap.Name]
cmData := cm.Data
isLog := true
for _, volumeMount := range parameter.Template.Spec.Containers[0].VolumeMounts {
if volume.Name != volumeMount.Name {
continue
}
isLog = false
if volume.ConfigMap.Items != nil {
if volumeMount.SubPath != "" {
configName := ""
var mode int32
for _, item := range volume.ConfigMap.Items {
if item.Path == volumeMount.SubPath {
configName = item.Key
mode = *item.Mode
}
}
configs = append(configs, model.ConfigManagement{
ConfigName: configName,
ConfigPath: volumeMount.MountPath,
ConfigValue: cmData[configName],
Mode: mode,
})
continue
}
p := volumeMount.MountPath
for _, item := range volume.ConfigMap.Items {
p := path.Join(p, item.Path)
var mode int32
if item.Mode != nil {
mode = *item.Mode
}
configs = append(configs, model.ConfigManagement{
ConfigName: item.Key,
ConfigPath: p,
ConfigValue: cmData[item.Key],
Mode: mode,
})
}
} else {
mode := int32(777)
if volume.ConfigMap.DefaultMode != nil {
mode = *volume.ConfigMap.DefaultMode
}
if volumeMount.SubPath != "" {
configs = append(configs, model.ConfigManagement{
ConfigName: volumeMount.SubPath,
ConfigPath: volumeMount.MountPath,
ConfigValue: cmData[volumeMount.SubPath],
Mode: mode,
})
continue
}
mountPath := volumeMount.MountPath
for key, val := range cmData {
mountPath = path.Join(mountPath, key)
configs = append(configs, model.ConfigManagement{
ConfigName: key,
ConfigPath: mountPath,
ConfigValue: val,
Mode: *volume.ConfigMap.DefaultMode,
})
}
}
}
if isLog {
logrus.Warningf("configmap type resource %v is not mounted in volumemount", volume.ConfigMap.Name)
}
}
}
//TelescopicManagement
HPAList, err := c.clientset.AutoscalingV1().HorizontalPodAutoscalers(parameter.Namespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to get HorizontalPodAutoscalers list:%v", err)
}
HPAList.Items = append(HPAList.Items, parameter.HPAs...)
var t model.TelescopicManagement
//这一块就是自动伸缩的对应解析,
//需要注意的一点是hpa的cpu和memory的阈值设置是通过Annotations["autoscaling.alpha.kubernetes.io/metrics"]字段设置
//而且它的返回值是个json字符串所以设置了一个结构体进行解析。
for _, hpa := range HPAList.Items {
if (hpa.Spec.ScaleTargetRef.Kind != model.Deployment && hpa.Spec.ScaleTargetRef.Kind != model.StateFulSet) || hpa.Spec.ScaleTargetRef.Name != parameter.Name {
t.Enable = false
continue
}
t.Enable = true
t.MinReplicas = *hpa.Spec.MinReplicas
t.MaxReplicas = hpa.Spec.MaxReplicas
var cpuormemorys []*dbmodel.TenantServiceAutoscalerRuleMetrics
cpuUsage := hpa.Spec.TargetCPUUtilizationPercentage
if cpuUsage != nil {
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "utilization",
MetricTargetValue: int(*cpuUsage),
})
}
CPUAndMemoryJSON, ok := hpa.Annotations["autoscaling.alpha.kubernetes.io/metrics"]
if ok {
type com struct {
T string `json:"type"`
Resource map[string]interface{}
}
var c []com
err := json.Unmarshal([]byte(CPUAndMemoryJSON), &c)
if err != nil {
logrus.Errorf("autoscaling.alpha.kubernetes.io/metrics parsing failed%v", err)
}
for _, cpuormemory := range c {
switch cpuormemory.Resource["name"] {
case "cpu":
cpu := fmt.Sprint(cpuormemory.Resource["targetAverageValue"])
cpuUnit := cpu[len(cpu)-1:]
var cpuUsage int
if cpuUnit == "m" {
cpuUsage, _ = strconv.Atoi(cpu[:len(cpu)-1])
}
if cpuUnit == "g" || cpuUnit == "G" {
cpuUsage, _ = strconv.Atoi(cpu[:len(cpu)-1])
cpuUsage = cpuUsage * 1024
}
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "average_value",
MetricTargetValue: cpuUsage,
})
case "memory":
memory := fmt.Sprint(cpuormemory.Resource["targetAverageValue"])
memoryUnit := memory[:len(memory)-1]
var MemoryUsage int
if memoryUnit == "m" {
MemoryUsage, _ = strconv.Atoi(memory[:len(memory)-1])
}
if memoryUnit == "g" || memoryUnit == "G" {
MemoryUsage, _ = strconv.Atoi(memory[:len(memory)-1])
MemoryUsage = MemoryUsage * 1024
}
cpuormemorys = append(cpuormemorys, &dbmodel.TenantServiceAutoscalerRuleMetrics{
MetricsType: "resource_metrics",
MetricsName: "cpu",
MetricTargetType: "average_value",
MetricTargetValue: MemoryUsage,
})
}
}
}
t.CPUOrMemory = cpuormemorys
}
//HealthyCheckManagement
var hcm model.HealthyCheckManagement
livenessProbe := parameter.Template.Spec.Containers[0].LivenessProbe
if livenessProbe != nil {
var httpHeaders []string
if livenessProbe.HTTPGet != nil {
for _, httpHeader := range livenessProbe.HTTPGet.HTTPHeaders {
nv := httpHeader.Name + "=" + httpHeader.Value
httpHeaders = append(httpHeaders, nv)
}
hcm.DetectionMethod = strings.ToLower(string(livenessProbe.HTTPGet.Scheme))
hcm.Path = livenessProbe.HTTPGet.Path
hcm.Port = int(livenessProbe.HTTPGet.Port.IntVal)
}
hcm.Status = 1
if livenessProbe.Exec != nil {
hcm.Command = strings.Join(livenessProbe.Exec.Command, " ")
}
hcm.HTTPHeader = strings.Join(httpHeaders, ",")
hcm.Mode = "liveness"
hcm.InitialDelaySecond = int(livenessProbe.InitialDelaySeconds)
hcm.PeriodSecond = int(livenessProbe.PeriodSeconds)
hcm.TimeoutSecond = int(livenessProbe.TimeoutSeconds)
hcm.FailureThreshold = int(livenessProbe.FailureThreshold)
hcm.SuccessThreshold = int(livenessProbe.SuccessThreshold)
} else {
readinessProbe := parameter.Template.Spec.Containers[0].ReadinessProbe
if readinessProbe != nil {
var httpHeaders []string
if readinessProbe.HTTPGet != nil {
for _, httpHeader := range readinessProbe.HTTPGet.HTTPHeaders {
nv := httpHeader.Name + "=" + httpHeader.Value
httpHeaders = append(httpHeaders, nv)
}
hcm.DetectionMethod = strings.ToLower(string(readinessProbe.HTTPGet.Scheme))
hcm.Path = readinessProbe.HTTPGet.Path
hcm.Port = int(readinessProbe.HTTPGet.Port.IntVal)
}
hcm.Status = 1
hcm.Mode = "readiness"
if readinessProbe.Exec != nil {
hcm.Command = strings.Join(readinessProbe.Exec.Command, " ")
}
hcm.HTTPHeader = strings.Join(httpHeaders, ",")
hcm.InitialDelaySecond = int(readinessProbe.InitialDelaySeconds)
hcm.PeriodSecond = int(readinessProbe.PeriodSeconds)
hcm.TimeoutSecond = int(readinessProbe.TimeoutSeconds)
hcm.FailureThreshold = int(readinessProbe.FailureThreshold)
hcm.SuccessThreshold = int(readinessProbe.SuccessThreshold)
}
}
var attributes []*dbmodel.ComponentK8sAttributes
if parameter.Template.Spec.Containers[0].Env != nil && len(parameter.Template.Spec.Containers[0].Env) > 0 {
envYaml, err := ObjectToJSONORYaml("yaml", parameter.Template.Spec.Containers[0].Env)
if err != nil {
logrus.Errorf("deployment:%v env %v", parameter.Name, err)
}
envAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameENV,
SaveType: "yaml",
AttributeValue: envYaml,
}
attributes = append(attributes, envAttributes)
}
if parameter.Template.Spec.Volumes != nil {
volumesYaml, err := ObjectToJSONORYaml("yaml", parameter.Template.Spec.Volumes)
if err != nil {
logrus.Errorf("deployment:%v volumes %v", parameter.Name, err)
}
volumesAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameVolumes,
SaveType: "yaml",
AttributeValue: volumesYaml,
}
attributes = append(attributes, volumesAttributes)
}
if parameter.Template.Spec.Containers[0].VolumeMounts != nil {
volumeMountsYaml, err := ObjectToJSONORYaml("yaml", parameter.Template.Spec.Containers[0].VolumeMounts)
if err != nil {
logrus.Errorf("deployment:%v volumeMounts %v", parameter.Name, err)
}
volumeMountsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameVolumeMounts,
SaveType: "yaml",
AttributeValue: volumeMountsYaml,
}
attributes = append(attributes, volumeMountsAttributes)
}
if parameter.Template.Spec.ServiceAccountName != "" {
serviceAccountAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameServiceAccountName,
SaveType: "string",
AttributeValue: parameter.Template.Spec.ServiceAccountName,
}
attributes = append(attributes, serviceAccountAttributes)
}
if parameter.RsLabel != nil {
labelsJSON, err := ObjectToJSONORYaml("json", parameter.RsLabel)
if err != nil {
logrus.Errorf("deployment:%v labels %v", parameter.Name, err)
}
labelsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameLabels,
SaveType: "json",
AttributeValue: labelsJSON,
}
attributes = append(attributes, labelsAttributes)
}
if parameter.Template.Spec.NodeSelector != nil {
NodeSelectorJSON, err := ObjectToJSONORYaml("json", parameter.Template.Spec.NodeSelector)
if err != nil {
logrus.Errorf("deployment:%v nodeSelector %v", parameter.Name, err)
}
nodeSelectorAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameNodeSelector,
SaveType: "json",
AttributeValue: NodeSelectorJSON,
}
attributes = append(attributes, nodeSelectorAttributes)
}
if parameter.Template.Spec.Tolerations != nil {
tolerationsYaml, err := ObjectToJSONORYaml("yaml", parameter.Template.Spec.Tolerations)
if err != nil {
logrus.Errorf("deployment:%v tolerations %v", parameter.Name, err)
}
tolerationsAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameTolerations,
SaveType: "yaml",
AttributeValue: tolerationsYaml,
}
attributes = append(attributes, tolerationsAttributes)
}
if parameter.Template.Spec.Affinity != nil {
affinityYaml, err := ObjectToJSONORYaml("yaml", parameter.Template.Spec.Affinity)
if err != nil {
logrus.Errorf("deployment:%v affinity %v", parameter.Name, err)
}
affinityAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNameAffinity,
SaveType: "yaml",
AttributeValue: affinityYaml,
}
attributes = append(attributes, affinityAttributes)
}
if securityContext := parameter.Template.Spec.Containers[0].SecurityContext; securityContext != nil && securityContext.Privileged != nil {
privilegedAttributes := &dbmodel.ComponentK8sAttributes{
Name: dbmodel.K8sAttributeNamePrivileged,
SaveType: "string",
AttributeValue: strconv.FormatBool(*securityContext.Privileged),
}
attributes = append(attributes, privilegedAttributes)
}
*parameter.ComponentsCR = append(*parameter.ComponentsCR, model.ConvertResource{
ComponentsName: parameter.Name,
BasicManagement: parameter.Basic,
PortManagement: ps,
ENVManagement: envs,
ConfigManagement: configs,
TelescopicManagement: t,
HealthyCheckManagement: hcm,
ComponentK8sAttributesManagement: attributes,
})
}
//ObjectToJSONORYaml changeType true is json / yaml
func ObjectToJSONORYaml(changeType string, data interface{}) (string, error) {
if data == nil {
return "", nil
}
dataJSON, err := json.Marshal(data)
if err != nil {
return "", fmt.Errorf("json serialization failed err:%v", err)
}
if changeType == "json" {
return string(dataJSON), nil
}
dataYaml, err := yaml.JSONToYAML(dataJSON)
if err != nil {
return "", fmt.Errorf("yaml serialization failed err:%v", err)
}
return string(dataYaml), nil
}

View File

@ -0,0 +1,612 @@
package handler
import (
"bytes"
"context"
"encoding/json"
"fmt"
api_model "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/api/util"
"github.com/goodrain/rainbond/db"
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/jinzhu/gorm"
"github.com/sirupsen/logrus"
"io/ioutil"
appv1 "k8s.io/api/apps/v1"
autoscalingv1 "k8s.io/api/autoscaling/v1"
batchv1 "k8s.io/api/batch/v1"
"k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/yaml"
yamlt "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/restmapper"
"path"
"path/filepath"
"strings"
)
//AppYamlResourceName -
func (c *clusterAction) AppYamlResourceName(yamlResource api_model.YamlResource) (map[string]api_model.LabelResource, *util.APIHandleError) {
fileResource := make(map[string]api_model.LabelResource)
k8sResourceObjects := c.YamlToResource(yamlResource)
var DeployNames, JobNames, CJNames, SFSNames, RoleNames, HPANames, RBNames, SANames, SecretNames, ServiceNames, CMNames, NetworkPolicyNames, IngressNames, PVCNames []string
defaultResource := make(map[string][]string)
for _, k8sResourceObject := range k8sResourceObjects {
if k8sResourceObject.Error != "" {
fileResource[k8sResourceObject.FileName] = api_model.LabelResource{
Status: k8sResourceObject.Error,
}
continue
}
for _, buildResource := range k8sResourceObject.BuildResources {
switch buildResource.Resource.GetKind() {
case api_model.Deployment:
DeployNames = append(DeployNames, buildResource.Resource.GetName())
case api_model.Job:
JobNames = append(JobNames, buildResource.Resource.GetName())
case api_model.CronJob:
CJNames = append(CJNames, buildResource.Resource.GetName())
case api_model.StateFulSet:
SFSNames = append(SFSNames, buildResource.Resource.GetName())
case api_model.Role:
RoleNames = append(RoleNames, buildResource.Resource.GetName())
case api_model.HorizontalPodAutoscaler:
HPANames = append(HPANames, buildResource.Resource.GetName())
case api_model.RoleBinding:
RBNames = append(RBNames, buildResource.Resource.GetName())
case api_model.ServiceAccount:
SANames = append(SANames, buildResource.Resource.GetName())
case api_model.Secret:
SecretNames = append(SecretNames, buildResource.Resource.GetName())
case api_model.Service:
ServiceNames = append(ServiceNames, buildResource.Resource.GetName())
case api_model.ConfigMap:
CMNames = append(CMNames, buildResource.Resource.GetName())
case api_model.NetworkPolicy:
NetworkPolicyNames = append(NetworkPolicyNames, buildResource.Resource.GetName())
case api_model.Ingress:
IngressNames = append(IngressNames, buildResource.Resource.GetName())
case api_model.PVC:
PVCNames = append(PVCNames, buildResource.Resource.GetName())
default:
defaultNames, ok := defaultResource[buildResource.Resource.GetKind()]
if ok {
defaultResource[buildResource.Resource.GetKind()] = append(defaultNames, buildResource.Resource.GetName())
} else {
defaultResource[buildResource.Resource.GetKind()] = []string{buildResource.Resource.GetName()}
}
}
}
}
fileResource["app_resource"] = api_model.LabelResource{
UnSupport: defaultResource,
Workloads: api_model.WorkLoadsResource{
Deployments: DeployNames,
Jobs: JobNames,
CronJobs: CJNames,
StateFulSets: SFSNames,
},
Others: api_model.OtherResource{
Services: ServiceNames,
PVC: PVCNames,
Ingresses: IngressNames,
NetworkPolicies: NetworkPolicyNames,
ConfigMaps: CMNames,
Secrets: SecretNames,
ServiceAccounts: ServiceNames,
RoleBindings: RoleNames,
HorizontalPodAutoscalers: HPANames,
Roles: RoleNames,
},
Status: "",
}
return fileResource, nil
}
//AppYamlResourceDetailed -
func (c *clusterAction) AppYamlResourceDetailed(yamlResource api_model.YamlResource, yamlImport bool) (api_model.ApplicationResource, *util.APIHandleError) {
k8sResourceObjects := c.YamlToResource(yamlResource)
var K8SResource []dbmodel.K8sResource
var ConvertResource []api_model.ConvertResource
for _, k8sResourceObject := range k8sResourceObjects {
if k8sResourceObject.Error != "" {
continue
}
var cms []corev1.ConfigMap
var hpas []autoscalingv1.HorizontalPodAutoscaler
for _, buildResource := range k8sResourceObject.BuildResources {
if buildResource.Resource.GetKind() == api_model.ConfigMap {
var cm corev1.ConfigMap
cmJSON, _ := json.Marshal(buildResource.Resource)
json.Unmarshal(cmJSON, &cm)
cms = append(cms, cm)
continue
}
if buildResource.Resource.GetKind() == api_model.HorizontalPodAutoscaler {
var hpa autoscalingv1.HorizontalPodAutoscaler
cmJSON, _ := json.Marshal(buildResource.Resource)
json.Unmarshal(cmJSON, &hpa)
hpas = append(hpas, hpa)
}
}
for _, buildResource := range k8sResourceObject.BuildResources {
errorOverview := "创建成功"
state := 1
switch buildResource.Resource.GetKind() {
case api_model.Deployment:
deployJSON, _ := json.Marshal(buildResource.Resource)
var deployObject appv1.Deployment
json.Unmarshal(deployJSON, &deployObject)
basic := api_model.BasicManagement{
ResourceType: api_model.Deployment,
Replicas: deployObject.Spec.Replicas,
Memory: deployObject.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() / 1024 / 1024,
CPU: deployObject.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().Value(),
Image: deployObject.Spec.Template.Spec.Containers[0].Image,
Cmd: strings.Join(append(deployObject.Spec.Template.Spec.Containers[0].Command, deployObject.Spec.Template.Spec.Containers[0].Args...), " "),
}
parameter := api_model.YamlResourceParameter{
ComponentsCR: &ConvertResource,
Basic: basic,
Template: deployObject.Spec.Template,
Namespace: yamlResource.Namespace,
Name: buildResource.Resource.GetName(),
RsLabel: deployObject.Labels,
HPAs: hpas,
CMs: cms,
}
c.PodTemplateSpecResource(parameter)
case api_model.Job:
jobJSON, _ := json.Marshal(buildResource.Resource)
var jobObject batchv1.Job
json.Unmarshal(jobJSON, &jobObject)
basic := api_model.BasicManagement{
ResourceType: api_model.Job,
Replicas: jobObject.Spec.Completions,
Memory: jobObject.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() / 1024 / 1024,
CPU: jobObject.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().Value(),
Image: jobObject.Spec.Template.Spec.Containers[0].Image,
Cmd: strings.Join(append(jobObject.Spec.Template.Spec.Containers[0].Command, jobObject.Spec.Template.Spec.Containers[0].Args...), " "),
}
parameter := api_model.YamlResourceParameter{
ComponentsCR: &ConvertResource,
Basic: basic,
Template: jobObject.Spec.Template,
Namespace: yamlResource.Namespace,
Name: buildResource.Resource.GetName(),
RsLabel: jobObject.Labels,
HPAs: hpas,
CMs: cms,
}
c.PodTemplateSpecResource(parameter)
case api_model.CronJob:
cjJSON, _ := json.Marshal(buildResource.Resource)
var cjObject v1beta1.CronJob
json.Unmarshal(cjJSON, &cjObject)
basic := api_model.BasicManagement{
ResourceType: api_model.Job,
Replicas: cjObject.Spec.JobTemplate.Spec.Completions,
Memory: cjObject.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() / 1024 / 1024,
CPU: cjObject.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().Value(),
Image: cjObject.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Image,
Cmd: strings.Join(append(cjObject.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Command, cjObject.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Args...), " "),
}
parameter := api_model.YamlResourceParameter{
ComponentsCR: &ConvertResource,
Basic: basic,
Template: cjObject.Spec.JobTemplate.Spec.Template,
Namespace: yamlResource.Namespace,
Name: buildResource.Resource.GetName(),
RsLabel: cjObject.Labels,
HPAs: hpas,
CMs: cms,
}
c.PodTemplateSpecResource(parameter)
case api_model.StateFulSet:
sfsJSON, _ := json.Marshal(buildResource.Resource)
var sfsObject appv1.StatefulSet
json.Unmarshal(sfsJSON, &sfsObject)
basic := api_model.BasicManagement{
ResourceType: api_model.Deployment,
Replicas: sfsObject.Spec.Replicas,
Memory: sfsObject.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().Value() / 1024 / 1024,
CPU: sfsObject.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().Value(),
Image: sfsObject.Spec.Template.Spec.Containers[0].Image,
Cmd: strings.Join(append(sfsObject.Spec.Template.Spec.Containers[0].Command, sfsObject.Spec.Template.Spec.Containers[0].Args...), " "),
}
parameter := api_model.YamlResourceParameter{
ComponentsCR: &ConvertResource,
Basic: basic,
Template: sfsObject.Spec.Template,
Namespace: yamlResource.Namespace,
Name: buildResource.Resource.GetName(),
RsLabel: sfsObject.Labels,
HPAs: hpas,
CMs: cms,
}
c.PodTemplateSpecResource(parameter)
case api_model.Role:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v Role:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.Role,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.HorizontalPodAutoscaler:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v HorizontalPodAutoscaler:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.HorizontalPodAutoscaler,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.RoleBinding:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v RoleBinding:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.HorizontalPodAutoscaler,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.ServiceAccount:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v ServiceAccount:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.HorizontalPodAutoscaler,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.Secret:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v Secret:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.Secret,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.Service:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v Service:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.Service,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.ConfigMap:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v ConfigMap:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.ConfigMap,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.NetworkPolicy:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v NetworkPolicy:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.NetworkPolicy,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.Ingress:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v Ingress:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.Ingress,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
case api_model.PVC:
if yamlImport {
resource, err := c.ResourceCreate(buildResource, yamlResource.Namespace)
if err != nil {
errorOverview = err.Error()
state = 3
} else {
buildResource.Resource = resource
}
}
kubernetesResourcesYAML, err := ObjectToJSONORYaml("yaml", buildResource.Resource)
if err != nil {
logrus.Errorf("namespace:%v PVC:%v error: %v", yamlResource.Namespace, buildResource.Resource.GetName(), err)
}
K8SResource = append(K8SResource, dbmodel.K8sResource{
Name: buildResource.Resource.GetName(),
Kind: api_model.PVC,
Content: kubernetesResourcesYAML,
State: state,
ErrorOverview: errorOverview,
})
}
}
}
return api_model.ApplicationResource{
K8SResource,
ConvertResource,
}, nil
}
//AppYamlResourceImport -
func (c *clusterAction) AppYamlResourceImport(yamlResource api_model.YamlResource, components api_model.ApplicationResource) (api_model.AppComponent, *util.APIHandleError) {
app, err := db.GetManager().ApplicationDao().GetAppByID(yamlResource.AppID)
if err != nil {
return api_model.AppComponent{}, &util.APIHandleError{Code: 400, Err: fmt.Errorf("GetAppByID error %v", err)}
}
var ar api_model.AppComponent
err = db.GetManager().DB().Transaction(func(tx *gorm.DB) error {
k8sResource, err := c.CreateK8sResource(tx, components.KubernetesResources, app.AppID)
if err != nil {
logrus.Errorf("create K8sResources err:%v", err)
return &util.APIHandleError{Code: 400, Err: fmt.Errorf("create K8sResources err:%v", err)}
}
var componentAttributes []api_model.ComponentAttributes
for _, componentResource := range components.ConvertResource {
component, err := c.CreateComponent(app, yamlResource.TenantID, componentResource, yamlResource.Namespace)
if err != nil {
logrus.Errorf("%v", err)
return &util.APIHandleError{Code: 400, Err: fmt.Errorf("create app error:%v", err)}
}
c.createENV(componentResource.ENVManagement, component)
c.createConfig(componentResource.ConfigManagement, component)
c.createPort(componentResource.PortManagement, component)
componentResource.TelescopicManagement.RuleID = c.createTelescopic(componentResource.TelescopicManagement, component)
componentResource.HealthyCheckManagement.ProbeID = c.createHealthyCheck(componentResource.HealthyCheckManagement, component)
c.createK8sAttributes(componentResource.ComponentK8sAttributesManagement, yamlResource.TenantID, component)
componentAttributes = append(componentAttributes, api_model.ComponentAttributes{
TS: component,
Image: componentResource.BasicManagement.Image,
Cmd: componentResource.BasicManagement.Cmd,
ENV: componentResource.ENVManagement,
Config: componentResource.ConfigManagement,
Port: componentResource.PortManagement,
Telescopic: componentResource.TelescopicManagement,
HealthyCheck: componentResource.HealthyCheckManagement,
ComponentK8sAttributes: componentResource.ComponentK8sAttributesManagement,
})
}
ar = api_model.AppComponent{
App: app,
K8sResources: k8sResource,
Component: componentAttributes,
}
return nil
})
if err != nil {
return api_model.AppComponent{}, &util.APIHandleError{Code: 400, Err: fmt.Errorf("app yaml resource import error:%v", err)}
}
return ar, nil
}
//YamlToResource -
func (c *clusterAction) YamlToResource(yamlResource api_model.YamlResource) []api_model.K8sResourceObject {
yamlDirectoryPath := path.Join("/grdata/package_build/temp/events", yamlResource.EventID, "*")
yamlFilesPath, _ := filepath.Glob(yamlDirectoryPath)
var fileBuildResourceList []api_model.K8sResourceObject
for _, yamlFilePath := range yamlFilesPath {
pathSplitList := strings.Split(yamlFilePath, "/")
fileName := pathSplitList[len(pathSplitList)-1]
yamlFileBytes, err := ioutil.ReadFile(yamlFilePath)
if err != nil {
logrus.Errorf("%v", err)
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: nil,
Error: err.Error(),
})
continue
}
dc, err := dynamic.NewForConfig(c.config)
if err != nil {
logrus.Errorf("%v", err)
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: nil,
Error: err.Error(),
})
continue
}
decoder := yamlt.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFileBytes), 1000)
var buildResourceList []api_model.BuildResource
for {
var rawObj runtime.RawExtension
if err = decoder.Decode(&rawObj); err != nil {
if err.Error() == "EOF" {
break
}
logrus.Errorf("%v", err)
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: nil,
Error: err.Error(),
})
break
}
obj, gvk, err := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme).Decode(rawObj.Raw, nil, nil)
if err != nil {
logrus.Errorf("%v", err)
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: nil,
Error: err.Error(),
})
break
}
unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
logrus.Errorf("%v", err)
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: nil,
Error: err.Error(),
})
break
}
unstructuredObj := &unstructured.Unstructured{Object: unstructuredMap}
buildResourceList = append(buildResourceList, api_model.BuildResource{
Resource: unstructuredObj,
State: api_model.CreateError,
ErrorOverview: "",
Dri: nil,
DC: dc,
GVK: gvk,
})
}
fileBuildResourceList = append(fileBuildResourceList, api_model.K8sResourceObject{
FileName: fileName,
BuildResources: buildResourceList,
Error: "",
})
}
return fileBuildResourceList
}
//ResourceCreate -
func (c *clusterAction) ResourceCreate(buildResource api_model.BuildResource, namespace string) (*unstructured.Unstructured, error) {
gr, err := restmapper.GetAPIGroupResources(c.clientset.Discovery())
if err != nil {
logrus.Errorf("%v", err)
return nil, err
}
mapper := restmapper.NewDiscoveryRESTMapper(gr)
mapping, err := mapper.RESTMapping(buildResource.GVK.GroupKind(), buildResource.GVK.Version)
if err != nil {
logrus.Errorf("%v", err)
return nil, err
}
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
buildResource.Resource.SetNamespace(namespace)
buildResource.Dri = buildResource.DC.Resource(mapping.Resource).Namespace(buildResource.Resource.GetNamespace())
} else {
buildResource.Dri = buildResource.DC.Resource(mapping.Resource)
}
obj, err := buildResource.Dri.Create(context.Background(), buildResource.Resource, metav1.CreateOptions{})
if err != nil {
return nil, err
}
return obj, nil
}

View File

@ -469,7 +469,7 @@ type HandleResource struct {
//YamlResource -
type YamlResource struct {
EventID string `json:"event_id"`
K8SApp string `json:"k8s_app"`
AppID string `json:"region_app_id"`
TenantID string `json:"tenant_id"`
Namespace string `json:"namespace"`
}
@ -2059,4 +2059,3 @@ type SyncAppConfigGroup struct {
type AppStatusesReq struct {
AppIDs []string `json:"app_ids"`
}

View File

@ -1,5 +1,13 @@
package model
import (
autoscalingv1 "k8s.io/api/autoscaling/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
)
//LabelResource -
type LabelResource struct {
Workloads WorkLoadsResource `json:"workloads,omitempty"`
@ -30,6 +38,25 @@ type LabelOthersResourceProcess struct {
Roles map[string][]string `json:"roles,omitempty"`
}
//YamlResourceParameter -
type YamlResourceParameter struct {
ComponentsCR *[]ConvertResource
Basic BasicManagement
Template corev1.PodTemplateSpec
Namespace string
Name string
RsLabel map[string]string
CMs []corev1.ConfigMap
HPAs []autoscalingv1.HorizontalPodAutoscaler
}
//K8sResourceObject -
type K8sResourceObject struct {
FileName string
BuildResources []BuildResource
Error string
}
//WorkLoadsResource -
type WorkLoadsResource struct {
Deployments []string `json:"deployments,omitempty"`
@ -38,6 +65,16 @@ type WorkLoadsResource struct {
StateFulSets []string `json:"state_ful_sets,omitempty"`
}
//BuildResource -
type BuildResource struct {
Resource *unstructured.Unstructured
State int
ErrorOverview string
Dri dynamic.ResourceInterface
DC dynamic.Interface
GVK *schema.GroupVersionKind
}
//OtherResource -
type OtherResource struct {
Services []string `json:"services,omitempty"`

View File

@ -105,10 +105,10 @@ type K8sResource struct {
Kind string `gorm:"column:kind" json:"kind"`
// Yaml file for the storage resource
Content string `gorm:"column:content;type:longtext" json:"content"`
// resource create status
Status string `gorm:"column:status;type:longtext" json:"status"`
// resource create error overview
ErrorOverview string `gorm:"column:status;type:longtext" json:"error_overview"`
//whether it was created successfully
Success int `gorm:"column:success;type:int" json:"success"`
State int `gorm:"column:success;type:int" json:"state"`
}
// TableName return tableName "k8s_resources"