diff --git a/docs/apidoc/swagger.json b/docs/apidoc/swagger.json index affcd2b52..b67b1f056 100644 --- a/docs/apidoc/swagger.json +++ b/docs/apidoc/swagger.json @@ -3644,14 +3644,15 @@ "required": true }, { - "type": "string", - "description": "if specified, query the definition supported by the env.", - "name": "envName", + "type": "boolean", + "default": false, + "description": "query all definitions include hidden in UI", + "name": "queryAll", "in": "query" }, { "type": "string", - "description": "if specified, query the trait definition applied to the workload.", + "description": "if specified, query the trait definition applied to the workload", "name": "appliedWorkload", "in": "query" } @@ -3682,7 +3683,7 @@ "tags": [ "definition" ], - "summary": "detail definition", + "summary": "Detail a definition", "operationId": "detailDefinition", "parameters": [ { @@ -3712,6 +3713,82 @@ } } }, + "/api/v1/definitions/{definitionName}/status": { + "put": { + "consumes": [ + "application/xml", + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "tags": [ + "definition" + ], + "summary": "Update the status for a definition", + "operationId": "updateDefinitionStatus", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UpdateDefinitionStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SimpleResponse" + } + }, + "500": { + "description": "Bummer, something went wrong" + } + } + } + }, + "/api/v1/definitions/{definitionName}/uischema": { + "put": { + "consumes": [ + "application/xml", + "application/json" + ], + "produces": [ + "application/json", + "application/xml" + ], + "tags": [ + "definition" + ], + "summary": "Update the UI schema for a definition", + "operationId": "updateUISchema", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1.UpdateUISchemaRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/v1.SimpleResponse" + } + }, + "500": { + "description": "Bummer, something went wrong" + } + } + } + }, "/api/v1/enabled_addon": { "get": { "consumes": [ @@ -3951,31 +4028,6 @@ } } }, - "/api/v1/policy_definitions": { - "get": { - "consumes": [ - "application/xml", - "application/json" - ], - "produces": [ - "application/json", - "application/xml" - ], - "tags": [ - "definition" - ], - "summary": "list all policydefinition", - "operationId": "noop", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/v1.ListPolicyDefinitionResponse" - } - } - } - } - }, "/api/v1/projects": { "get": { "consumes": [ @@ -6428,6 +6480,9 @@ "suspend": { "type": "boolean" }, + "suspendState": { + "type": "string" + }, "terminated": { "type": "boolean" } @@ -7044,42 +7099,6 @@ } } }, - "types.Parameter": { - "required": [ - "name" - ], - "properties": { - "alias": { - "type": "string" - }, - "default": { - "$ref": "#/definitions/types.Parameter.default" - }, - "ignore": { - "type": "boolean" - }, - "jsonType": { - "type": "string" - }, - "name": { - "type": "string" - }, - "required": { - "type": "boolean" - }, - "short": { - "type": "string" - }, - "type": { - "type": "integer", - "format": "int32" - }, - "usage": { - "type": "string" - } - } - }, - "types.Parameter.default": {}, "types.Reference": { "required": [ "name" @@ -7371,8 +7390,8 @@ }, "v1.AddonStatusResponse": { "required": [ - "phase", "name", + "phase", "args" ], "properties": { @@ -7529,11 +7548,11 @@ "v1.ApplicationDeployResponse": { "required": [ "createTime", - "status", - "envName", - "version", "note", - "triggerType" + "envName", + "triggerType", + "version", + "status" ], "properties": { "codeInfo": { @@ -8648,8 +8667,11 @@ "v1.DefinitionBase": { "required": [ "name", + "alias", "description", - "icon" + "icon", + "status", + "labels" ], "properties": { "alias": { @@ -8664,12 +8686,21 @@ "icon": { "type": "string" }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, "name": { "type": "string" }, "policy": { "$ref": "#/definitions/v1beta1.PolicyDefinitionSpec" }, + "status": { + "type": "string" + }, "trait": { "$ref": "#/definitions/v1beta1.TraitDefinitionSpec" }, @@ -8683,11 +8714,11 @@ }, "v1.DetailAddonResponse": { "required": [ - "version", "invisible", - "name", + "version", "description", "icon", + "name", "schema", "uiSchema", "definitions", @@ -8767,13 +8798,13 @@ }, "v1.DetailApplicationResponse": { "required": [ - "alias", - "createTime", "updateTime", - "name", "project", + "createTime", "description", "icon", + "name", + "alias", "policies", "envBindings", "applicationType", @@ -8834,20 +8865,20 @@ }, "v1.DetailClusterResponse": { "required": [ - "name", + "description", "status", "dashboardURL", - "labels", - "kubeConfig", - "kubeConfigSecret", - "updateTime", + "name", "alias", - "icon", - "reason", + "provider", "apiServerURL", "createTime", - "description", - "provider", + "updateTime", + "reason", + "kubeConfig", + "icon", + "labels", + "kubeConfigSecret", "resourceInfo" ], "properties": { @@ -8905,14 +8936,14 @@ }, "v1.DetailComponentResponse": { "required": [ - "creator", - "main", + "name", "type", "createTime", - "alias", - "name", "updateTime", + "creator", + "main", "appPrimaryKey", + "alias", "definition" ], "properties": { @@ -8997,30 +9028,72 @@ }, "v1.DetailDefinitionResponse": { "required": [ + "alias", + "description", + "icon", + "status", + "name", + "labels", "schema", "uiSchema" ], "properties": { + "alias": { + "type": "string" + }, + "component": { + "$ref": "#/definitions/v1beta1.ComponentDefinitionSpec" + }, + "description": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "type": "string" + }, + "policy": { + "$ref": "#/definitions/v1beta1.PolicyDefinitionSpec" + }, "schema": { "type": "string" }, + "status": { + "type": "string" + }, + "trait": { + "$ref": "#/definitions/v1beta1.TraitDefinitionSpec" + }, "uiSchema": { "type": "array", "items": { "$ref": "#/definitions/utils.UIParameter" } + }, + "workflowStep": { + "$ref": "#/definitions/v1beta1.WorkflowStepDefinitionSpec" + }, + "workloadType": { + "type": "string" } } }, "v1.DetailPolicyResponse": { "required": [ + "updateTime", + "name", + "type", "description", "creator", "properties", - "createTime", - "updateTime", - "name", - "type" + "createTime" ], "properties": { "createTime": { @@ -9050,17 +9123,17 @@ }, "v1.DetailRevisionResponse": { "required": [ - "appPrimaryKey", - "deployUser", - "note", - "envName", - "updateTime", - "workflowName", "createTime", "status", - "reason", + "updateTime", + "version", "triggerType", - "version" + "appPrimaryKey", + "note", + "reason", + "deployUser", + "workflowName", + "envName" ], "properties": { "appPrimaryKey": { @@ -9114,10 +9187,10 @@ }, "v1.DetailTargetResponse": { "required": [ - "updateTime", - "project", "name", - "createTime" + "updateTime", + "createTime", + "project" ], "properties": { "alias": { @@ -9157,11 +9230,11 @@ }, "v1.DetailUserResponse": { "required": [ + "disabled", "createTime", "lastLoginTime", "name", "email", - "disabled", "projects", "roles" ], @@ -9202,12 +9275,12 @@ }, "v1.DetailWorkflowRecordResponse": { "required": [ - "namespace", - "workflowName", "workflowAlias", "applicationRevision", "status", "name", + "namespace", + "workflowName", "deployTime", "deployUser", "note", @@ -9259,14 +9332,14 @@ }, "v1.DetailWorkflowResponse": { "required": [ - "createTime", - "updateTime", "name", - "alias", "enable", + "envName", + "updateTime", + "alias", "description", "default", - "envName" + "createTime" ], "properties": { "alias": { @@ -9673,19 +9746,6 @@ } } }, - "v1.ListPolicyDefinitionResponse": { - "required": [ - "policyDefinitions" - ], - "properties": { - "policyDefinitions": { - "type": "array", - "items": { - "$ref": "#/definitions/v1.PolicyDefinition" - } - } - } - }, "v1.ListProjectResponse": { "required": [ "projects", @@ -9858,11 +9918,11 @@ }, "v1.LoginUserInfoResponse": { "required": [ - "email", "disabled", "createTime", "lastLoginTime", "name", + "email", "projects", "platformPermissions", "projectPermissions" @@ -10036,27 +10096,6 @@ } } }, - "v1.PolicyDefinition": { - "required": [ - "name", - "description", - "parameters" - ], - "properties": { - "description": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parameters": { - "type": "array", - "items": { - "$ref": "#/definitions/types.Parameter" - } - } - } - }, "v1.ProjectBase": { "required": [ "name", @@ -10178,19 +10217,25 @@ "clusterCount": { "type": "string" }, - "enabledAddon": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "topKCompDef": { + "componentDefinitionTopList": { "type": "array", "items": { "type": "string" } }, - "topKTraitDef": { + "enableAddonList": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "policyDefinitionTopList": { + "type": "array", + "items": { + "type": "string" + } + }, + "traitDefinitionTopList": { "type": "array", "items": { "type": "string" @@ -10199,12 +10244,18 @@ "updateTime": { "type": "string", "format": "date-time" + }, + "workflowDefinitionTopList": { + "type": "array", + "items": { + "type": "string" + } } } }, "v1.SystemInfo": { "required": [ - "installID", + "platformID", "enableCollection", "loginType" ], @@ -10212,11 +10263,15 @@ "enableCollection": { "type": "boolean" }, - "installID": { - "type": "string" + "installTime": { + "type": "string", + "format": "date-time" }, "loginType": { "type": "string" + }, + "platformID": { + "type": "string" } } }, @@ -10239,7 +10294,7 @@ }, "v1.SystemInfoResponse": { "required": [ - "installID", + "platformID", "enableCollection", "loginType", "systemVersion" @@ -10248,12 +10303,16 @@ "enableCollection": { "type": "boolean" }, - "installID": { - "type": "string" + "installTime": { + "type": "string", + "format": "date-time" }, "loginType": { "type": "string" }, + "platformID": { + "type": "string" + }, "statisticInfo": { "$ref": "#/definitions/v1.StatisticInfo" }, @@ -10404,6 +10463,20 @@ } } }, + "v1.UpdateDefinitionStatusRequest": { + "required": [ + "type", + "hiddenInUI" + ], + "properties": { + "hiddenInUI": { + "type": "boolean" + }, + "type": { + "type": "string" + } + } + }, "v1.UpdatePolicyRequest": { "required": [ "description", @@ -10478,6 +10551,23 @@ } } }, + "v1.UpdateUISchemaRequest": { + "required": [ + "type", + "uiSchema" + ], + "properties": { + "type": { + "type": "string" + }, + "uiSchema": { + "type": "array", + "items": { + "$ref": "#/definitions/utils.UIParameter" + } + } + } + }, "v1.UpdateWorkflowRequest": { "required": [ "default" diff --git a/pkg/apiserver/rest/apis/v1/types.go b/pkg/apiserver/rest/apis/v1/types.go index aa09fc9a6..fc3a523d8 100644 --- a/pkg/apiserver/rest/apis/v1/types.go +++ b/pkg/apiserver/rest/apis/v1/types.go @@ -803,16 +803,32 @@ type ListDefinitionResponse struct { // DetailDefinitionResponse get definition detail type DetailDefinitionResponse struct { - APISchema *openapi3.Schema `json:"schema"` - UISchema []*utils.UIParameter `json:"uiSchema"` + DefinitionBase + APISchema *openapi3.Schema `json:"schema"` + UISchema utils.UISchema `json:"uiSchema"` +} + +// UpdateUISchemaRequest the request body struct about updated ui schema +type UpdateUISchemaRequest struct { + DefinitionType string `json:"type"` + UISchema utils.UISchema `json:"uiSchema"` +} + +// UpdateDefinitionStatusRequest the request body struct about updated definition +// Only support set the status of definition +type UpdateDefinitionStatusRequest struct { + DefinitionType string `json:"type"` + HiddenInUI bool `json:"hiddenInUI"` } // DefinitionBase is the definition base model type DefinitionBase struct { - Name string `json:"name"` - Alias string `json:"alias" validate:"checkalias" optional:"true"` - Description string `json:"description"` - Icon string `json:"icon"` + Name string `json:"name"` + Alias string `json:"alias"` + Description string `json:"description"` + Icon string `json:"icon"` + Status string `json:"status"` + Labels map[string]string `json:"labels"` // WorkloadType the component workload type // Deprecated: it same as component.workload.type WorkloadType string `json:"workloadType,omitempty"` diff --git a/pkg/apiserver/rest/usecase/definition.go b/pkg/apiserver/rest/usecase/definition.go index 28b04849a..57719bb8b 100644 --- a/pkg/apiserver/rest/usecase/definition.go +++ b/pkg/apiserver/rest/usecase/definition.go @@ -32,7 +32,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" k8stypes "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/yaml" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" @@ -46,11 +45,13 @@ import ( // DefinitionUsecase definition usecase, Implement the management of ComponentDefinition、TraitDefinition and WorkflowStepDefinition. type DefinitionUsecase interface { // ListDefinitions list definition base info - ListDefinitions(ctx context.Context, envName, defType, appliedWorkloads string) ([]*apisv1.DefinitionBase, error) + ListDefinitions(ctx context.Context, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) // DetailDefinition get definition detail DetailDefinition(ctx context.Context, name, defType string) (*apisv1.DetailDefinitionResponse, error) // AddDefinitionUISchema add or update custom definition ui schema - AddDefinitionUISchema(ctx context.Context, name, defType, configRaw string) ([]*utils.UIParameter, error) + AddDefinitionUISchema(ctx context.Context, name, defType string, schema []*utils.UIParameter) ([]*utils.UIParameter, error) + // UpdateDefinitionStatus update the status of definition + UpdateDefinitionStatus(ctx context.Context, name string, status apisv1.UpdateDefinitionStatusRequest) (*apisv1.DetailDefinitionResponse, error) } type definitionUsecaseImpl struct { @@ -58,6 +59,18 @@ type definitionUsecaseImpl struct { caches *utils.MemoryCacheStore } +// DefinitionQueryOption define a set of query options +type DefinitionQueryOption struct { + Type string `json:"type"` + AppliedWorkloads string `json:"appliedWorkloads"` + QueryAll bool `json:"queryAll"` +} + +// String return cache key string +func (d DefinitionQueryOption) String() string { + return fmt.Sprintf("type:%s/appliedWorkloads:%s/queryAll:%v", d.Type, d.AppliedWorkloads, d.QueryAll) +} + const ( definitionAPIVersion = "core.oam.dev/v1beta1" kindComponentDefinition = "ComponentDefinition" @@ -75,36 +88,19 @@ func NewDefinitionUsecase() DefinitionUsecase { return &definitionUsecaseImpl{kubeClient: kubecli, caches: utils.NewMemoryCacheStore(context.Background())} } -func (d *definitionUsecaseImpl) ListDefinitions(ctx context.Context, envName, defType, appliedWorkload string) ([]*apisv1.DefinitionBase, error) { +func (d *definitionUsecaseImpl) ListDefinitions(ctx context.Context, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { defs := &unstructured.UnstructuredList{} - switch defType { - case "component": - defs.SetAPIVersion(definitionAPIVersion) - defs.SetKind(kindComponentDefinition) - return d.listDefinitions(ctx, defs, kindComponentDefinition, "") - - case "trait": - defs.SetAPIVersion(definitionAPIVersion) - defs.SetKind(kindTraitDefinition) - return d.listDefinitions(ctx, defs, kindTraitDefinition, appliedWorkload) - - case "workflowstep": - defs.SetAPIVersion(definitionAPIVersion) - defs.SetKind(kindWorkflowStepDefinition) - return d.listDefinitions(ctx, defs, kindWorkflowStepDefinition, "") - - case "policy": - defs.SetAPIVersion(definitionAPIVersion) - defs.SetKind(kindPolicyDefinition) - return d.listDefinitions(ctx, defs, kindPolicyDefinition, "") - - default: - return nil, bcode.ErrDefinitionTypeNotSupport + version, kind, err := getKindAndVersion(ops.Type) + if err != nil { + return nil, err } + defs.SetAPIVersion(version) + defs.SetKind(kind) + return d.listDefinitions(ctx, defs, kind, ops) } -func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstructured.UnstructuredList, cache, appliedWorkload string) ([]*apisv1.DefinitionBase, error) { - if mc := d.caches.Get(cache); mc != nil && appliedWorkload == "" { +func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstructured.UnstructuredList, kind string, ops DefinitionQueryOption) ([]*apisv1.DefinitionBase, error) { + if mc := d.caches.Get(ops.String()); mc != nil { return mc.([]*apisv1.DefinitionBase), nil } matchLabels := metav1.LabelSelector{ @@ -113,12 +109,14 @@ func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstr Key: types.LabelDefinitionDeprecated, Operator: metav1.LabelSelectorOpDoesNotExist, }, - { - Key: types.LabelDefinitionHidden, - Operator: metav1.LabelSelectorOpDoesNotExist, - }, }, } + if !ops.QueryAll { + matchLabels.MatchExpressions = append(matchLabels.MatchExpressions, metav1.LabelSelectorRequirement{ + Key: types.LabelDefinitionHidden, + Operator: metav1.LabelSelectorOpDoesNotExist, + }) + } selector, err := metav1.LabelSelectorAsSelector(&matchLabels) if err != nil { return nil, err @@ -130,14 +128,14 @@ func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstr } var defs []*apisv1.DefinitionBase for _, def := range list.Items { - if appliedWorkload != "" { + if ops.AppliedWorkloads != "" { traitDef := &v1beta1.TraitDefinition{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, traitDef); err != nil { return nil, errors.Wrap(err, "invalid trait definition") } filter := false for _, workload := range traitDef.Spec.AppliesToWorkloads { - if workload == appliedWorkload || workload == "*" { + if workload == ops.AppliedWorkloads || workload == "*" { filter = true break } @@ -146,53 +144,102 @@ func (d *definitionUsecaseImpl) listDefinitions(ctx context.Context, list *unstr continue } } - definition := &apisv1.DefinitionBase{ - Name: def.GetName(), - Alias: def.GetAnnotations()[types.AnnoDefinitionAlias], - Description: def.GetAnnotations()[types.AnnoDefinitionDescription], - Icon: def.GetAnnotations()[types.AnnoDefinitionIcon], - } - if cache == kindComponentDefinition { - compDef := &v1beta1.ComponentDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, compDef); err != nil { - return nil, errors.Wrap(err, "invalid component definition") - } - definition.WorkloadType = compDef.Spec.Workload.Type - definition.Component = &compDef.Spec - } - if cache == kindTraitDefinition { - traitDef := &v1beta1.TraitDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, traitDef); err != nil { - return nil, errors.Wrap(err, "invalid trait definition") - } - definition.Trait = &traitDef.Spec - } - if cache == kindWorkflowStepDefinition { - workflowStepDef := &v1beta1.WorkflowStepDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, workflowStepDef); err != nil { - return nil, errors.Wrap(err, "invalid trait definition") - } - definition.WorkflowStep = &workflowStepDef.Spec - } - if cache == kindPolicyDefinition { - policyDef := &v1beta1.PolicyDefinition{} - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, policyDef); err != nil { - return nil, errors.Wrap(err, "invalid trait definition") - } - definition.Policy = &policyDef.Spec + definition, err := convertDefinitionBase(def, kind) + if err != nil { + log.Logger.Errorf("convert definition to base failure %s", err.Error()) + continue } defs = append(defs, definition) } - if appliedWorkload == "" { - d.caches.Put(cache, defs, time.Minute*3) + if ops.AppliedWorkloads == "" { + d.caches.Put(ops.String(), defs, time.Minute*3) } return defs, nil } +func getKindAndVersion(defType string) (apiVersion, kind string, err error) { + switch defType { + case "component": + return definitionAPIVersion, kindComponentDefinition, nil + + case "trait": + return definitionAPIVersion, kindTraitDefinition, nil + + case "workflowstep": + return definitionAPIVersion, kindWorkflowStepDefinition, nil + + case "policy": + return definitionAPIVersion, kindPolicyDefinition, nil + + default: + return "", "", bcode.ErrDefinitionTypeNotSupport + } +} + +func convertDefinitionBase(def unstructured.Unstructured, kind string) (*apisv1.DefinitionBase, error) { + definition := &apisv1.DefinitionBase{ + Name: def.GetName(), + Alias: def.GetAnnotations()[types.AnnoDefinitionAlias], + Description: def.GetAnnotations()[types.AnnoDefinitionDescription], + Icon: def.GetAnnotations()[types.AnnoDefinitionIcon], + Labels: def.GetLabels(), + Status: func() string { + if _, exist := def.GetLabels()[types.LabelDefinitionHidden]; exist { + return "disable" + } + return "enable" + }(), + } + if kind == kindComponentDefinition { + compDef := &v1beta1.ComponentDefinition{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, compDef); err != nil { + return nil, errors.Wrap(err, "invalid component definition") + } + definition.WorkloadType = compDef.Spec.Workload.Type + definition.Component = &compDef.Spec + } + if kind == kindTraitDefinition { + traitDef := &v1beta1.TraitDefinition{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, traitDef); err != nil { + return nil, errors.Wrap(err, "invalid trait definition") + } + definition.Trait = &traitDef.Spec + } + if kind == kindWorkflowStepDefinition { + workflowStepDef := &v1beta1.WorkflowStepDefinition{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, workflowStepDef); err != nil { + return nil, errors.Wrap(err, "invalid trait definition") + } + definition.WorkflowStep = &workflowStepDef.Spec + } + if kind == kindPolicyDefinition { + policyDef := &v1beta1.PolicyDefinition{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, policyDef); err != nil { + return nil, errors.Wrap(err, "invalid trait definition") + } + definition.Policy = &policyDef.Spec + } + return definition, nil +} + // DetailDefinition get definition detail func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defType string) (*apisv1.DetailDefinitionResponse, error) { - if !utils.StringsContain([]string{"component", "trait", "workflowstep", "policy"}, defType) { - return nil, bcode.ErrDefinitionTypeNotSupport + def := &unstructured.Unstructured{} + version, kind, err := getKindAndVersion(defType) + if err != nil { + return nil, err + } + def.SetAPIVersion(version) + def.SetKind(kind) + if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { + if apierrors.IsNotFound(err) { + return nil, bcode.ErrDefinitionNotFound + } + return nil, err + } + base, err := convertDefinitionBase(*def, kind) + if err != nil { + return nil, err } var cm v1.ConfigMap if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{ @@ -218,8 +265,9 @@ func (d *definitionUsecaseImpl) DetailDefinition(ctx context.Context, name, defT // patch from custom ui schema customUISchema := d.renderCustomUISchema(ctx, name, defType, defaultUISchema) return &apisv1.DetailDefinitionResponse{ - APISchema: schema, - UISchema: customUISchema, + DefinitionBase: *base, + APISchema: schema, + UISchema: customUISchema, }, nil } @@ -247,14 +295,8 @@ func (d *definitionUsecaseImpl) renderCustomUISchema(ctx context.Context, name, } // AddDefinitionUISchema add definition custom ui schema config -func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, defType, configRaw string) ([]*utils.UIParameter, error) { - var uiParameters []*utils.UIParameter - err := yaml.Unmarshal([]byte(configRaw), &uiParameters) - if err != nil { - log.Logger.Errorf("yaml unmarshal failure %s", err.Error()) - return nil, bcode.ErrInvalidDefinitionUISchema - } - dataBate, err := json.Marshal(uiParameters) +func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, defType string, schema []*utils.UIParameter) ([]*utils.UIParameter, error) { + dataBate, err := json.Marshal(schema) if err != nil { log.Logger.Errorf("json marshal failure %s", err.Error()) return nil, bcode.ErrInvalidDefinitionUISchema @@ -285,7 +327,46 @@ func (d *definitionUsecaseImpl) AddDefinitionUISchema(ctx context.Context, name, return nil, err } } - return uiParameters, nil + res, err := d.DetailDefinition(ctx, name, defType) + if err != nil { + return nil, err + } + return res.UISchema, nil +} + +// UpdateDefinitionStatus update the status of the definition +func (d *definitionUsecaseImpl) UpdateDefinitionStatus(ctx context.Context, name string, update apisv1.UpdateDefinitionStatusRequest) (*apisv1.DetailDefinitionResponse, error) { + def := &unstructured.Unstructured{} + version, kind, err := getKindAndVersion(update.DefinitionType) + if err != nil { + return nil, err + } + def.SetAPIVersion(version) + def.SetKind(kind) + if err := d.kubeClient.Get(ctx, k8stypes.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: name}, def); err != nil { + if apierrors.IsNotFound(err) { + return nil, bcode.ErrDefinitionNotFound + } + return nil, err + } + _, exist := def.GetLabels()[types.LabelDefinitionHidden] + if exist && !update.HiddenInUI { + labels := def.GetLabels() + delete(labels, types.LabelDefinitionHidden) + def.SetLabels(labels) + if err := d.kubeClient.Update(ctx, def); err != nil { + return nil, err + } + } + if !exist && update.HiddenInUI { + labels := def.GetLabels() + labels[types.LabelDefinitionHidden] = "true" + def.SetLabels(labels) + if err := d.kubeClient.Update(ctx, def); err != nil { + return nil, err + } + } + return d.DetailDefinition(ctx, name, update.DefinitionType) } func patchSchema(defaultSchema, customSchema []*utils.UIParameter) []*utils.UIParameter { diff --git a/pkg/apiserver/rest/usecase/definition_test.go b/pkg/apiserver/rest/usecase/definition_test.go index 4aa2b3d4f..2c1df9b43 100644 --- a/pkg/apiserver/rest/usecase/definition_test.go +++ b/pkg/apiserver/rest/usecase/definition_test.go @@ -20,14 +20,13 @@ import ( "context" "encoding/json" "io/ioutil" - "path" - "strings" "testing" "github.com/getkin/kin-openapi/openapi3" "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" @@ -62,7 +61,8 @@ var _ = Describe("Test namespace usecase functions", func() { Expect(err).Should(Succeed()) err = k8sClient.Create(context.Background(), &cd) Expect(err).Should(Succeed()) - definitions, err := definitionUsecase.ListDefinitions(context.TODO(), "", "component", "") + + definitions, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "component"}) Expect(err).Should(BeNil()) var selectDefinition *v1.DefinitionBase for i, definition := range definitions { @@ -83,7 +83,7 @@ var _ = Describe("Test namespace usecase functions", func() { Expect(err).Should(Succeed()) err = k8sClient.Create(context.Background(), &td) Expect(err).Should(Succeed()) - traits, err := definitionUsecase.ListDefinitions(context.TODO(), "", "trait", "") + traits, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "trait"}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(traits), 1)).Should(BeEmpty()) Expect(cmp.Diff(traits[0].Name, "myingress")).Should(BeEmpty()) @@ -99,7 +99,8 @@ var _ = Describe("Test namespace usecase functions", func() { Expect(err).Should(Succeed()) err = k8sClient.Create(context.Background(), &sd) Expect(err).Should(Succeed()) - wfstep, err := definitionUsecase.ListDefinitions(context.TODO(), "", "workflowstep", "") + + wfstep, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep"}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(wfstep), 1)).Should(BeEmpty()) Expect(cmp.Diff(wfstep[0].Name, "apply-application")).Should(BeEmpty()) @@ -107,6 +108,18 @@ var _ = Describe("Test namespace usecase functions", func() { Expect(wfstep[0].WorkflowStep.Schematic).ShouldNot(BeNil()) Expect(wfstep[0].Alias).Should(Equal("test-alias")) + step, err = ioutil.ReadFile("./testdata/apply-application-hide.yaml") + Expect(err).Should(Succeed()) + var sd2 v1beta1.WorkflowStepDefinition + err = yaml.Unmarshal(step, &sd2) + Expect(err).Should(Succeed()) + err = k8sClient.Create(context.Background(), &sd2) + Expect(err).Should(Succeed()) + + allstep, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "workflowstep", QueryAll: true}) + Expect(err).Should(BeNil()) + Expect(cmp.Diff(len(allstep), 2)).Should(BeEmpty()) + By("List policy definitions") var policy = v1beta1.PolicyDefinition{ ObjectMeta: metav1.ObjectMeta{ @@ -123,7 +136,7 @@ var _ = Describe("Test namespace usecase functions", func() { } err = k8sClient.Create(context.Background(), &policy) Expect(err).Should(Succeed()) - policies, err := definitionUsecase.ListDefinitions(context.TODO(), "", "policy", "") + policies, err := definitionUsecase.ListDefinitions(context.TODO(), DefinitionQueryOption{Type: "policy"}) Expect(err).Should(BeNil()) Expect(cmp.Diff(len(policies), 1)).Should(BeEmpty()) Expect(cmp.Diff(policies[0].Name, "health")).Should(BeEmpty()) @@ -133,6 +146,14 @@ var _ = Describe("Test namespace usecase functions", func() { }) It("Test DetailDefinition function", func() { + + webserver, err := ioutil.ReadFile("./testdata/apply-object.yaml") + Expect(err).Should(Succeed()) + var cd v1beta1.WorkflowStepDefinition + err = yaml.Unmarshal(webserver, &cd) + Expect(err).Should(Succeed()) + Expect(k8sClient.Create(context.Background(), &cd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "workflowstep-schema-apply-object", @@ -142,16 +163,17 @@ var _ = Describe("Test namespace usecase functions", func() { types.OpenapiV3JSONSchema: `{"properties":{"batchPartition":{"title":"batchPartition","type":"integer"},"volumes": {"description":"Specify volume type, options: pvc, configMap, secret, emptyDir","enum":["pvc","configMap","secret","emptyDir"],"title":"volumes","type":"string"}, "rolloutBatches":{"items":{"properties":{"replicas":{"title":"replicas","type":"integer"}},"required":["replicas"],"type":"object"},"title":"rolloutBatches","type":"array"},"targetRevision":{"title":"targetRevision","type":"string"},"targetSize":{"title":"targetSize","type":"integer"}},"required":["targetRevision","targetSize"],"type":"object"}`, }, } - err := k8sClient.Create(context.Background(), cm) + err = k8sClient.Create(context.Background(), cm) Expect(err).Should(Succeed()) - schema, err := definitionUsecase.DetailDefinition(context.TODO(), "apply-object", "workflowstep") + definitionDetail, err := definitionUsecase.DetailDefinition(context.TODO(), "apply-object", "workflowstep") Expect(err).Should(Succeed()) schemaFromCM := &openapi3.Schema{} err = schemaFromCM.UnmarshalJSON([]byte(cm.Data["openapi-v3-json-schema"])) Expect(err).Should(Succeed()) - Expect(schema.APISchema).Should(Equal(schemaFromCM)) + Expect(definitionDetail.APISchema).Should(Equal(schemaFromCM)) + Expect(definitionDetail.WorkflowStep).ShouldNot(BeNil()) }) It("Test renderDefaultUISchema", func() { @@ -188,30 +210,42 @@ var _ = Describe("Test namespace usecase functions", func() { It("Test sortDefaultUISchema", testSortDefaultUISchema) + It("Test update ui schema", func() { + du := NewDefinitionUsecase() + cdata, err := ioutil.ReadFile("./testdata/workflowstep-apply-object.yaml") + Expect(err).Should(Succeed()) + var schema utils.UISchema + yaml.Unmarshal(cdata, &schema) + uiSchema, err := du.AddDefinitionUISchema(context.TODO(), "apply-object", "workflowstep", schema) + Expect(err).Should(Succeed()) + for _, param := range uiSchema { + if param.JSONKey == "batchPartition" { + Expect(len(param.Conditions)).Should(Equal(1)) + Expect(param.Validate.Required).Should(Equal(true)) + Expect(param.Sort).Should(Equal(uint(77))) + } + } + }) + + It("Test update status of the definition", func() { + du := NewDefinitionUsecase() + detail, err := du.UpdateDefinitionStatus(context.TODO(), "apply-object", v1.UpdateDefinitionStatusRequest{ + DefinitionType: "workflowstep", + HiddenInUI: true, + }) + Expect(err).Should(Succeed()) + Expect(detail.Status).Should(Equal("disable")) + + detail, err = du.UpdateDefinitionStatus(context.TODO(), "apply-object", v1.UpdateDefinitionStatusRequest{ + DefinitionType: "workflowstep", + HiddenInUI: false, + }) + Expect(err).Should(Succeed()) + Expect(detail.Status).Should(Equal("enable")) + }) + }) -func TestAddDefinitionUISchema(t *testing.T) { - du := NewDefinitionUsecase() - schemaFiles, err := ioutil.ReadDir("../../../../vela-templates/definitions/uischema") - if err != nil { - t.Fatal(err) - } - for _, sf := range schemaFiles { - if !sf.IsDir() { - typeNames := strings.SplitN(sf.Name(), "-", 2) - cdata, err := ioutil.ReadFile(path.Join("../../../../vela-templates/definitions/uischema", sf.Name())) - if err != nil { - t.Fatal(err) - } - definitionName := strings.Replace(typeNames[1], path.Ext(sf.Name()), "", -1) - _, err = du.AddDefinitionUISchema(context.TODO(), definitionName, typeNames[0], string(cdata)) - if err != nil { - t.Fatal(err) - } - t.Logf("create ui schema %s for %s definition", definitionName, typeNames[0]) - } - } -} func testSortDefaultUISchema() { var params = []*utils.UIParameter{ { @@ -333,3 +367,12 @@ func testSortDefaultUISchema() { Expect(param.Sort).Should(Equal(expectedParams[i].Sort)) } } + +func TestDefinitionQueryOption(t *testing.T) { + assert.Equal(t, DefinitionQueryOption{ + Type: "workflowstep", + }.String() == DefinitionQueryOption{ + Type: "workflowstep", + QueryAll: true, + }.String(), false) +} diff --git a/pkg/apiserver/rest/usecase/rbac.go b/pkg/apiserver/rest/usecase/rbac.go index 8a75310d8..c4edb841e 100644 --- a/pkg/apiserver/rest/usecase/rbac.go +++ b/pkg/apiserver/rest/usecase/rbac.go @@ -207,7 +207,9 @@ var ResourceMaps = map[string]resourceMetadata{ "role": {}, "permission": {}, "systemSetting": {}, - "definition": {}, + "definition": { + pathName: "definitionName", + }, "configType": { pathName: "configType", subResources: map[string]resourceMetadata{ diff --git a/pkg/apiserver/rest/usecase/testdata/apply-application-hide.yaml b/pkg/apiserver/rest/usecase/testdata/apply-application-hide.yaml new file mode 100644 index 000000000..00716fb77 --- /dev/null +++ b/pkg/apiserver/rest/usecase/testdata/apply-application-hide.yaml @@ -0,0 +1,20 @@ +apiVersion: core.oam.dev/v1beta1 +kind: WorkflowStepDefinition +metadata: + annotations: + definition.oam.dev/description: Apply application for your workflow steps + definition.oam.dev/alias: test-alias + labels: + custom.definition.oam.dev/ui-hidden: "true" + name: apply-application-hidden + namespace: vela-system +spec: + schematic: + cue: + template: | + import ( + "vela/op" + ) + + // apply application + output: op.#ApplyApplication & {} \ No newline at end of file diff --git a/pkg/apiserver/rest/usecase/testdata/apply-object.yaml b/pkg/apiserver/rest/usecase/testdata/apply-object.yaml new file mode 100644 index 000000000..add2be0e4 --- /dev/null +++ b/pkg/apiserver/rest/usecase/testdata/apply-object.yaml @@ -0,0 +1,30 @@ +# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file. +# Definition source cue file: vela-templates/definitions/internal/apply-object.cue +apiVersion: core.oam.dev/v1beta1 +kind: WorkflowStepDefinition +metadata: + annotations: + definition.oam.dev/description: Apply raw kubernetes objects for your workflow steps + labels: + custom.definition.oam.dev/ui-hidden: "true" + name: apply-object + namespace: vela-system +spec: + schematic: + cue: + template: | + import ( + "vela/op" + ) + + apply: op.#Apply & { + value: parameter.value + cluster: parameter.cluster + } + parameter: { + // +usage=Specify the value of the object + value: {...} + // +usage=Specify the cluster of the object + cluster: *"" | string + } + diff --git a/pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml b/pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml index 76b489476..c1c141be4 100644 --- a/pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml +++ b/pkg/apiserver/rest/usecase/testdata/applyapplication-sd.yaml @@ -17,4 +17,4 @@ spec: ) // apply application - output: op.#ApplyApplication & {} + output: op.#ApplyApplication & {} \ No newline at end of file diff --git a/pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml b/pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml index a27a31cd5..7ad343842 100755 --- a/pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml +++ b/pkg/apiserver/rest/usecase/testdata/ui-custom-schema.yaml @@ -86,7 +86,7 @@ - jsonKey: annotations sort: 19 -- jsonKey: lables +- jsonKey: labels sort: 21 - jsonKey: addRevisionLabel diff --git a/pkg/apiserver/rest/usecase/testdata/workflowstep-apply-object.yaml b/pkg/apiserver/rest/usecase/testdata/workflowstep-apply-object.yaml new file mode 100644 index 000000000..1fa0584a3 --- /dev/null +++ b/pkg/apiserver/rest/usecase/testdata/workflowstep-apply-object.yaml @@ -0,0 +1,8 @@ +- jsonKey: batchPartition + sort: 77 + conditions: + - jsonKey: xxx + op: == + value: 123 + validate: + required: true \ No newline at end of file diff --git a/pkg/apiserver/rest/utils/bcode/bcode.go b/pkg/apiserver/rest/utils/bcode/bcode.go index dc7829700..0b652c635 100644 --- a/pkg/apiserver/rest/utils/bcode/bcode.go +++ b/pkg/apiserver/rest/utils/bcode/bcode.go @@ -52,6 +52,15 @@ func (b *Bcode) Error() string { return fmt.Sprintf("HTTPCode:%d BusinessCode:%d Message:%s", b.HTTPCode, b.BusinessCode, b.Message) } +// SetMessage set new message and return a new bcode instance +func (b *Bcode) SetMessage(message string) *Bcode { + return &Bcode{ + HTTPCode: b.HTTPCode, + BusinessCode: b.BusinessCode, + Message: message, + } +} + var bcodeMap map[int32]*Bcode // NewBcode new business code diff --git a/pkg/apiserver/rest/utils/ui_schema.go b/pkg/apiserver/rest/utils/ui_schema.go index 1532b06da..dbab87925 100644 --- a/pkg/apiserver/rest/utils/ui_schema.go +++ b/pkg/apiserver/rest/utils/ui_schema.go @@ -24,6 +24,20 @@ import ( // UISchema ui schema type UISchema []*UIParameter +// Validate check the ui schema +func (u UISchema) Validate() error { + for _, p := range u { + // check the conditions + for _, c := range p.Conditions { + if err := c.Validate(); err != nil { + return err + } + } + //TODO: other fields check + } + return nil +} + // UIParameter Structured import table simple UI model type UIParameter struct { Sort uint `json:"sort"` @@ -63,6 +77,20 @@ type Condition struct { Action string `json:"action,omitempty"` } +// Validate check the validity of condition +func (c Condition) Validate() error { + if c.JSONKey == "" { + return fmt.Errorf("the json key of the condition can not be empty") + } + if c.Action != "enable" && c.Action != "disable" { + return fmt.Errorf("the action of the condition must be enable or disable") + } + if c.Op != "" && !StringsContain([]string{"==", "!=", "in"}, c.Op) { + return fmt.Errorf("the op of the condition must be `==` 、`!=` and `in`") + } + return nil +} + // Style ui style type Style struct { // ColSpan the width of a responsive layout diff --git a/pkg/apiserver/rest/webservice/definition.go b/pkg/apiserver/rest/webservice/definition.go index bb0d90390..fc07bb55c 100644 --- a/pkg/apiserver/rest/webservice/definition.go +++ b/pkg/apiserver/rest/webservice/definition.go @@ -17,11 +17,14 @@ limitations under the License. package webservice import ( + "strconv" + restfulspec "github.com/emicklei/go-restful-openapi/v2" restful "github.com/emicklei/go-restful/v3" apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" "github.com/oam-dev/kubevela/pkg/apiserver/rest/usecase" + "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils/bcode" ) @@ -45,18 +48,34 @@ func (d *definitionWebservice) GetWebService() *restful.WebService { // TODO: provide project scope api for query definition list // Filter(d.rbacUsecase.CheckPerm("definition", "list")). Param(ws.QueryParameter("type", "query the definition type").DataType("string").Required(true).AllowableValues(map[string]string{"component": "", "trait": "", "workflowstep": ""})). - Param(ws.QueryParameter("envName", "if specified, query the definition supported by the env.").DataType("string")). - Param(ws.QueryParameter("appliedWorkload", "if specified, query the trait definition applied to the workload.").DataType("string")). + Param(ws.QueryParameter("queryAll", "query all definitions include hidden in UI").DataType("boolean").DefaultValue("false")). + Param(ws.QueryParameter("appliedWorkload", "if specified, query the trait definition applied to the workload").DataType("string")). Returns(200, "OK", apis.ListDefinitionResponse{}). Writes(apis.ListDefinitionResponse{}).Do(returns200, returns500)) ws.Route(ws.GET("/{definitionName}").To(d.detailDefinition). - Doc("detail definition"). + Doc("Detail a definition"). // Filter(d.rbacUsecase.CheckPerm("definition", "detail")). Param(ws.PathParameter("definitionName", "identifier of the definition").DataType("string")). Param(ws.QueryParameter("type", "query the definition type").DataType("string")). Metadata(restfulspec.KeyOpenAPITags, tags). - Returns(200, "create success", apis.DetailDefinitionResponse{}). + Returns(200, "create successfully", apis.DetailDefinitionResponse{}). + Writes(apis.DetailDefinitionResponse{}).Do(returns200, returns500)) + + ws.Route(ws.PUT("/{definitionName}/uischema").To(d.updateUISchema). + Doc("Update the UI schema for a definition"). + Filter(d.rbacUsecase.CheckPerm("definition", "update")). + Metadata(restfulspec.KeyOpenAPITags, tags). + Reads(apis.UpdateUISchemaRequest{}). + Returns(200, "update successfully", utils.UISchema{}). + Writes(apis.DetailDefinitionResponse{}).Do(returns200, returns500)) + + ws.Route(ws.PUT("/{definitionName}/status").To(d.updateDefinitionStatus). + Doc("Update the status for a definition"). + Filter(d.rbacUsecase.CheckPerm("definition", "update")). + Metadata(restfulspec.KeyOpenAPITags, tags). + Reads(apis.UpdateDefinitionStatusRequest{}). + Returns(200, "update successfully", utils.UISchema{}). Writes(apis.DetailDefinitionResponse{}).Do(returns200, returns500)) ws.Filter(authCheckFilter) @@ -72,7 +91,15 @@ func NewDefinitionWebservice(du usecase.DefinitionUsecase, rbacUsecase usecase.R } func (d *definitionWebservice) listDefinitions(req *restful.Request, res *restful.Response) { - definitions, err := d.definitionUsecase.ListDefinitions(req.Request.Context(), req.QueryParameter("envName"), req.QueryParameter("type"), req.QueryParameter("appliedWorkload")) + queryAll, err := strconv.ParseBool(req.QueryParameter("queryAll")) + if err != nil { + queryAll = false + } + definitions, err := d.definitionUsecase.ListDefinitions(req.Request.Context(), usecase.DefinitionQueryOption{ + Type: req.QueryParameter("type"), + AppliedWorkloads: req.QueryParameter("appliedWorkload"), + QueryAll: queryAll, + }) if err != nil { bcode.ReturnError(req, res, err) return @@ -94,3 +121,51 @@ func (d *definitionWebservice) detailDefinition(req *restful.Request, res *restf return } } + +func (d *definitionWebservice) updateUISchema(req *restful.Request, res *restful.Response) { + // Verify the validity of parameters + var updateReq apis.UpdateUISchemaRequest + if err := req.ReadEntity(&updateReq); err != nil { + bcode.ReturnError(req, res, err) + return + } + if err := validate.Struct(&updateReq); err != nil { + bcode.ReturnError(req, res, err) + return + } + if err := updateReq.UISchema.Validate(); err != nil { + bcode.ReturnError(req, res, bcode.ErrInvalidDefinitionUISchema.SetMessage(err.Error())) + return + } + schema, err := d.definitionUsecase.AddDefinitionUISchema(req.Request.Context(), req.PathParameter("definitionName"), updateReq.DefinitionType, updateReq.UISchema) + if err != nil { + bcode.ReturnError(req, res, err) + return + } + if err := res.WriteEntity(schema); err != nil { + bcode.ReturnError(req, res, err) + return + } +} + +func (d *definitionWebservice) updateDefinitionStatus(req *restful.Request, res *restful.Response) { + // Verify the validity of parameters + var updateReq apis.UpdateDefinitionStatusRequest + if err := req.ReadEntity(&updateReq); err != nil { + bcode.ReturnError(req, res, err) + return + } + if err := validate.Struct(&updateReq); err != nil { + bcode.ReturnError(req, res, err) + return + } + schema, err := d.definitionUsecase.UpdateDefinitionStatus(req.Request.Context(), req.PathParameter("definitionName"), updateReq) + if err != nil { + bcode.ReturnError(req, res, err) + return + } + if err := res.WriteEntity(schema); err != nil { + bcode.ReturnError(req, res, err) + return + } +} diff --git a/pkg/apiserver/rest/webservice/policy_definition.go b/pkg/apiserver/rest/webservice/policy_definition.go deleted file mode 100644 index b25af48e1..000000000 --- a/pkg/apiserver/rest/webservice/policy_definition.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2021 The KubeVela Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package webservice - -import ( - restfulspec "github.com/emicklei/go-restful-openapi/v2" - restful "github.com/emicklei/go-restful/v3" - - apis "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" -) - -type policyDefinitionWebservice struct { -} - -func (c *policyDefinitionWebservice) GetWebService() *restful.WebService { - ws := new(restful.WebService) - ws.Path(versionPrefix+"/policy_definitions"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML). - Doc("api for policydefinition manage") - - tags := []string{"definition"} - - ws.Route(ws.GET("/").To(noop). - Doc("list all policydefinition"). - Metadata(restfulspec.KeyOpenAPITags, tags). - Returns(200, "OK", apis.ListPolicyDefinitionResponse{}). - Writes(apis.ListPolicyDefinitionResponse{})) - - ws.Filter(authCheckFilter) - return ws -} diff --git a/pkg/apiserver/rest/webservice/webservice.go b/pkg/apiserver/rest/webservice/webservice.go index 4158d0a6b..0c48dd54b 100644 --- a/pkg/apiserver/rest/webservice/webservice.go +++ b/pkg/apiserver/rest/webservice/webservice.go @@ -49,8 +49,6 @@ func GetRegisteredWebService() []WebService { return registeredWebService } -func noop(req *restful.Request, resp *restful.Response) {} - func returns200(b *restful.RouteBuilder) { b.Returns(http.StatusOK, "OK", apisv1.SimpleResponse{Status: "ok"}) } @@ -102,7 +100,6 @@ func Init(ctx context.Context, ds datastore.DataStore, addonCacheTime time.Durat // Resources RegisterWebService(NewClusterWebService(clusterUsecase, rbacUsecase)) RegisterWebService(NewOAMApplication(oamApplicationUsecase, rbacUsecase)) - RegisterWebService(&policyDefinitionWebservice{}) RegisterWebService(&payloadTypesWebservice{}) RegisterWebService(NewTargetWebService(targetUsecase, applicationUsecase, rbacUsecase)) RegisterWebService(NewVelaQLWebService(velaQLUsecase, rbacUsecase)) diff --git a/test/e2e-apiserver-test/definition_test.go b/test/e2e-apiserver-test/definition_test.go index fa6b0308b..890ec3b3f 100644 --- a/test/e2e-apiserver-test/definition_test.go +++ b/test/e2e-apiserver-test/definition_test.go @@ -17,10 +17,17 @@ limitations under the License. package e2e_apiserver_test import ( + "context" + "fmt" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" apisv1 "github.com/oam-dev/kubevela/pkg/apiserver/rest/apis/v1" + "github.com/oam-dev/kubevela/pkg/apiserver/rest/utils" + "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/utils/common" ) var _ = Describe("Test definitions rest api", func() { @@ -30,6 +37,90 @@ var _ = Describe("Test definitions rest api", func() { res := get("/definitions?type=component") var definitions apisv1.ListDefinitionResponse Expect(decodeResponseBody(res, &definitions)).Should(Succeed()) + Expect(len(definitions.Definitions) > 0).Should(BeTrue()) + + updateDefinitionName := definitions.Definitions[0].Name + upRes := put(fmt.Sprintf("/definitions/%s/status", updateDefinitionName), apisv1.UpdateDefinitionStatusRequest{ + DefinitionType: "component", + HiddenInUI: true, + }) + Expect(upRes.StatusCode).Should(Equal(200)) + + res2 := get("/definitions?type=component&queryAll=true") + var allDefinitions apisv1.ListDefinitionResponse + Expect(decodeResponseBody(res2, &allDefinitions)).Should(Succeed()) + expected := false + for _, d := range allDefinitions.Definitions { + if d.Name == updateDefinitionName && d.Status == "disable" { + expected = true + } + } + Expect(expected).Should(BeTrue()) + }) + + It("Test detail the definition", func() { + defer GinkgoRecover() + componentSchema := new(corev1.ConfigMap) + Expect(common.ReadYamlToObject("./testdata/component-schema-webservice.yaml", componentSchema)).Should(BeNil()) + Expect(k8sClient.Create(context.Background(), componentSchema)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + res := get("/definitions/webservice?type=component") + var detail apisv1.DetailDefinitionResponse + Expect(decodeResponseBody(res, &detail)).Should(Succeed()) + }) + + It("Test update ui schema", func() { + defer GinkgoRecover() + req := apisv1.UpdateUISchemaRequest{ + DefinitionType: "component", + UISchema: utils.UISchema{ + { + JSONKey: "image", + UIType: "ImageInput", + }, + }, + } + res := put("/definitions/webservice/uischema", req) + var schema utils.UISchema + Expect(decodeResponseBody(res, &schema)).Should(Succeed()) + }) + + It("Test error update ui schema", func() { + defer GinkgoRecover() + req := apisv1.UpdateUISchemaRequest{ + DefinitionType: "component", + UISchema: utils.UISchema{ + { + JSONKey: "image", + UIType: "ImageInput", + Conditions: []utils.Condition{ + { + JSONKey: "", + }, + }, + }, + }, + } + res := put("/definitions/webservice/uischema", req) + Expect(res.StatusCode).Should(Equal(400)) + + req2 := apisv1.UpdateUISchemaRequest{ + DefinitionType: "component", + UISchema: utils.UISchema{ + { + JSONKey: "image", + UIType: "ImageInput", + Conditions: []utils.Condition{ + { + JSONKey: "secretName", + Value: "", + Op: "===", + }, + }, + }, + }, + } + res2 := put("/definitions/webservice/uischema", req2) + Expect(res2.StatusCode).Should(Equal(400)) }) }) diff --git a/test/e2e-apiserver-test/testdata/component-schema-webservice.yaml b/test/e2e-apiserver-test/testdata/component-schema-webservice.yaml new file mode 100644 index 000000000..29caafa66 --- /dev/null +++ b/test/e2e-apiserver-test/testdata/component-schema-webservice.yaml @@ -0,0 +1,93 @@ +apiVersion: v1 +data: + openapi-v3-json-schema: '{"properties":{"addRevisionLabel":{"default":false,"description":"If + addRevisionLabel is true, the appRevision label will be added to the underlying + pods","title":"addRevisionLabel","type":"boolean"},"annotations":{"additionalProperties":{"type":"string"},"description":"Specify + the annotations in the workload","title":"annotations","type":"object"},"cmd":{"description":"Commands + to run in the container","items":{"type":"string"},"title":"cmd","type":"array"},"cpu":{"description":"Number + of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)","title":"cpu","type":"string"},"env":{"description":"Define + arguments by using environment variables","items":{"properties":{"name":{"description":"Environment + variable name","title":"name","type":"string"},"value":{"description":"The value + of the environment variable","title":"value","type":"string"},"valueFrom":{"description":"Specifies + a source the value of this var should come from","properties":{"configMapKeyRef":{"description":"Selects + a key of a config map in the pod''s namespace","properties":{"key":{"description":"The + key of the config map to select from. Must be a valid secret key","title":"key","type":"string"},"name":{"description":"The + name of the config map in the pod''s namespace to select from","title":"name","type":"string"}},"required":["name","key"],"title":"configMapKeyRef","type":"object"},"secretKeyRef":{"description":"Selects + a key of a secret in the pod''s namespace","properties":{"key":{"description":"The + key of the secret to select from. Must be a valid secret key","title":"key","type":"string"},"name":{"description":"The + name of the secret in the pod''s namespace to select from","title":"name","type":"string"}},"required":["name","key"],"title":"secretKeyRef","type":"object"}},"title":"valueFrom","type":"object"}},"required":["name"],"type":"object"},"title":"env","type":"array"},"exposeType":{"default":"ClusterIP","description":"Specify + what kind of Service you want. options: \"ClusterIP\", \"NodePort\", \"LoadBalancer\", + \"ExternalName\"","enum":["ClusterIP","NodePort","LoadBalancer","ExternalName"],"title":"exposeType","type":"string"},"image":{"description":"Which + image would you like to use for your service","title":"image","type":"string"},"imagePullPolicy":{"description":"Specify + image pull policy for your service","enum":["Always","Never","IfNotPresent"],"title":"imagePullPolicy","type":"string"},"imagePullSecrets":{"description":"Specify + image pull secrets for your service","items":{"type":"string"},"title":"imagePullSecrets","type":"array"},"labels":{"additionalProperties":{"type":"string"},"description":"Specify + the labels in the workload","title":"labels","type":"object"},"livenessProbe":{"description":"Instructions + for assessing whether the container is alive.","properties":{"exec":{"description":"Instructions + for assessing container health by executing a command. Either this attribute or + the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute + is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.","properties":{"command":{"description":"A + command to be executed inside the container to assess its health. Each space delimited + token of the command is a separate array element. Commands exiting 0 are considered + to be successful probes, whilst all other exit codes are considered failures.","items":{"type":"string"},"title":"command","type":"array"}},"required":["command"],"title":"exec","type":"object"},"failureThreshold":{"default":3,"description":"Number + of consecutive failures required to determine the container is not alive (liveness + probe) or not ready (readiness probe).","title":"failureThreshold","type":"integer"},"hostAliases":{"description":"Specify + the hostAliases to add","items":{"properties":{"hostnames":{"items":{"type":"string"},"title":"hostnames","type":"array"},"ip":{"title":"ip","type":"string"}},"required":["ip","hostnames"],"type":"object"},"title":"hostAliases","type":"array"},"httpGet":{"description":"Instructions + for assessing container health by executing an HTTP GET request. Either this attribute + or the exec attribute or the tcpSocket attribute MUST be specified. This attribute + is mutually exclusive with both the exec attribute and the tcpSocket attribute.","properties":{"httpHeaders":{"items":{"properties":{"name":{"title":"name","type":"string"},"value":{"title":"value","type":"string"}},"required":["name","value"],"type":"object"},"title":"httpHeaders","type":"array"},"path":{"description":"The + endpoint, relative to the port, to which the HTTP GET request should be directed.","title":"path","type":"string"},"port":{"description":"The + TCP socket within the container to which the HTTP GET request should be directed.","title":"port","type":"integer"}},"required":["path","port"],"title":"httpGet","type":"object"},"initialDelaySeconds":{"default":0,"description":"Number + of seconds after the container is started before the first probe is initiated.","title":"initialDelaySeconds","type":"integer"},"periodSeconds":{"default":10,"description":"How + often, in seconds, to execute the probe.","title":"periodSeconds","type":"integer"},"successThreshold":{"default":1,"description":"Minimum + consecutive successes for the probe to be considered successful after having failed.","title":"successThreshold","type":"integer"},"tcpSocket":{"description":"Instructions + for assessing container health by probing a TCP socket. Either this attribute + or the exec attribute or the httpGet attribute MUST be specified. This attribute + is mutually exclusive with both the exec attribute and the httpGet attribute.","properties":{"port":{"description":"The + TCP socket within the container that should be probed to assess container health.","title":"port","type":"integer"}},"required":["port"],"title":"tcpSocket","type":"object"},"timeoutSeconds":{"default":1,"description":"Number + of seconds after which the probe times out.","title":"timeoutSeconds","type":"integer"}},"required":["hostAliases","initialDelaySeconds","periodSeconds","timeoutSeconds","successThreshold","failureThreshold"],"title":"livenessProbe","type":"object"},"memory":{"description":"Specifies + the attributes of the memory resource required for the container.","title":"memory","type":"string"},"port":{"description":"Deprecated + field, please use ports instead","title":"port","type":"integer"},"ports":{"description":"Which + ports do you want customer traffic sent to, defaults to 80","items":{"properties":{"expose":{"default":false,"description":"Specify + if the port should be exposed","title":"expose","type":"boolean"},"name":{"description":"Name + of the port","title":"name","type":"string"},"port":{"description":"Number of + port to expose on the pod''s IP address","title":"port","type":"integer"},"protocol":{"default":"TCP","description":"Protocol + for port. Must be UDP, TCP, or SCTP","enum":["TCP","UDP","SCTP"],"title":"protocol","type":"string"}},"required":["port","protocol","expose"],"type":"object"},"title":"ports","type":"array"},"readinessProbe":{"description":"Instructions + for assessing whether the container is in a suitable state to serve traffic.","properties":{"exec":{"description":"Instructions + for assessing container health by executing a command. Either this attribute or + the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute + is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.","properties":{"command":{"description":"A + command to be executed inside the container to assess its health. Each space delimited + token of the command is a separate array element. Commands exiting 0 are considered + to be successful probes, whilst all other exit codes are considered failures.","items":{"type":"string"},"title":"command","type":"array"}},"required":["command"],"title":"exec","type":"object"},"failureThreshold":{"default":3,"description":"Number + of consecutive failures required to determine the container is not alive (liveness + probe) or not ready (readiness probe).","title":"failureThreshold","type":"integer"},"hostAliases":{"description":"Specify + the hostAliases to add","items":{"properties":{"hostnames":{"items":{"type":"string"},"title":"hostnames","type":"array"},"ip":{"title":"ip","type":"string"}},"required":["ip","hostnames"],"type":"object"},"title":"hostAliases","type":"array"},"httpGet":{"description":"Instructions + for assessing container health by executing an HTTP GET request. Either this attribute + or the exec attribute or the tcpSocket attribute MUST be specified. This attribute + is mutually exclusive with both the exec attribute and the tcpSocket attribute.","properties":{"httpHeaders":{"items":{"properties":{"name":{"title":"name","type":"string"},"value":{"title":"value","type":"string"}},"required":["name","value"],"type":"object"},"title":"httpHeaders","type":"array"},"path":{"description":"The + endpoint, relative to the port, to which the HTTP GET request should be directed.","title":"path","type":"string"},"port":{"description":"The + TCP socket within the container to which the HTTP GET request should be directed.","title":"port","type":"integer"}},"required":["path","port"],"title":"httpGet","type":"object"},"initialDelaySeconds":{"default":0,"description":"Number + of seconds after the container is started before the first probe is initiated.","title":"initialDelaySeconds","type":"integer"},"periodSeconds":{"default":10,"description":"How + often, in seconds, to execute the probe.","title":"periodSeconds","type":"integer"},"successThreshold":{"default":1,"description":"Minimum + consecutive successes for the probe to be considered successful after having failed.","title":"successThreshold","type":"integer"},"tcpSocket":{"description":"Instructions + for assessing container health by probing a TCP socket. Either this attribute + or the exec attribute or the httpGet attribute MUST be specified. This attribute + is mutually exclusive with both the exec attribute and the httpGet attribute.","properties":{"port":{"description":"The + TCP socket within the container that should be probed to assess container health.","title":"port","type":"integer"}},"required":["port"],"title":"tcpSocket","type":"object"},"timeoutSeconds":{"default":1,"description":"Number + of seconds after which the probe times out.","title":"timeoutSeconds","type":"integer"}},"required":["hostAliases","initialDelaySeconds","periodSeconds","timeoutSeconds","successThreshold","failureThreshold"],"title":"readinessProbe","type":"object"},"volumeMounts":{"properties":{"configMap":{"description":"Mount + ConfigMap type volume","items":{"properties":{"cmName":{"title":"cmName","type":"string"},"defaultMode":{"default":420,"title":"defaultMode","type":"integer"},"items":{"items":{"properties":{"key":{"title":"key","type":"string"},"mode":{"default":511,"title":"mode","type":"integer"},"path":{"title":"path","type":"string"}},"required":["path","key","mode"],"type":"object"},"title":"items","type":"array"},"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"}},"required":["name","mountPath","defaultMode","cmName"],"type":"object"},"title":"configMap","type":"array"},"emptyDir":{"description":"Mount + EmptyDir type volume","items":{"properties":{"medium":{"default":"","enum":["","Memory"],"title":"medium","type":"string"},"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"}},"required":["name","mountPath","medium"],"type":"object"},"title":"emptyDir","type":"array"},"hostPath":{"description":"Mount + HostPath type volume","items":{"properties":{"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"},"path":{"title":"path","type":"string"}},"required":["path","name","mountPath"],"type":"object"},"title":"hostPath","type":"array"},"pvc":{"description":"Mount + PVC type volume","items":{"properties":{"claimName":{"description":"The name of + the PVC","title":"claimName","type":"string"},"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"}},"required":["name","mountPath","claimName"],"type":"object"},"title":"pvc","type":"array"},"secret":{"description":"Mount + Secret type volume","items":{"properties":{"defaultMode":{"default":420,"title":"defaultMode","type":"integer"},"items":{"items":{"properties":{"key":{"title":"key","type":"string"},"mode":{"default":511,"title":"mode","type":"integer"},"path":{"title":"path","type":"string"}},"required":["path","key","mode"],"type":"object"},"title":"items","type":"array"},"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"},"secretName":{"title":"secretName","type":"string"}},"required":["name","mountPath","defaultMode","secretName"],"type":"object"},"title":"secret","type":"array"}},"title":"volumeMounts","type":"object"},"volumes":{"description":"Deprecated + field, use volumeMounts instead.","items":{"properties":{"mountPath":{"title":"mountPath","type":"string"},"name":{"title":"name","type":"string"},"type":{"description":"Specify + volume type, options: \"pvc\",\"configMap\",\"secret\",\"emptyDir\"","enum":["pvc","configMap","secret","emptyDir"],"title":"type","type":"string"}},"required":["name","mountPath","type"],"type":"object"},"title":"volumes","type":"array"}},"required":["addRevisionLabel","image","exposeType"],"type":"object"}' +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/managed-by: Helm + definition.oam.dev: schema + definition.oam.dev/name: webservice + name: component-schema-webservice + namespace: vela-system \ No newline at end of file diff --git a/vela-templates/definitions/uischema/component-alibaba-rds.yaml b/vela-templates/definitions/uischema/component-alibaba-rds.yaml deleted file mode 100644 index 16553419a..000000000 --- a/vela-templates/definitions/uischema/component-alibaba-rds.yaml +++ /dev/null @@ -1,23 +0,0 @@ -- jsonKey: writeConnectionSecretToRef - disable: true -- jsonKey: providerRef - disable: true -- jsonKey: region - disable: true -- jsonKey: instance_name - label: InstanceName - sort: 1 -- jsonKey: database_name - label: DatabaseName - sort: 2 -- jsonKey: account_name - label: AccountName - sort: 3 -- jsonKey: password - sort: 4 -- jsonKey: allocate_public_connection - label: AllocatePublicConnection - sort: 5 -- jsonKey: deleteResource - label: DeleteResource - sort: 10 diff --git a/vela-templates/definitions/uischema/component-k8s-objects.yaml b/vela-templates/definitions/uischema/component-k8s-objects.yaml deleted file mode 100644 index a35528eaf..000000000 --- a/vela-templates/definitions/uischema/component-k8s-objects.yaml +++ /dev/null @@ -1,2 +0,0 @@ -- jsonKey: objects - uiType: K8sObjectsCode \ No newline at end of file diff --git a/vela-templates/definitions/uischema/component-task.yaml b/vela-templates/definitions/uischema/component-task.yaml deleted file mode 100644 index 961a90e68..000000000 --- a/vela-templates/definitions/uischema/component-task.yaml +++ /dev/null @@ -1,168 +0,0 @@ -- uiType: ImageInput - jsonKey: image - label: Image - sort: 1 -- jsonKey: restart - sort: 2 - uiType: Select - validate: - options: - - label: Never - value: Never - - label: OnFailure - value: OnFailure -- jsonKey: count - sort: 3 - uiType: Number -- jsonKey: memory - uiType: MemoryNumber - sort: 4 - label: Memory Request&Limit -- uiType: CPUNumber - jsonKey: cpu - sort: 5 - label: CPU Request&Limit -- description: Specify image pull policy for your service - jsonKey: imagePullPolicy - label: Image Pull Policy - uiType: Select - sort: 7 - validate: - options: - - label: IfNotPresent - value: IfNotPresent - - label: Always - value: Always - - label: Never - value: Never -- jsonKey: cmd - label: CMD - sort: 9 -- jsonKey: env - sort: 10 - label: ENV - subParameterGroupOption: - - label: Add By Value - keys: - - name - - value - - label: Add By Secret - keys: - - name - - valueFrom - subParameters: - - jsonKey: valueFrom - label: Secret Selector - uiType: InnerGroup - subParameters: - - jsonKey: configMapKeyRef - disable: true - - jsonKey: secretKeyRef - uiType: Ignore - subParameters: - - jsonKey: name - label: Secret Name - uiType: SecretSelect - sort: 1 - - jsonKey: key - label: Secret Key - uiType: SecretKeySelect - sort: 3 - uiType: Structs -- jsonKey: ports - label: Service Ports - sort: 11 - subParameters: - - jsonKey: port - sort: 1 - - jsonKey: protocol - sort: 2 - - jsonKey: expose - sort: 3 -- jsonKey: volumeMounts - label: Persistent Storage - description: "Set the path and type that the service needs to persist." - uiType: Group - subParameters: - - jsonKey: secret - disable: true - - jsonKey: pvc - sort: 1 - - jsonKey: hostPath - sort: 3 - - jsonKey: emptyDir - sort: 5 - sort: 12 - - -- jsonKey: readinessProbe - uiType: Group - label: ReadinessProbe - subParameters: - - jsonKey: hostAliases - disable: true - - jsonKey: timeoutSeconds - sort: 1 - - jsonKey: failureThreshold - sort: 4 - - jsonKey: initialDelaySeconds - sort: 7 - - jsonKey: periodSeconds - sort: 9 - - jsonKey: successThreshold - sort: 11 - - jsonKey: exec - sort: 14 - - jsonKey: httpGet - sort: 19 - subParameters: - - jsonKey: port - sort: 1 - - jsonKey: path - sort: 3 - - jsonKey: httpHeaders - sort: 5 - - jsonKey: tcpSocket - sort: 19 - - sort: 13 - -- jsonKey: livenessProbe - uiType: Group - label: LivenessProbe - subParameters: - - jsonKey: hostAliases - disable: true - - jsonKey: timeoutSeconds - sort: 1 - - jsonKey: failureThreshold - sort: 4 - - jsonKey: initialDelaySeconds - sort: 7 - - jsonKey: periodSeconds - sort: 9 - - jsonKey: successThreshold - sort: 11 - - jsonKey: exec - sort: 14 - - jsonKey: httpGet - sort: 19 - subParameters: - - jsonKey: port - sort: 1 - - jsonKey: path - sort: 3 - - jsonKey: httpHeaders - sort: 5 - - jsonKey: tcpSocket - sort: 19 - sort: 15 - -- jsonKey: annotations - sort: 19 - -- jsonKey: lables - sort: 21 - -- jsonKey: volumes - disable: true \ No newline at end of file diff --git a/vela-templates/definitions/uischema/component-webservice.yaml b/vela-templates/definitions/uischema/component-webservice.yaml deleted file mode 100644 index 5a9dc4c26..000000000 --- a/vela-templates/definitions/uischema/component-webservice.yaml +++ /dev/null @@ -1,142 +0,0 @@ -- uiType: ImageInput - jsonKey: image - label: Image - sort: 1 -- jsonKey: memory - uiType: MemoryNumber - sort: 3 - label: Memory Request&Limit -- uiType: CPUNumber - jsonKey: cpu - sort: 5 - label: CPU Request&Limit -- description: Specify image pull policy for your service - jsonKey: imagePullPolicy - label: Image Pull Policy - uiType: Select - sort: 7 - validate: - options: - - label: IfNotPresent - value: IfNotPresent - - label: Always - value: Always - - label: Never - value: Never -- jsonKey: exposeType - sort: 8 -- jsonKey: cmd - label: CMD - sort: 9 -- jsonKey: env - sort: 10 - label: ENV - subParameterGroupOption: - - label: Add By Value - keys: - - name - - value - - label: Add By Secret - keys: - - name - - valueFrom - subParameters: - - jsonKey: valueFrom - label: Secret Selector - uiType: InnerGroup - subParameters: - - jsonKey: configMapKeyRef - disable: true - - jsonKey: secretKeyRef - uiType: Ignore - subParameters: - - jsonKey: name - label: Secret Name - uiType: SecretSelect - sort: 1 - - jsonKey: key - label: Secret Key - uiType: SecretKeySelect - sort: 3 - uiType: Structs -- jsonKey: ports - label: Service Ports - sort: 11 - subParameters: - - jsonKey: port - sort: 1 - - jsonKey: protocol - sort: 2 - - jsonKey: expose - sort: 3 -- jsonKey: volumeMounts - label: Persistent Storage - description: "Set the path and type that the service needs to persist." - uiType: Group - subParameters: - - jsonKey: configMap - disable: true - - jsonKey: secret - disable: true - - jsonKey: pvc - sort: 1 - - jsonKey: hostPath - sort: 3 - - jsonKey: emptyDir - sort: 5 - sort: 12 - -- jsonKey: readinessProbe - uiType: Group - label: ReadinessProbe - subParameters: - - jsonKey: hostAliases - disable: true - - jsonKey: timeoutSeconds - sort: 1 - - jsonKey: failureThreshold - sort: 4 - - jsonKey: initialDelaySeconds - sort: 7 - - jsonKey: periodSeconds - sort: 9 - - jsonKey: successThreshold - sort: 11 - - jsonKey: exec - sort: 14 - - jsonKey: httpGet - sort: 19 - subParameters: - - jsonKey: port - sort: 1 - - jsonKey: path - sort: 3 - - jsonKey: httpHeaders - sort: 5 - - jsonKey: tcpSocket - sort: 19 - - sort: 13 - -- jsonKey: livenessProbe - uiType: Group - label: LivenessProbe - subParameters: - - jsonKey: hostAliases - disable: true - sort: 15 - -- jsonKey: annotations - sort: 19 - -- jsonKey: lables - sort: 21 - -- jsonKey: addRevisionLabel - disable: true - -- jsonKey: port - disable: true - -- jsonKey: volumes - disable: true \ No newline at end of file