From dd90d8b542dca4c0450b88ff4237a053be5ad692 Mon Sep 17 00:00:00 2001 From: wilhelmguo Date: Mon, 17 Dec 2018 18:25:28 +0800 Subject: [PATCH 1/5] backend: update deployment add check, prevent orphan ReplicaSet --- .../resources/deployment/deployment.go | 36 +++++++++++++++++++ src/backend/util/maps/maps.go | 15 ++++++++ 2 files changed, 51 insertions(+) diff --git a/src/backend/resources/deployment/deployment.go b/src/backend/resources/deployment/deployment.go index f420c8427..efdff4015 100644 --- a/src/backend/resources/deployment/deployment.go +++ b/src/backend/resources/deployment/deployment.go @@ -1,10 +1,13 @@ package deployment import ( + "fmt" + "github.com/Qihoo360/wayne/src/backend/client" "github.com/Qihoo360/wayne/src/backend/resources/common" "github.com/Qihoo360/wayne/src/backend/resources/event" "github.com/Qihoo360/wayne/src/backend/resources/pod" + "github.com/Qihoo360/wayne/src/backend/util/maps" "k8s.io/api/apps/v1beta1" "k8s.io/apimachinery/pkg/api/errors" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,16 +54,49 @@ func CreateOrUpdateDeployment(cli *kubernetes.Clientset, deployment *v1beta1.Dep } return nil, err } + err = checkDeploymentLabelSelector(deployment, old) + if err != nil { + return nil, err + } + old.Labels = deployment.Labels old.Annotations = deployment.Annotations old.Spec = deployment.Spec return cli.AppsV1beta1().Deployments(deployment.Namespace).Update(old) } + func UpdateDeployment(cli *kubernetes.Clientset, deployment *v1beta1.Deployment) (*v1beta1.Deployment, error) { + old, err := cli.AppsV1beta1().Deployments(deployment.Namespace).Get(deployment.Name, metaV1.GetOptions{}) + if err != nil { + return nil, err + } + + err = checkDeploymentLabelSelector(deployment, old) + if err != nil { + return nil, err + } + return cli.AppsV1beta1().Deployments(deployment.Namespace).Update(deployment) } +// check Deployment .Spec.Selector.MatchLabels, prevent orphan ReplicaSet +// old deployment .Spec.Selector.MatchLabels labels should contain all new deployment .Spec.Selector.MatchLabels labels +// e.g. old Deployment .Spec.Selector.MatchLabels is app = infra-wayne,wayne-app = infra +// new Deployment .Spec.Selector.MatchLabels valid labels is +// app = infra-wayne or wayne-app = infra or app = infra-wayne,wayne-app = infra +func checkDeploymentLabelSelector(new *v1beta1.Deployment, old *v1beta1.Deployment) error { + for key, value := range new.Spec.Selector.MatchLabels { + oldValue, ok := old.Spec.Selector.MatchLabels[key] + if !ok || oldValue != value { + return fmt.Errorf("New's Deployment .Spec.Selector.MatchLabels(%s) not match old MatchLabels(%s),do not allow deploy to prevent the orphan ReplicaSet. ", + maps.LabelsToString(new.Spec.Selector.MatchLabels), maps.LabelsToString(old.Spec.Selector.MatchLabels)) + } + } + + return nil +} + func GetDeployment(cli *kubernetes.Clientset, name, namespace string) (*v1beta1.Deployment, error) { return cli.AppsV1beta1().Deployments(namespace).Get(name, metaV1.GetOptions{}) } diff --git a/src/backend/util/maps/maps.go b/src/backend/util/maps/maps.go index c49884a5b..75bc11986 100644 --- a/src/backend/util/maps/maps.go +++ b/src/backend/util/maps/maps.go @@ -1,5 +1,10 @@ package maps +import ( + "fmt" + "strings" +) + // merge label // the new map will overwrite the old one. // e.g. new: {"foo": "newbar"} old: {"foo": "bar"} will return {"foo": "newbar"} @@ -17,3 +22,13 @@ func MergeLabels(old map[string]string, new map[string]string) map[string]string } return old } + +func LabelsToString(labels map[string]string) string { + result := make([]string, len(labels)) + for k, v := range labels { + result = append(result, fmt.Sprintf("%s=%s", k, v)) + + } + + return strings.Join(result, ",") +} From d11e23e3add849d73f1ac365ca95b28a22fca184 Mon Sep 17 00:00:00 2001 From: wilhelmguo Date: Tue, 18 Dec 2018 16:34:37 +0800 Subject: [PATCH 2/5] backend: move errorresult to util package --- src/backend/controllers/auth/authenticator.go | 3 ++- src/backend/controllers/base/logged.go | 3 ++- src/backend/controllers/base/resulthandler.go | 22 ++++--------------- .../kubernetes/deployment/deployment.go | 7 +++--- .../kubernetes/statefulset/statefulset.go | 7 +++--- .../resources/deployment/deployment.go | 9 ++++++-- src/backend/util/errors/errorresult.go | 18 +++++++++++++++ src/backend/util/maps/maps.go | 2 +- 8 files changed, 42 insertions(+), 29 deletions(-) create mode 100644 src/backend/util/errors/errorresult.go diff --git a/src/backend/controllers/auth/authenticator.go b/src/backend/controllers/auth/authenticator.go index 34d70e7e9..f712ea835 100644 --- a/src/backend/controllers/auth/authenticator.go +++ b/src/backend/controllers/auth/authenticator.go @@ -10,6 +10,7 @@ import ( "github.com/Qihoo360/wayne/src/backend/controllers/base" "github.com/Qihoo360/wayne/src/backend/models" selfoauth "github.com/Qihoo360/wayne/src/backend/oauth2" + "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/hack" "github.com/Qihoo360/wayne/src/backend/util/logs" "github.com/astaxie/beego" @@ -172,7 +173,7 @@ func (c *AuthController) CurrentUser() { // we also only use its public counter part to verify return rsakey.RsaPublicKey, nil }) - errResult := base.ErrorResult{} + errResult := errors.ErrorResult{} switch err.(type) { case nil: // no error if !token.Valid { // but may still be invalid diff --git a/src/backend/controllers/base/logged.go b/src/backend/controllers/base/logged.go index 34b03ddc2..c32310ceb 100644 --- a/src/backend/controllers/base/logged.go +++ b/src/backend/controllers/base/logged.go @@ -9,6 +9,7 @@ import ( "github.com/Qihoo360/wayne/src/backend/bus" "github.com/Qihoo360/wayne/src/backend/bus/message" "github.com/Qihoo360/wayne/src/backend/models" + "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/hack" "github.com/Qihoo360/wayne/src/backend/util/logs" "github.com/dgrijalva/jwt-go" @@ -45,7 +46,7 @@ func (c *LoggedInController) Prepare() { return rsakey.RsaPublicKey, nil }) - errResult := ErrorResult{} + errResult := errors.ErrorResult{} switch err.(type) { case nil: // no error if !token.Valid { // but may still be invalid diff --git a/src/backend/controllers/base/resulthandler.go b/src/backend/controllers/base/resulthandler.go index 63ced128a..c489a112c 100644 --- a/src/backend/controllers/base/resulthandler.go +++ b/src/backend/controllers/base/resulthandler.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + erroresult "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/hack" "github.com/Qihoo360/wayne/src/backend/util/logs" "github.com/astaxie/beego" @@ -21,21 +22,6 @@ type Result struct { Data interface{} `json:"data"` } -var _ error = &ErrorResult{} - -// Error implements the Error interface. -func (e *ErrorResult) Error() string { - return fmt.Sprintf("code:%d,subCode:%d,msg:%s", e.Code, e.SubCode, e.Msg) -} - -type ErrorResult struct { - // http code - Code int `json:"code"` - // The custom code - SubCode int `json:"subCode"` - Msg string `json:"msg"` -} - func (c *ResultHandlerController) Success(data interface{}) { c.Ctx.Output.SetStatus(http.StatusOK) c.Data["json"] = Result{Data: data} @@ -72,7 +58,7 @@ func (c *ResultHandlerController) AbortUnauthorized(msg string) { // Handle return http code and body normally, need return func (c *ResultHandlerController) HandleError(err error) int { - errorResult := &ErrorResult{ + errorResult := &erroresult.ErrorResult{ Code: http.StatusInternalServerError, } switch e := err.(type) { @@ -91,7 +77,7 @@ func (c *ResultHandlerController) HandleError(err error) int { } else { errorResult.Msg = e.Message } - case *ErrorResult: + case *erroresult.ErrorResult: errorResult = e default: if err == orm.ErrNoRows { @@ -120,7 +106,7 @@ func (c *ResultHandlerController) HandleError(err error) int { } func (c *ResultHandlerController) errorResult(code int, msg string) []byte { - errorResult := ErrorResult{ + errorResult := erroresult.ErrorResult{ Code: code, Msg: msg, } diff --git a/src/backend/controllers/kubernetes/deployment/deployment.go b/src/backend/controllers/kubernetes/deployment/deployment.go index 272c3b257..e71bf4d11 100644 --- a/src/backend/controllers/kubernetes/deployment/deployment.go +++ b/src/backend/controllers/kubernetes/deployment/deployment.go @@ -13,6 +13,7 @@ import ( "github.com/Qihoo360/wayne/src/backend/resources/deployment" "github.com/Qihoo360/wayne/src/backend/resources/namespace" "github.com/Qihoo360/wayne/src/backend/util" + "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/hack" "github.com/Qihoo360/wayne/src/backend/util/logs" "github.com/Qihoo360/wayne/src/backend/workers/webhook" @@ -218,7 +219,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub // this namespace can't use current cluster. clusterMetas, ok := ns.MetaDataObj.ClusterMetas[cluster] if !ok { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: http.StatusForbidden, Msg: fmt.Sprintf("Current namespace (%s) can't use current cluster (%s).Please contact administrator. ", ns.Name, cluster), @@ -240,7 +241,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub if clusterMetas.ResourcesLimit.Memory != 0 && clusterMetas.ResourcesLimit.Memory-(namespaceResourceUsed.Memory+requestResourceList.Memory)/1024 < 0 { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: base.ErrorSubCodeInsufficientResource, Msg: fmt.Sprintf("request namespace resource (memory:%dGi) is not enough for this deploy", requestResourceList.Memory/1024), @@ -249,7 +250,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub if clusterMetas.ResourcesLimit.Cpu != 0 && clusterMetas.ResourcesLimit.Cpu-(namespaceResourceUsed.Cpu+requestResourceList.Cpu)/1000 < 0 { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: base.ErrorSubCodeInsufficientResource, Msg: fmt.Sprintf("request namespace resource (cpu:%d) is not enough for this deploy", requestResourceList.Cpu/1000), diff --git a/src/backend/controllers/kubernetes/statefulset/statefulset.go b/src/backend/controllers/kubernetes/statefulset/statefulset.go index 5a397c66a..ac29b95f1 100644 --- a/src/backend/controllers/kubernetes/statefulset/statefulset.go +++ b/src/backend/controllers/kubernetes/statefulset/statefulset.go @@ -11,6 +11,7 @@ import ( "github.com/Qihoo360/wayne/src/backend/resources/namespace" "github.com/Qihoo360/wayne/src/backend/resources/statefulset" "github.com/Qihoo360/wayne/src/backend/util" + "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/hack" "github.com/Qihoo360/wayne/src/backend/util/logs" "k8s.io/api/apps/v1beta1" @@ -154,7 +155,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub // this namespace can't use current cluster. clusterMetas, ok := ns.MetaDataObj.ClusterMetas[cluster] if !ok { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: http.StatusForbidden, Msg: fmt.Sprintf("Current namespace (%s) can't use current cluster (%s).Please contact administrator. ", ns.Name, cluster), @@ -175,7 +176,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub if clusterMetas.ResourcesLimit.Memory != 0 && clusterMetas.ResourcesLimit.Memory-(namespaceResourceUsed.Memory+requestResourceList.Memory)/1024 < 0 { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: base.ErrorSubCodeInsufficientResource, Msg: fmt.Sprintf("request namespace resource (memory:%dGi) is not enough for this deploy", requestResourceList.Memory/1024), @@ -184,7 +185,7 @@ func checkResourceAvailable(ns *models.Namespace, cli *kubernetes.Clientset, kub if clusterMetas.ResourcesLimit.Cpu != 0 && clusterMetas.ResourcesLimit.Cpu-(namespaceResourceUsed.Cpu+requestResourceList.Cpu)/1000 < 0 { - return &base.ErrorResult{ + return &errors.ErrorResult{ Code: http.StatusForbidden, SubCode: base.ErrorSubCodeInsufficientResource, Msg: fmt.Sprintf("request namespace resource (cpu:%d) is not enough for this deploy", requestResourceList.Cpu/1000), diff --git a/src/backend/resources/deployment/deployment.go b/src/backend/resources/deployment/deployment.go index efdff4015..19cee5122 100644 --- a/src/backend/resources/deployment/deployment.go +++ b/src/backend/resources/deployment/deployment.go @@ -2,11 +2,13 @@ package deployment import ( "fmt" + "net/http" "github.com/Qihoo360/wayne/src/backend/client" "github.com/Qihoo360/wayne/src/backend/resources/common" "github.com/Qihoo360/wayne/src/backend/resources/event" "github.com/Qihoo360/wayne/src/backend/resources/pod" + erroresult "github.com/Qihoo360/wayne/src/backend/util/errors" "github.com/Qihoo360/wayne/src/backend/util/maps" "k8s.io/api/apps/v1beta1" "k8s.io/apimachinery/pkg/api/errors" @@ -89,8 +91,11 @@ func checkDeploymentLabelSelector(new *v1beta1.Deployment, old *v1beta1.Deployme for key, value := range new.Spec.Selector.MatchLabels { oldValue, ok := old.Spec.Selector.MatchLabels[key] if !ok || oldValue != value { - return fmt.Errorf("New's Deployment .Spec.Selector.MatchLabels(%s) not match old MatchLabels(%s),do not allow deploy to prevent the orphan ReplicaSet. ", - maps.LabelsToString(new.Spec.Selector.MatchLabels), maps.LabelsToString(old.Spec.Selector.MatchLabels)) + return &erroresult.ErrorResult{ + Code: http.StatusBadRequest, + Msg: fmt.Sprintf("New's Deployment MatchLabels(%s) not match old MatchLabels(%s), do not allow deploy to prevent the orphan ReplicaSet. ", + maps.LabelsToString(new.Spec.Selector.MatchLabels), maps.LabelsToString(old.Spec.Selector.MatchLabels)), + } } } diff --git a/src/backend/util/errors/errorresult.go b/src/backend/util/errors/errorresult.go new file mode 100644 index 000000000..0e6e5d6ed --- /dev/null +++ b/src/backend/util/errors/errorresult.go @@ -0,0 +1,18 @@ +package errors + +import "fmt" + +var _ error = &ErrorResult{} + +// Error implements the Error interface. +func (e *ErrorResult) Error() string { + return fmt.Sprintf("code:%d,subCode:%d,msg:%s", e.Code, e.SubCode, e.Msg) +} + +type ErrorResult struct { + // http code + Code int `json:"code"` + // The custom code + SubCode int `json:"subCode"` + Msg string `json:"msg"` +} diff --git a/src/backend/util/maps/maps.go b/src/backend/util/maps/maps.go index 75bc11986..5ae77e648 100644 --- a/src/backend/util/maps/maps.go +++ b/src/backend/util/maps/maps.go @@ -24,7 +24,7 @@ func MergeLabels(old map[string]string, new map[string]string) map[string]string } func LabelsToString(labels map[string]string) string { - result := make([]string, len(labels)) + result := make([]string, 0) for k, v := range labels { result = append(result, fmt.Sprintf("%s=%s", k, v)) From 1939017540c31a2321706e8aaea9e4c883a0b547 Mon Sep 17 00:00:00 2001 From: wilhelmguo Date: Tue, 18 Dec 2018 16:47:33 +0800 Subject: [PATCH 3/5] frontend: User advanced mode paste removes unnecessary fields --- src/frontend/lib | 2 +- .../create-edit-configmaptpl.component.ts | 62 +++-- .../create-edit-cronjobtpl.component.ts | 75 +++--- .../create-edit-daemonsettpl.component.ts | 108 +++++---- .../create-edit-deploymenttpl.component.ts | 60 +++-- ...edit-persistentvolumeclaimtpl.component.ts | 68 +++--- .../create-edit-secrettpl.component.ts | 62 +++-- .../app/portal/sidenav/sidenav.component.html | 18 +- .../create-edit-statefulsettpl.component.ts | 106 ++++---- .../resource/create-edit-resource-template.ts | 15 +- .../app/shared/model/v1/kubernetes/base.ts | 227 ++++++++++++++++++ src/frontend/src/app/shared/utils.ts | 19 +- 12 files changed, 590 insertions(+), 232 deletions(-) create mode 100644 src/frontend/src/app/shared/model/v1/kubernetes/base.ts diff --git a/src/frontend/lib b/src/frontend/lib index 78e72f46e..d2c795e13 160000 --- a/src/frontend/lib +++ b/src/frontend/lib @@ -1 +1 @@ -Subproject commit 78e72f46eb82945941c1fdaf813e7b8f57a628da +Subproject commit d2c795e131a95fff0b4bf71f51fe3152c534af93 diff --git a/src/frontend/src/app/portal/configmap/create-edit-configmaptpl/create-edit-configmaptpl.component.ts b/src/frontend/src/app/portal/configmap/create-edit-configmaptpl/create-edit-configmaptpl.component.ts index cc95e700b..7de0a8039 100644 --- a/src/frontend/src/app/portal/configmap/create-edit-configmaptpl/create-edit-configmaptpl.component.ts +++ b/src/frontend/src/app/portal/configmap/create-edit-configmaptpl/create-edit-configmaptpl.component.ts @@ -30,8 +30,8 @@ import { AuthService } from '../../../shared/auth/auth.service'; export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, OnDestroy { currentForm: FormGroup; configMapTpl: ConfigMapTpl = new ConfigMapTpl(); - checkOnGoing: boolean = false; - isSubmitOnGoing: boolean = false; + checkOnGoing = false; + isSubmitOnGoing = false; actionType: ActionType; app: App; configMap: ConfigMap; @@ -41,8 +41,8 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O top: number; box: HTMLElement; - show: boolean = false; - eventList: any = new Array(); + show = false; + eventList: any = Array(); constructor(private configMapTplService: ConfigMapTplService, private configMapService: ConfigMapService, @@ -92,7 +92,7 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O get datas(): FormArray { return this.currentForm.get('datas') as FormArray; - }; + } initData() { return this.fb.group({ @@ -115,7 +115,7 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O createForm() { let disabled = false; - if (this.actionType == ActionType.EDIT) { + if (this.actionType === ActionType.EDIT) { disabled = true; } this.currentForm = this.fb.group({ @@ -130,7 +130,7 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O } initClusterGroups() { - let clusters = Array(); + const clusters = Array(); this.clusters.forEach(cluster => { clusters.push(this.fb.group({ checked: cluster.checked, @@ -144,11 +144,11 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O } ngOnInit(): void { - let appId = parseInt(this.route.parent.snapshot.params['id']); - let namespaceId = this.cacheService.namespaceId; - let configMapId = parseInt(this.route.snapshot.params['configMapId']); - let tplId = parseInt(this.route.snapshot.params['tplId']); - let observables = Array( + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); + const namespaceId = this.cacheService.namespaceId; + const configMapId = parseInt(this.route.snapshot.params['configMapId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); + const observables = Array( this.clusterService.getNames(), this.appService.getById(appId, namespaceId), this.configMapService.getById(configMapId, appId) @@ -162,22 +162,22 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O this.createForm(); Observable.combineLatest(observables).subscribe( response => { - let clusters = response[0].data; + const clusters = response[0].data; for (let i = 0; i < clusters.length; i++) { clusters[i].checked = false; } this.clusters = this.filterCluster(clusters); this.app = response[1].data; this.configMap = response[2].data; - let tpl = response[3]; + const tpl = response[3]; if (tpl) { this.configMapTpl = tpl.data; this.saveConfigMapTpl(JSON.parse(this.configMapTpl.template)); if (this.configMapTpl.metaData) { - let clusters = JSON.parse(this.configMapTpl.metaData).clusters; - for (let cluster of clusters) { + const configedClusters = JSON.parse(this.configMapTpl.metaData).clusters; + for (const cluster of configedClusters) { for (let i = 0; i < this.clusters.length; i++) { - if (cluster == this.clusters[i].name) { + if (cluster === this.clusters[i].name) { this.clusters[i].checked = true; } } @@ -210,17 +210,17 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O } this.isSubmitOnGoing = true; - let metaDataStr = this.configMapTpl.metaData ? this.configMapTpl.metaData : '{}'; - let clusters = Array(); + const metaDataStr = this.configMapTpl.metaData ? this.configMapTpl.metaData : '{}'; + const clusters = Array(); this.currentForm.controls.clusters.value.map((cluster: Cluster) => { if (cluster.checked) { clusters.push(cluster.name); } }); - let metaData = JSON.parse(metaDataStr); + const metaData = JSON.parse(metaDataStr); metaData['clusters'] = clusters; this.configMapTpl.metaData = JSON.stringify(metaData); - let kubeConfigMap = this.getKubeConfigMapByForm(); + const kubeConfigMap = this.getKubeConfigMapByForm(); this.configMapTpl.template = JSON.stringify(kubeConfigMap); this.configMapTpl.id = undefined; this.configMapTplService.create(this.configMapTpl, this.app.id).subscribe( @@ -259,7 +259,7 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O this.configMapTpl.name = this.configMap.name; this.configMapTpl.configMapId = this.configMap.id; - let kubeConfigMap = this.kubeConfigMap; + const kubeConfigMap = this.kubeConfigMap; if (!kubeConfigMap.metadata) { kubeConfigMap.metadata = new ObjectMeta(); } @@ -267,7 +267,7 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O kubeConfigMap.metadata.labels = this.buildLabels(kubeConfigMap.metadata.labels); if (formValue.datas && formValue.datas.length > 0) { kubeConfigMap.data = {}; - for (let data of formValue.datas) { + for (const data of formValue.datas) { kubeConfigMap.data[data.dataName] = data.dataValue; } } @@ -279,17 +279,29 @@ export class CreateEditConfigMapTplComponent implements OnInit, AfterViewInit, O } saveConfigMapTpl(kubeConfigMap: KubeConfigMap) { + this.removeUnused(kubeConfigMap); if (kubeConfigMap && kubeConfigMap.data) { this.kubeConfigMap = kubeConfigMap; - let datas = Array(); + const datas = Array(); Object.getOwnPropertyNames(kubeConfigMap.data).map(key => { datas.push(this.fb.group({ dataName: key, dataValue: kubeConfigMap.data[key], - }),); + })); }); this.currentForm.setControl('datas', this.fb.array(datas)); } } + + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: any) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } } diff --git a/src/frontend/src/app/portal/cronjob/create-edit-cronjobtpl/create-edit-cronjobtpl.component.ts b/src/frontend/src/app/portal/cronjob/create-edit-cronjobtpl/create-edit-cronjobtpl.component.ts index 8f3a2cb2f..09cd27d72 100644 --- a/src/frontend/src/app/portal/cronjob/create-edit-cronjobtpl/create-edit-cronjobtpl.component.ts +++ b/src/frontend/src/app/portal/cronjob/create-edit-cronjobtpl/create-edit-cronjobtpl.component.ts @@ -34,6 +34,7 @@ import { AceEditorMsg } from '../../../shared/ace-editor/ace-editor'; import { defaultCronJob } from '../../../shared/default-models/cronjob.const'; import { Observable } from 'rxjs'; import * as cron from 'cron-parser'; +import { ObjectMeta } from '../../../shared/model/v1/kubernetes/deployment'; const templateDom = [ { @@ -73,7 +74,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD actionType: ActionType; cronjobTpl: CronjobTpl = new CronjobTpl(); - isSubmitOnGoing: boolean = false; + isSubmitOnGoing = false; app: App; cronjob: Cronjob; kubeCronjob: KubeCronJob = new KubeCronJob(); @@ -138,7 +139,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } setContainDom(i) { - let dom = JSON.parse(JSON.stringify(containerDom)); + const dom = JSON.parse(JSON.stringify(containerDom)); dom.id += i ? i : ''; dom.child.forEach(item => { item.id += i ? i : ''; @@ -148,7 +149,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD initNavList() { this.naviList = null; - let naviList = JSON.parse(JSON.stringify(templateDom)); + const naviList = JSON.parse(JSON.stringify(templateDom)); for (let key = 0; key < this.containersLength; key++) { naviList[0].child.push(this.setContainDom(key)); } @@ -156,9 +157,11 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } get isScheduleValid(): boolean { - if (!this.kubeCronjob.spec.schedule) return false; - let result = cron.parseString(this.kubeCronjob.spec.schedule); - if (Object.keys(result.errors).length != 0) { + if (!this.kubeCronjob.spec.schedule) { + return false; + } + const result = cron.parseString(this.kubeCronjob.spec.schedule); + if (Object.keys(result.errors).length !== 0) { return false; } return true; @@ -191,10 +194,10 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD get memoryLimit(): number { let memoryLimit = defaultResources.memoryLimit; if (this.cronjob && this.cronjob.metaData) { - let metaData = JSON.parse(this.cronjob.metaData); + const metaData = JSON.parse(this.cronjob.metaData); if (metaData.resources && metaData.resources.memoryLimit) { - memoryLimit = parseInt(metaData.resources.memoryLimit); + memoryLimit = parseInt(metaData.resources.memoryLimit, 10); } } return memoryLimit; @@ -203,10 +206,10 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD get cpuLimit(): number { let cpuLimit = defaultResources.cpuLimit; if (this.cronjob && this.cronjob.metaData) { - let metaData = JSON.parse(this.cronjob.metaData); + const metaData = JSON.parse(this.cronjob.metaData); if (metaData.resources && metaData.resources.cpuLimit) { - cpuLimit = parseInt(metaData.resources.cpuLimit); + cpuLimit = parseInt(metaData.resources.cpuLimit, 10); } } return cpuLimit; @@ -218,7 +221,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } defaultContainer(): Container { - let container = new Container(); + const container = new Container(); container.resources = new ResourceRequirements(); container.resources.limits = {'memory': '', 'cpu': ''}; container.env = []; @@ -228,11 +231,11 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD ngOnInit(): void { this.initDefault(); - let appId = parseInt(this.route.parent.snapshot.params['id']); - let namespaceId = this.cacheService.namespaceId; - let cronjobId = parseInt(this.route.snapshot.params['cronjobId']); - let tplId = parseInt(this.route.snapshot.params['tplId']); - let observables = Array( + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); + const namespaceId = this.cacheService.namespaceId; + const cronjobId = parseInt(this.route.snapshot.params['cronjobId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); + const observables = Array( this.appService.getById(appId, namespaceId), this.cronjobService.getById(cronjobId, appId) ); @@ -246,7 +249,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD response => { this.app = response[0].data; this.cronjob = response[1].data; - let tpl = response[2]; + const tpl = response[2]; if (tpl) { this.cronjobTpl = tpl.data; this.cronjobTpl.description = null; @@ -274,7 +277,8 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD kubeCronJob.metadata.name = this.cronjob.name; kubeCronJob.metadata.labels = this.buildLabels(this.kubeCronjob.metadata.labels); kubeCronJob.spec.jobTemplate.metadata.labels = this.buildLabels(this.kubeCronjob.spec.jobTemplate.metadata.labels); - kubeCronJob.spec.jobTemplate.spec.template.metadata.labels = this.buildLabels(this.kubeCronjob.spec.jobTemplate.spec.template.metadata.labels); + kubeCronJob.spec.jobTemplate.spec.template.metadata.labels = this.buildLabels( + this.kubeCronjob.spec.jobTemplate.spec.template.metadata.labels); return kubeCronJob; } @@ -319,8 +323,8 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } defaultEnv(type: number): EnvVar { - let env = new EnvVar(); - switch (parseInt(type.toString())) { + const env = new EnvVar(); + switch (parseInt(type.toString(), 10)) { case 0: env.value = ''; break; @@ -339,8 +343,8 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } defaultEnvFrom(type: number): EnvFromSource { - let envFrom = new EnvFromSource(); - switch (parseInt(type.toString())) { + const envFrom = new EnvFromSource(); + switch (parseInt(type.toString(), 10)) { case 1: envFrom.configMapRef = new ConfigMapEnvSource(); break; @@ -388,15 +392,28 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD saveCronjob(kubeCronjob: KubeCronJob) { // this.removeResourceUnit(kubeStatefulSet); + this.removeUnused(kubeCronjob); this.fillDefault(kubeCronjob); this.kubeCronjob = kubeCronjob; this.initNavList(); } + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: KubeCronJob) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } + fillDefault(kubeCronjob: KubeCronJob) { this.kubeCronjob = mergeDeep(JSON.parse(defaultCronJob), kubeCronjob); - if (this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers && this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers.length > 0) { - for (let container of this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers) { + if (this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers && + this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers.length > 0) { + for (const container of this.kubeCronjob.spec.jobTemplate.spec.template.spec.containers) { if (!container.resources) { container.resources = ResourceRequirements.emptyObject(); } @@ -413,7 +430,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD let cpuRequestLimitPercent = 0.5; let memoryRequestLimitPercent = 1; if (this.cronjob.metaData) { - let metaData = JSON.parse(this.cronjob.metaData); + const metaData = JSON.parse(this.cronjob.metaData); if (metaData.resources && metaData.resources.cpuRequestLimitPercent) { if (metaData.resources.cpuRequestLimitPercent.indexOf('%') > -1) { cpuRequestLimitPercent = parseFloat(metaData.resources.cpuRequestLimitPercent.replace('%', '')) / 100; @@ -430,9 +447,9 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } } - for (let container of kubeCronjob.spec.jobTemplate.spec.template.spec.containers) { - let memoryLimit = container.resources.limits['memory']; - let cpuLimit = container.resources.limits['cpu']; + for (const container of kubeCronjob.spec.jobTemplate.spec.template.spec.containers) { + const memoryLimit = container.resources.limits['memory']; + const cpuLimit = container.resources.limits['cpu']; if (!container.resources.requests) { container.resources.requests = {}; } @@ -460,7 +477,7 @@ export class CreateEditCronjobTplComponent implements OnInit, AfterViewInit, OnD } getImagePrefixReg() { - let imagePrefix = this.authService.config['system.image-prefix']; + const imagePrefix = this.authService.config['system.image-prefix']; return imagePrefix; } diff --git a/src/frontend/src/app/portal/daemonset/create-edit-daemonsettpl/create-edit-daemonsettpl.component.ts b/src/frontend/src/app/portal/daemonset/create-edit-daemonsettpl/create-edit-daemonsettpl.component.ts index b7d2a126d..8e58d7bc8 100644 --- a/src/frontend/src/app/portal/daemonset/create-edit-daemonsettpl/create-edit-daemonsettpl.component.ts +++ b/src/frontend/src/app/portal/daemonset/create-edit-daemonsettpl/create-edit-daemonsettpl.component.ts @@ -6,16 +6,20 @@ import { DOCUMENT, EventManager } from '@angular/platform-browser'; import { FormBuilder, NgForm } from '@angular/forms'; import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service'; import { + ConfigMapEnvSource, ConfigMapKeySelector, Container, DaemonSetUpdateStrategy, + EnvFromSource, EnvVar, EnvVarSource, ExecAction, HTTPGetAction, KubeDaemonSet, + ObjectMeta, Probe, ResourceRequirements, + SecretEnvSource, SecretKeySelector, TCPSocketAction } from '../../../shared/model/v1/kubernetes/daemonset'; @@ -35,7 +39,6 @@ import { DaemonSetService } from '../../../shared/client/v1/daemonset.service'; import { DaemonSetTplService } from '../../../shared/client/v1/daemonsettpl.service'; import { defaultDaemonSet } from '../../../shared/default-models/daemonset.const'; import { ResourceUnitConvertor } from '../../../shared/utils'; -import { ConfigMapEnvSource, EnvFromSource, SecretEnvSource } from '../../../shared/model/v1/kubernetes/deployment'; import { TranslateService } from '@ngx-translate/core'; const templateDom = [ @@ -82,7 +85,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O actionType: ActionType; daemonSetTpl = new DaemonSetTemplate(); - isSubmitOnGoing: boolean = false; + isSubmitOnGoing = false; app: App; daemonSet: DaemonSet; kubeDaemonSet = new KubeDaemonSet(); @@ -92,7 +95,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O top: number; box: HTMLElement; naviList: string = JSON.stringify(templateDom); - eventList: any = new Array(); + eventList: any = Array(); constructor(private daemonSetTplService: DaemonSetTplService, private fb: FormBuilder, @@ -151,7 +154,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } setContainDom(i) { - let dom = JSON.parse(JSON.stringify(containerDom)); + const dom = JSON.parse(JSON.stringify(containerDom)); dom.id += i ? i : ''; dom.child.forEach(item => { item.id += i ? i : ''; @@ -161,7 +164,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O initNavList() { this.naviList = null; - let naviList = JSON.parse(JSON.stringify(templateDom)); + const naviList = JSON.parse(JSON.stringify(templateDom)); for (let key = 0; key < this.containersLength; key++) { naviList[0].child.push(this.setContainDom(key)); } @@ -187,10 +190,10 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O get memoryLimit(): number { let memoryLimit = defaultResources.memoryLimit; if (this.daemonSet && this.daemonSet.metaData) { - let metaData = JSON.parse(this.daemonSet.metaData); + const metaData = JSON.parse(this.daemonSet.metaData); if (metaData.resources && metaData.resources.memoryLimit) { - memoryLimit = parseInt(metaData.resources.memoryLimit); + memoryLimit = parseInt(metaData.resources.memoryLimit, 10); } } return memoryLimit; @@ -199,10 +202,10 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O get cpuLimit(): number { let cpuLimit = defaultResources.cpuLimit; if (this.daemonSet && this.daemonSet.metaData) { - let metaData = JSON.parse(this.daemonSet.metaData); + const metaData = JSON.parse(this.daemonSet.metaData); if (metaData.resources && metaData.resources.cpuLimit) { - cpuLimit = parseInt(metaData.resources.cpuLimit); + cpuLimit = parseInt(metaData.resources.cpuLimit, 10); } } return cpuLimit; @@ -210,11 +213,11 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O ngOnInit(): void { this.initDefault(); - let appId = parseInt(this.route.parent.snapshot.params['id']); - let namespaceId = this.cacheService.namespaceId; - let daemonSetId = parseInt(this.route.snapshot.params['daemonSetId']); - let tplId = parseInt(this.route.snapshot.params['tplId']); - let observables = Array( + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); + const namespaceId = this.cacheService.namespaceId; + const daemonSetId = parseInt(this.route.snapshot.params['daemonSetId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); + const observables = Array( this.appService.getById(appId, namespaceId), this.daemonSetService.getById(daemonSetId, appId) ); @@ -228,7 +231,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O response => { this.app = response[0].data; this.daemonSet = response[1].data; - let tpl = response[2]; + const tpl = response[2]; if (tpl) { this.daemonSetTpl = tpl.data; @@ -254,13 +257,12 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } buildSelectorLabels(labels: {}) { - if (!labels) { - labels = {}; + if (Object.keys(labels).length > 0) { + return labels; } - labels[this.authService.config[appLabelKey]] = this.app.name; - labels['app'] = this.daemonSet.name; - delete labels[this.authService.config[namespaceLabelKey]]; - return labels; + const result = {}; + result['app'] = this.daemonSet.name; + return result; } fillLabel(kubeDaemonSet: KubeDaemonSet): KubeDaemonSet { @@ -317,8 +319,8 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } defaultEnvFrom(type: number): EnvFromSource { - let envFrom = new EnvFromSource(); - switch (parseInt(type.toString())) { + const envFrom = new EnvFromSource(); + switch (parseInt(type.toString(), 10)) { case 1: envFrom.configMapRef = new ConfigMapEnvSource(); break; @@ -359,7 +361,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } probeTypeChange(probe: Probe, type: number) { - switch (parseInt(type.toString())) { + switch (parseInt(type.toString(), 10)) { case 0: probe.httpGet = new HTTPGetAction(); probe.tcpSocket = undefined; @@ -394,7 +396,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } defaultContainer(): Container { - let container = new Container(); + const container = new Container(); container.resources = new ResourceRequirements(); container.resources.limits = {'memory': '', 'cpu': ''}; container.env = []; @@ -403,8 +405,8 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } defaultEnv(type: number): EnvVar { - let env = new EnvVar(); - switch (parseInt(type.toString())) { + const env = new EnvVar(); + switch (parseInt(type.toString(), 10)) { case 0: env.value = ''; break; @@ -454,7 +456,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O let cpuRequestLimitPercent = 0.5; let memoryRequestLimitPercent = 1; if (this.daemonSet.metaData) { - let metaData = JSON.parse(this.daemonSet.metaData); + const metaData = JSON.parse(this.daemonSet.metaData); if (metaData.resources && metaData.resources.cpuRequestLimitPercent) { if (metaData.resources.cpuRequestLimitPercent.indexOf('%') > -1) { cpuRequestLimitPercent = parseFloat(metaData.resources.cpuRequestLimitPercent.replace('%', '')) / 100; @@ -471,9 +473,9 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } } - for (let container of kubeDaemonSet.spec.template.spec.containers) { - let memoryLimit = container.resources.limits['memory']; - let cpuLimit = container.resources.limits['cpu']; + for (const container of kubeDaemonSet.spec.template.spec.containers) { + const memoryLimit = container.resources.limits['memory']; + const cpuLimit = container.resources.limits['cpu']; if (!container.resources.requests) { container.resources.requests = {}; } @@ -493,10 +495,10 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O get totalFee() { let fee = 0; if (this.kubeDaemonSet.spec.template.spec.containers) { - for (let container of this.kubeDaemonSet.spec.template.spec.containers) { - let limit = container.resources.limits; - let cpu = limit['cpu']; - let memory = limit['memory']; + for (const container of this.kubeDaemonSet.spec.template.spec.containers) { + const limit = container.resources.limits; + const cpu = limit['cpu']; + const memory = limit['memory']; if (cpu) { fee += parseFloat(cpu) * this.cpuUnitPrice; } @@ -510,22 +512,36 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } saveDaemonSet(kubeDaemonSet: KubeDaemonSet) { + this.removeUnused(kubeDaemonSet); this.fillDefault(kubeDaemonSet); this.convertProbeCommandToText(kubeDaemonSet); this.kubeDaemonSet = kubeDaemonSet; this.initNavList(); } + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: KubeDaemonSet) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } + convertProbeCommandToText(kubeDaemonSet: KubeDaemonSet) { if (kubeDaemonSet.spec.template.spec.containers && kubeDaemonSet.spec.template.spec.containers.length > 0) { - for (let container of kubeDaemonSet.spec.template.spec.containers) { - if (container.livenessProbe && container.livenessProbe.exec && container.livenessProbe.exec.command && container.livenessProbe.exec.command.length > 0) { - let commands = container.livenessProbe.exec.command; + for (const container of kubeDaemonSet.spec.template.spec.containers) { + if (container.livenessProbe && container.livenessProbe.exec && + container.livenessProbe.exec.command && container.livenessProbe.exec.command.length > 0) { + const commands = container.livenessProbe.exec.command; container.livenessProbe.exec.command = Array(); container.livenessProbe.exec.command.push(commands.join('\n')); } - if (container.readinessProbe && container.readinessProbe.exec && container.readinessProbe.exec.command && container.readinessProbe.exec.command.length > 0) { - let commands = container.readinessProbe.exec.command; + if (container.readinessProbe && container.readinessProbe.exec && + container.readinessProbe.exec.command && container.readinessProbe.exec.command.length > 0) { + const commands = container.readinessProbe.exec.command; container.readinessProbe.exec.command = Array(); container.readinessProbe.exec.command.push(commands.join('\n')); } @@ -541,7 +557,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O kubeDaemonSet.spec.updateStrategy.type = 'OnDelete'; } if (kubeDaemonSet.spec.template.spec.containers && kubeDaemonSet.spec.template.spec.containers.length > 0) { - for (let container of kubeDaemonSet.spec.template.spec.containers) { + for (const container of kubeDaemonSet.spec.template.spec.containers) { if (!container.resources) { container.resources = ResourceRequirements.emptyObject(); } @@ -563,11 +579,13 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O convertProbeCommandToArray(kubeDaemonSet: KubeDaemonSet): KubeDaemonSet { if (kubeDaemonSet.spec.template.spec.containers && kubeDaemonSet.spec.template.spec.containers.length > 0) { - for (let container of kubeDaemonSet.spec.template.spec.containers) { - if (container.livenessProbe && container.livenessProbe.exec && container.livenessProbe.exec.command && container.livenessProbe.exec.command.length > 0) { + for (const container of kubeDaemonSet.spec.template.spec.containers) { + if (container.livenessProbe && container.livenessProbe.exec && + container.livenessProbe.exec.command && container.livenessProbe.exec.command.length > 0) { container.livenessProbe.exec.command = container.livenessProbe.exec.command[0].split('\n'); } - if (container.readinessProbe && container.readinessProbe.exec && container.readinessProbe.exec.command && container.readinessProbe.exec.command.length > 0) { + if (container.readinessProbe && container.readinessProbe.exec && + container.readinessProbe.exec.command && container.readinessProbe.exec.command.length > 0) { container.readinessProbe.exec.command = container.readinessProbe.exec.command[0].split('\n'); } } @@ -596,7 +614,7 @@ export class CreateEditDaemonSetTplComponent implements OnInit, AfterViewInit, O } getImagePrefixReg() { - let imagePrefix = this.authService.config['system.image-prefix']; + const imagePrefix = this.authService.config['system.image-prefix']; return imagePrefix; } } diff --git a/src/frontend/src/app/portal/deployment/create-edit-deploymenttpl/create-edit-deploymenttpl.component.ts b/src/frontend/src/app/portal/deployment/create-edit-deploymenttpl/create-edit-deploymenttpl.component.ts index 57a944720..668b57201 100644 --- a/src/frontend/src/app/portal/deployment/create-edit-deploymenttpl/create-edit-deploymenttpl.component.ts +++ b/src/frontend/src/app/portal/deployment/create-edit-deploymenttpl/create-edit-deploymenttpl.component.ts @@ -18,6 +18,7 @@ import { HTTPGetAction, KubeDeployment, Lifecycle, + ObjectMeta, Probe, ResourceRequirements, RollingUpdateDeployment, @@ -179,7 +180,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, const metaData = JSON.parse(this.deployment.metaData); if (metaData.resources && metaData.resources.memoryLimit) { - memoryLimit = parseInt(metaData.resources.memoryLimit); + memoryLimit = parseInt(metaData.resources.memoryLimit, 10); } } return memoryLimit; @@ -191,7 +192,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, const metaData = JSON.parse(this.deployment.metaData); if (metaData.resources && metaData.resources.cpuLimit) { - cpuLimit = parseInt(metaData.resources.cpuLimit); + cpuLimit = parseInt(metaData.resources.cpuLimit, 10); } } return cpuLimit; @@ -241,10 +242,10 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, ngOnInit(): void { this.initDefault(); - const appId = parseInt(this.route.parent.snapshot.params['id']); + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); const namespaceId = this.cacheService.namespaceId; - const deploymentId = parseInt(this.route.snapshot.params['deploymentId']); - const tplId = parseInt(this.route.snapshot.params['tplId']); + const deploymentId = parseInt(this.route.snapshot.params['deploymentId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); const observables = Array( this.appService.getById(appId, namespaceId), this.deploymentService.getById(deploymentId, appId) @@ -284,7 +285,10 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, return labels; } - buildSelectorLabels() { + buildSelectorLabels(labels: {}) { + if (Object.keys(labels).length > 0) { + return labels; + } const result = {}; result['app'] = this.deployment.name; return result; @@ -293,7 +297,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, fillDeploymentLabel(kubeDeployment: KubeDeployment): KubeDeployment { kubeDeployment.metadata.name = this.deployment.name; kubeDeployment.metadata.labels = this.buildLabels(this.kubeDeployment.metadata.labels); - kubeDeployment.spec.selector.matchLabels = this.buildSelectorLabels(); + kubeDeployment.spec.selector.matchLabels = this.buildSelectorLabels(this.kubeDeployment.spec.selector.matchLabels); kubeDeployment.spec.template.metadata.labels = this.buildLabels(this.kubeDeployment.spec.template.metadata.labels); return kubeDeployment; } @@ -381,7 +385,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, } probeTypeChange(probe: Probe, type: number) { - switch (parseInt(type.toString())) { + switch (parseInt(type.toString(), 10)) { case 0: probe.httpGet = new HTTPGetAction(); probe.tcpSocket = undefined; @@ -404,18 +408,20 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, } lifecyclePostStartProbeTypeChange(type: number, i: number) { - this.kubeDeployment.spec.template.spec.containers[i].lifecycle.postStart = this.lifecycleProbeTypeChange(this.kubeDeployment.spec.template.spec.containers[i].lifecycle.postStart, type); + this.kubeDeployment.spec.template.spec.containers[i].lifecycle.postStart = this.lifecycleProbeTypeChange( + this.kubeDeployment.spec.template.spec.containers[i].lifecycle.postStart, type); } lifecyclePreStopProbeTypeChange(type: number, i: number) { - this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop = this.lifecycleProbeTypeChange(this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop, type); + this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop = this.lifecycleProbeTypeChange( + this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop, type); } lifecycleProbeTypeChange(handler: Handler, type: number) { if (!handler) { handler = new Handler(); } - switch (parseInt(type.toString())) { + switch (parseInt(type.toString(), 10)) { case -1: handler.httpGet = undefined; handler.tcpSocket = undefined; @@ -462,14 +468,14 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, const preStop = this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop; return preStop && preStop.exec && preStop.exec.command && preStop.exec.command.length > 0 && - preStop.exec.command[0] != this.defaultSafeExecCommand; + preStop.exec.command[0] !== this.defaultSafeExecCommand; } safeExitSelected(i: number): boolean { const preStop = this.kubeDeployment.spec.template.spec.containers[i].lifecycle.preStop; return preStop && preStop.exec && preStop.exec.command && preStop.exec.command.length > 0 && - preStop.exec.command[0] == this.defaultSafeExecCommand; + preStop.exec.command[0] === this.defaultSafeExecCommand; } trackByFn(index, item) { @@ -478,7 +484,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, defaultEnv(type: number): EnvVar { const env = new EnvVar(); - switch (parseInt(type.toString())) { + switch (parseInt(type.toString(), 10)) { case 0: env.value = ''; break; @@ -498,7 +504,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, defaultEnvFrom(type: number): EnvFromSource { const envFrom = new EnvFromSource(); - switch (parseInt(type.toString())) { + switch (parseInt(type.toString(), 10)) { case 1: envFrom.configMapRef = new ConfigMapEnvSource(); break; @@ -547,10 +553,12 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, if (kubeDeployment.spec.strategy) { if (kubeDeployment.spec.strategy.type === 'RollingUpdate' && kubeDeployment.spec.strategy.rollingUpdate) { if (kubeDeployment.spec.strategy.rollingUpdate.maxSurge.toString().indexOf('%') < 0) { - kubeDeployment.spec.strategy.rollingUpdate.maxSurge = parseInt(kubeDeployment.spec.strategy.rollingUpdate.maxSurge.toString()); + kubeDeployment.spec.strategy.rollingUpdate.maxSurge = parseInt( + kubeDeployment.spec.strategy.rollingUpdate.maxSurge.toString(), 10); } if (kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable.toString().indexOf('%') < 0) { - kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable = parseInt(kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable.toString()); + kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable = parseInt( + kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable.toString(), 10); } } if (kubeDeployment.spec.strategy.type === 'Recreate') { @@ -575,10 +583,10 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, if (container.lifecycle) { // 置空handler,避免出现 Deployment.apps 'infra-nginx' is invalid: spec.template.spec.containers[0].lifecycle.postStart: // Required value: must specify a handler type - if (container.lifecycle.postStart != undefined && Object.keys(container.lifecycle.postStart).length === 0) { + if (container.lifecycle.postStart !== undefined && Object.keys(container.lifecycle.postStart).length === 0) { container.lifecycle.postStart = undefined; } - if (container.lifecycle.preStop != undefined && Object.keys(container.lifecycle.preStop).length === 0) { + if (container.lifecycle.preStop !== undefined && Object.keys(container.lifecycle.preStop).length === 0) { container.lifecycle.preStop = undefined; } if (container.lifecycle.postStart && @@ -665,12 +673,24 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, saveDeployment(kubeDeployment: KubeDeployment) { // this.removeResourceUnit(kubeStatefulSet); + this.removeUnused(kubeDeployment); this.fillDefault(kubeDeployment); this.convertProbeCommandToText(kubeDeployment); this.kubeDeployment = kubeDeployment; this.initNavList(); } + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: KubeDeployment) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } + convertProbeCommandToText(kubeDeployment: KubeDeployment) { if (kubeDeployment.spec.template.spec.containers && kubeDeployment.spec.template.spec.containers.length > 0) { for (const container of kubeDeployment.spec.template.spec.containers) { @@ -718,7 +738,7 @@ export class CreateEditDeploymentTplComponent implements OnInit, AfterViewInit, kubeDeployment.spec.strategy = new DeploymentStrategy(); kubeDeployment.spec.strategy.type = 'RollingUpdate'; } - if (kubeDeployment.spec.strategy.type == 'RollingUpdate' && !kubeDeployment.spec.strategy.rollingUpdate) { + if (kubeDeployment.spec.strategy.type === 'RollingUpdate' && !kubeDeployment.spec.strategy.rollingUpdate) { kubeDeployment.spec.strategy.rollingUpdate = new RollingUpdateDeployment(); kubeDeployment.spec.strategy.rollingUpdate.maxSurge = '20%'; kubeDeployment.spec.strategy.rollingUpdate.maxUnavailable = 1; diff --git a/src/frontend/src/app/portal/persistentvolumeclaim/create-edit-persistentvolumeclaimtpl/create-edit-persistentvolumeclaimtpl.component.ts b/src/frontend/src/app/portal/persistentvolumeclaim/create-edit-persistentvolumeclaimtpl/create-edit-persistentvolumeclaimtpl.component.ts index 501d9e875..8d43df02c 100644 --- a/src/frontend/src/app/portal/persistentvolumeclaim/create-edit-persistentvolumeclaimtpl/create-edit-persistentvolumeclaimtpl.component.ts +++ b/src/frontend/src/app/portal/persistentvolumeclaim/create-edit-persistentvolumeclaimtpl/create-edit-persistentvolumeclaimtpl.component.ts @@ -4,7 +4,7 @@ import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import { FormArray, FormBuilder, FormGroup } from '@angular/forms'; import { MessageHandlerService } from '../../../shared/message-handler/message-handler.service'; -import { ActionType, appLabelKey } from '../../../shared/shared.const'; +import { ActionType, appLabelKey, namespaceLabelKey } from '../../../shared/shared.const'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { DOCUMENT, EventManager } from '@angular/platform-browser'; @@ -36,8 +36,8 @@ import { AuthService } from '../../../shared/auth/auth.service'; export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, AfterViewInit, OnDestroy { currentForm: FormGroup; pvcTpl: PersistentVolumeClaimTpl = new PersistentVolumeClaimTpl(); - checkOnGoing: boolean = false; - isSubmitOnGoing: boolean = false; + checkOnGoing = false; + isSubmitOnGoing = false; actionType: ActionType; app: App; top: number; @@ -47,8 +47,8 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte componentName = 'PVC'; clusters: Cluster[]; - show: boolean = false; - eventList: any[] = new Array(); + show = false; + eventList: any[] = Array(); constructor(private pvcTplService: PersistentVolumeClaimTplService, private pvcService: PersistentVolumeClaimService, @@ -99,7 +99,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte get selectors(): FormArray { return this.currentForm.get('selectors') as FormArray; - }; + } onAddSelector(index: number) { const selectors = this.currentForm.get(`selectors`) as FormArray; @@ -132,7 +132,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte } initClusterGroups() { - let clusters = Array(); + const clusters = Array(); this.clusters.forEach(cluster => { clusters.push(this.fb.group({ checked: cluster.checked, @@ -148,11 +148,11 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte ngOnInit(): void { this.kubePvc = new KubePersistentVolumeClaim(); - let appId = parseInt(this.route.parent.snapshot.params['id']); - let namespaceId = this.cacheService.namespaceId; - let pvcId = parseInt(this.route.snapshot.params['pvcId']); - let tplId = parseInt(this.route.snapshot.params['tplId']); - let observables = Array( + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); + const namespaceId = this.cacheService.namespaceId; + const pvcId = parseInt(this.route.snapshot.params['pvcId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); + const observables = Array( this.clusterService.getNames(), this.appService.getById(appId, namespaceId), this.pvcService.getById(pvcId, appId) @@ -166,23 +166,23 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte this.createForm(); Observable.combineLatest(observables).subscribe( response => { - let clusters = response[0].data; + const clusters = response[0].data; for (let i = 0; i < clusters.length; i++) { clusters[i].checked = false; } this.clusters = this.filterCluster(clusters); this.app = response[1].data; this.pvc = response[2].data; - let tpl = response[3]; + const tpl = response[3]; if (tpl) { this.pvcTpl = tpl.data; this.pvcTpl.description = null; this.savePvcTpl(JSON.parse(this.pvcTpl.template)); if (this.pvcTpl.metaData) { - let clusters = JSON.parse(this.pvcTpl.metaData).clusters; - for (let cluster of clusters) { + const configedClusters = JSON.parse(this.pvcTpl.metaData).clusters; + for (const cluster of configedClusters) { for (let i = 0; i < this.clusters.length; i++) { - if (cluster == this.clusters[i].name) { + if (cluster === this.clusters[i].name) { this.clusters[i].checked = true; } } @@ -215,24 +215,25 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte } this.isSubmitOnGoing = true; - let metaDataStr = this.pvcTpl.metaData ? this.pvcTpl.metaData : '{}'; - let clusters = Array(); + const metaDataStr = this.pvcTpl.metaData ? this.pvcTpl.metaData : '{}'; + const clusters = Array(); this.currentForm.controls.clusters.value.map((cluster: Cluster) => { if (cluster.checked) { clusters.push(cluster.name); } }); - let metaData = JSON.parse(metaDataStr); + const metaData = JSON.parse(metaDataStr); metaData['clusters'] = clusters; this.pvcTpl.metaData = JSON.stringify(metaData); - let kubePvc = this.getKubePvcByForm(); + const kubePvc = this.getKubePvcByForm(); this.pvcTpl.template = JSON.stringify(kubePvc); this.pvcTpl.id = undefined; this.pvcTplService.create(this.pvcTpl, this.app.id).subscribe( status => { this.isSubmitOnGoing = false; this.messageHandlerService.showSuccess('创建' + this.componentName + '模版成功!'); - this.router.navigate([`portal/namespace/${this.cacheService.namespaceId}/app/${this.app.id}/persistentvolumeclaim/${this.pvc.id}/list`]); + this.router.navigate( + [`portal/namespace/${this.cacheService.namespaceId}/app/${this.app.id}/persistentvolumeclaim/${this.pvc.id}/list`]); }, error => { this.isSubmitOnGoing = false; @@ -253,6 +254,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte labels = {}; } labels[this.authService.config[appLabelKey]] = this.app.name; + labels[this.authService.config[namespaceLabelKey]] = this.cacheService.currentNamespace.name; labels['app'] = this.pvc.name; return labels; } @@ -263,7 +265,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte this.pvcTpl.name = this.pvc.name; this.pvcTpl.persistentVolumeClaimId = this.pvc.id; - let kubePvc = this.kubePvc; + const kubePvc = this.kubePvc; if (!kubePvc.metadata) { kubePvc.metadata = new ObjectMeta(); } @@ -276,7 +278,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte kubePvc.spec.resources = new ResourceRequirements(); } kubePvc.spec.resources.requests = {'storage': formValue.storage + 'Gi'}; - let accessModes = Array(); + const accessModes = Array(); if (formValue.readWriteOnce) { accessModes.push('ReadWriteOnce'); } @@ -292,7 +294,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte } kubePvc.spec.selector.matchLabels = {}; if (formValue.selectors && formValue.selectors.length > 0) { - for (let selector of formValue.selectors) { + for (const selector of formValue.selectors) { kubePvc.spec.selector.matchLabels[selector.key] = selector.value; } } @@ -305,6 +307,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte } savePvcTpl(kubePvc: KubePersistentVolumeClaim) { + this.removeUnused(kubePvc); if (kubePvc && kubePvc.spec) { this.kubePvc = kubePvc; let storage; @@ -329,7 +332,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte } }); } - let selectors = Array(); + const selectors = Array(); if (kubePvc.spec.selector && kubePvc.spec.selector.matchLabels) { Object.getOwnPropertyNames(kubePvc.spec.selector.matchLabels).map(key => { selectors.push(this.fb.group({ @@ -338,7 +341,7 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte })); }); } - let clusters = this.currentForm.get('clusters'); + const clusters = this.currentForm.get('clusters'); this.currentForm = this.fb.group({ description: this.currentForm.get('description').value, storage: storage, @@ -350,5 +353,16 @@ export class CreateEditPersistentVolumeClaimTplComponent implements OnInit, Afte this.currentForm.setControl('clusters', clusters); } } + + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: any) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } } diff --git a/src/frontend/src/app/portal/secret/create-edit-secrettpl/create-edit-secrettpl.component.ts b/src/frontend/src/app/portal/secret/create-edit-secrettpl/create-edit-secrettpl.component.ts index c9aff82e7..da91e4343 100644 --- a/src/frontend/src/app/portal/secret/create-edit-secrettpl/create-edit-secrettpl.component.ts +++ b/src/frontend/src/app/portal/secret/create-edit-secrettpl/create-edit-secrettpl.component.ts @@ -31,17 +31,17 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe currentForm: FormGroup; secretTpl: SecretTpl = new SecretTpl(); - checkOnGoing: boolean = false; - isSubmitOnGoing: boolean = false; + checkOnGoing = false; + isSubmitOnGoing = false; actionType: ActionType; app: App; secret: Secret; top: number; box: HTMLElement; kubeSecret: KubeSecret = new KubeSecret(); - componentName = '配置集'; + componentName = '加密字典'; clusters: Cluster[]; - eventList: any[] = new Array(); + eventList: any[] = Array(); constructor(private secretTplService: SecretTplService, private secretService: SecretService, @@ -92,7 +92,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe get datas(): FormArray { return this.currentForm.get('datas') as FormArray; - }; + } initData() { return this.fb.group({ @@ -115,7 +115,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe createForm() { let disabled = false; - if (this.actionType == ActionType.EDIT) { + if (this.actionType === ActionType.EDIT) { disabled = true; } this.currentForm = this.fb.group({ @@ -130,7 +130,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe } initClusterGroups() { - let clusters = Array(); + const clusters = Array(); this.clusters.forEach(cluster => { clusters.push(this.fb.group({ checked: cluster.checked, @@ -144,11 +144,11 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe } ngOnInit(): void { - let appId = parseInt(this.route.parent.snapshot.params['id']); - let namespaceId = this.cacheService.namespaceId; - let secretId = parseInt(this.route.snapshot.params['secretId']); - let tplId = parseInt(this.route.snapshot.params['tplId']); - let observables = Array( + const appId = parseInt(this.route.parent.snapshot.params['id'], 10); + const namespaceId = this.cacheService.namespaceId; + const secretId = parseInt(this.route.snapshot.params['secretId'], 10); + const tplId = parseInt(this.route.snapshot.params['tplId'], 10); + const observables = Array( this.clusterService.getNames(), this.appService.getById(appId, namespaceId), this.secretService.getById(secretId, appId) @@ -162,7 +162,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe this.createForm(); Observable.combineLatest(observables).subscribe( response => { - let clusters = response[0].data; + const clusters = response[0].data; for (let i = 0; i < clusters.length; i++) { clusters[i].checked = false; } @@ -170,15 +170,15 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe this.app = response[1].data; this.secret = response[2].data; - let tpl = response[3]; + const tpl = response[3]; if (tpl) { this.secretTpl = tpl.data; this.saveSecretTpl(JSON.parse(this.secretTpl.template)); if (this.secretTpl.metaData) { - let clusters = JSON.parse(this.secretTpl.metaData).clusters; - for (let cluster of clusters) { + const configedClusters = JSON.parse(this.secretTpl.metaData).clusters; + for (const cluster of configedClusters) { for (let i = 0; i < this.clusters.length; i++) { - if (cluster == this.clusters[i].name) { + if (cluster === this.clusters[i].name) { this.clusters[i].checked = true; } } @@ -210,18 +210,18 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe return; } this.isSubmitOnGoing = true; - let metaDataStr = this.secretTpl.metaData ? this.secretTpl.metaData : '{}'; - let clusters = Array(); + const metaDataStr = this.secretTpl.metaData ? this.secretTpl.metaData : '{}'; + const clusters = Array(); this.currentForm.controls.clusters.value.map((cluster: Cluster) => { if (cluster.checked) { clusters.push(cluster.name); } }); - let metaData = JSON.parse(metaDataStr); + const metaData = JSON.parse(metaDataStr); metaData['clusters'] = clusters; this.secretTpl.metaData = JSON.stringify(metaData); - let kubeSecret = this.getKubeSecretByForm(); + const kubeSecret = this.getKubeSecretByForm(); this.secretTpl.template = JSON.stringify(kubeSecret); this.secretTpl.id = undefined; this.secretTplService.create(this.secretTpl, this.app.id).subscribe( @@ -260,7 +260,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe this.secretTpl.name = this.secret.name; this.secretTpl.secretId = this.secret.id; - let kubeSecret = this.kubeSecret; + const kubeSecret = this.kubeSecret; if (!kubeSecret.metadata) { kubeSecret.metadata = new ObjectMeta(); } @@ -271,7 +271,7 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe kubeSecret.metadata.labels = this.buildLabels(kubeSecret.metadata.labels); if (formValue.datas && formValue.datas.length > 0) { kubeSecret.data = {}; - for (let data of formValue.datas) { + for (const data of formValue.datas) { kubeSecret.data[data.dataName] = btoa(data.dataValue); } } @@ -283,17 +283,29 @@ export class CreateEditSecretTplComponent implements OnInit, AfterViewInit, OnDe } saveSecretTpl(kubeSecret: KubeSecret) { + this.removeUnused(kubeSecret); if (kubeSecret && kubeSecret.data) { this.kubeSecret = kubeSecret; - let datas = Array(); + const datas = Array(); Object.getOwnPropertyNames(kubeSecret.data).map(key => { datas.push(this.fb.group({ dataName: key, dataValue: atob(kubeSecret.data[key]), - }),); + })); }); this.currentForm.setControl('datas', this.fb.array(datas)); } } + + // remove unused fields, deal with user advanced mode paste yaml/json manually + removeUnused(obj: any) { + const metaData = new ObjectMeta(); + metaData.name = obj.metadata.name; + metaData.namespace = obj.metadata.namespace; + metaData.labels = obj.metadata.labels; + metaData.annotations = obj.metadata.annotations; + obj.metadata = metaData; + obj.status = undefined; + } } diff --git a/src/frontend/src/app/portal/sidenav/sidenav.component.html b/src/frontend/src/app/portal/sidenav/sidenav.component.html index c7d1a6e41..d1c14235f 100644 --- a/src/frontend/src/app/portal/sidenav/sidenav.component.html +++ b/src/frontend/src/app/portal/sidenav/sidenav.component.html @@ -27,15 +27,6 @@ {{'MENU.STATEFULSET' | translate}} - - - {{'MENU.DAEMONSET' | translate}} - {{'MENU.CRONJOB' | translate}} + + + {{'MENU.DAEMONSET' | translate}} +