From f4cbe1b98b3e5410b1419d30e8ac63a6d50375fd Mon Sep 17 00:00:00 2001 From: wangyuan249 <35907099+wangyuan249@users.noreply.github.com> Date: Thu, 10 Jun 2021 10:29:35 +0800 Subject: [PATCH] Add ignore feature for cue parameter (#1756) * add ignore feature for cue parameter * add test * fix diff * fix test * fix test 2 * fix interact init --- apis/types/capability.go | 1 + .../templates/defwithtemplate/webservice.yaml | 3 +- e2e/application/application_test.go | 2 +- e2e/plugin/plugin_suit_test.go | 6 ++ e2e/plugin/plugin_test.go | 92 +++++++++++++++++++ pkg/cue/convert.go | 14 ++- pkg/cue/convert_test.go | 13 +++ pkg/cue/testdata/workloads/webservice.cue | 56 +++++++++++ references/plugins/references.go | 14 ++- vela-templates/internal/cue/webservice.cue | 3 +- 10 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 pkg/cue/testdata/workloads/webservice.cue diff --git a/apis/types/capability.go b/apis/types/capability.go index e0fd1c18e..550930731 100644 --- a/apis/types/capability.go +++ b/apis/types/capability.go @@ -134,6 +134,7 @@ type Parameter struct { Required bool `json:"required,omitempty"` Default interface{} `json:"default,omitempty"` Usage string `json:"usage,omitempty"` + Ignore bool `json:"ignore,omitempty"` Type cue.Kind `json:"type,omitempty"` Alias string `json:"alias,omitempty"` JSONType string `json:"jsonType,omitempty"` diff --git a/charts/vela-core/templates/defwithtemplate/webservice.yaml b/charts/vela-core/templates/defwithtemplate/webservice.yaml index dd1dd73ee..a1d38e3e1 100644 --- a/charts/vela-core/templates/defwithtemplate/webservice.yaml +++ b/charts/vela-core/templates/defwithtemplate/webservice.yaml @@ -136,7 +136,8 @@ spec: // +short=p port: *80 | int - // If addRevisionLabel is true, the appRevision label will be added to the underlying pods + // +ignore + // +usage=If addRevisionLabel is true, the appRevision label will be added to the underlying pods addRevisionLabel: *false | bool // +usage=Commands to run in the container diff --git a/e2e/application/application_test.go b/e2e/application/application_test.go index 279674a2f..be2faa933 100644 --- a/e2e/application/application_test.go +++ b/e2e/application/application_test.go @@ -157,7 +157,7 @@ var ApplicationInitIntercativeCliContext = func(context string, appName string, a: "mysvc", }, { - q: "what would you configure for parameter 'addRevisionLabel' (optional, default is false):", + q: "If addRevisionLabel is true, the appRevision label will be added to the underlying pods (optional, default is false):", a: "N", }, { diff --git a/e2e/plugin/plugin_suit_test.go b/e2e/plugin/plugin_suit_test.go index 74ebe9dbb..cb0543286 100644 --- a/e2e/plugin/plugin_suit_test.go +++ b/e2e/plugin/plugin_suit_test.go @@ -46,6 +46,7 @@ var testShowTdDef v1beta1.TraitDefinition var testCdDef v1beta1.ComponentDefinition var testCdDefWithHelm v1beta1.ComponentDefinition var testCdDefWithKube v1beta1.ComponentDefinition +var testCdWithDeepCue v1beta1.ComponentDefinition var testTdDef v1beta1.TraitDefinition var testTdDefWithKube v1beta1.TraitDefinition @@ -88,6 +89,10 @@ var _ = BeforeSuite(func(done Done) { err = k8sClient.Create(ctx, &testCdDefWithKube) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + Expect(yaml.Unmarshal([]byte(componentWithDeepCue), &testCdWithDeepCue)).Should(BeNil()) + err = k8sClient.Create(ctx, &testCdWithDeepCue) + Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + Expect(yaml.Unmarshal([]byte(traitDef), &testTdDef)).Should(BeNil()) err = k8sClient.Create(ctx, &testTdDef) Expect(err).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) @@ -122,6 +127,7 @@ var _ = AfterSuite(func() { Expect(k8sClient.Delete(ctx, &testCdDef)).Should(BeNil()) Expect(k8sClient.Delete(ctx, &testCdDefWithHelm)).Should(BeNil()) Expect(k8sClient.Delete(ctx, &testCdDefWithKube)).Should(BeNil()) + Expect(k8sClient.Delete(ctx, &testCdWithDeepCue)).Should(BeNil()) Expect(k8sClient.Delete(ctx, &testTdDef)).Should(BeNil()) Expect(k8sClient.Delete(ctx, &testTdDefWithKube)).Should(BeNil()) Expect(k8sClient.Delete(ctx, &testShowCdDef)).Should(BeNil()) diff --git a/e2e/plugin/plugin_test.go b/e2e/plugin/plugin_test.go index ef680544a..abe3c6d49 100644 --- a/e2e/plugin/plugin_test.go +++ b/e2e/plugin/plugin_test.go @@ -146,6 +146,19 @@ var _ = Describe("Test Kubectl Plugin", func() { Expect(err).NotTo(HaveOccurred()) Expect(output).Should(ContainSubstring("map[string]string")) }) + It("Test show webservice def with cue ignore annotation ", func() { + tdName := "webservice" + output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName)) + Expect(err).NotTo(HaveOccurred()) + Expect(output).ShouldNot(ContainSubstring("addRevisionLabel")) + }) + It("Test show webservice def with cue ignore annotation ", func() { + tdName := "mywebservice" + output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", tdName)) + Expect(err).NotTo(HaveOccurred()) + Expect(output).ShouldNot(ContainSubstring("addRevisionLabel")) + Expect(output).ShouldNot(ContainSubstring("mySecretKey")) + }) }) Context("Test kubectl vela comp discover", func() { @@ -603,6 +616,85 @@ spec: description: "target port num for service provider." ` +var componentWithDeepCue = ` +# Test for deeper parameter in cue Template +apiVersion: core.oam.dev/v1beta1 +kind: ComponentDefinition +metadata: + name: mywebservice + namespace: default + annotations: + definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers." +spec: + workload: + definition: + apiVersion: apps/v1 + kind: Deployment + schematic: + cue: + template: | + output: { + apiVersion: "apps/v1" + kind: "Deployment" + spec: { + selector: matchLabels: { + "app.oam.dev/component": context.name + if parameter.addRevisionLabel { + "app.oam.dev/appRevision": context.appRevision + } + } + + template: { + metadata: labels: { + "app.oam.dev/component": context.name + if parameter.addRevisionLabel { + "app.oam.dev/appRevision": context.appRevision + } + } + + spec: { + containers: [{ + name: context.name + image: parameter.image + + if parameter["env"] != _|_ { + env: parameter.env + } + }] + } + } + } + } + parameter: { + // +usage=Which image would you like to use for your service + // +short=i + image: string + + // +ignore + // +usage=If addRevisionLabel is true, the appRevision label will be added to the underlying pods + addRevisionLabel: *false | bool + + // +usage=Define arguments by using environment variables + env?: [...{ + // +usage=Environment variable name + name: string + // +usage=The value of the environment variable + value?: string + // +usage=Specifies a source the value of this var should come from + valueFrom?: { + // +usage=Selects a key of a secret in the pod's namespace + secretKeyRef: { + // +usage=The name of the secret in the pod's namespace to select from + name: string + // +ignore + // +usage=The key of the secret to select from. Must be a valid secret key + mySecretKey: string + } + } + }] + } +` + var dryRunResult = `--- # Application(test-vela-app) -- Comopnent(express-server) --- diff --git a/pkg/cue/convert.go b/pkg/cue/convert.go index 4236c0876..5e8d5d821 100644 --- a/pkg/cue/convert.go +++ b/pkg/cue/convert.go @@ -79,7 +79,7 @@ func GetParameters(templateStr string) ([]types.Parameter, error) { if param.Default == nil { param.Default = getDefaultByKind(param.Type) } - param.Short, param.Usage, param.Alias = RetrieveComments(val) + param.Short, param.Usage, param.Alias, param.Ignore = RetrieveComments(val) params = append(params, param) } @@ -139,11 +139,14 @@ const ( ShortPrefix = "+short=" // AliasPrefix is an alias of the name of a parameter element, in order to making it more friendly to Cli users AliasPrefix = "+alias=" + // IgnorePrefix defines parameter in system level which we don't want our end user to see for KubeVela CLI + IgnorePrefix = "+ignore" ) -// RetrieveComments will retrieve Usage, Short and Alias from CUE Value -func RetrieveComments(value cue.Value) (string, string, string) { +// RetrieveComments will retrieve Usage, Short, Alias and Ignore from CUE Value +func RetrieveComments(value cue.Value) (string, string, string, bool) { var short, usage, alias string + var ignore bool docs := value.Doc() for _, doc := range docs { lines := strings.Split(doc.Text(), "\n") @@ -154,6 +157,9 @@ func RetrieveComments(value cue.Value) (string, string, string) { if strings.HasPrefix(line, ShortPrefix) { short = strings.TrimPrefix(line, ShortPrefix) } + if strings.HasPrefix(line, IgnorePrefix) { + ignore = true + } if strings.HasPrefix(line, UsagePrefix) { usage = strings.TrimPrefix(line, UsagePrefix) } @@ -162,5 +168,5 @@ func RetrieveComments(value cue.Value) (string, string, string) { } } } - return short, usage, alias + return short, usage, alias, ignore } diff --git a/pkg/cue/convert_test.go b/pkg/cue/convert_test.go index 9a10b5d2b..4634a00f1 100644 --- a/pkg/cue/convert_test.go +++ b/pkg/cue/convert_test.go @@ -65,4 +65,17 @@ func TestGetParameter(t *testing.T) { assert.NoError(t, err) var exp []types.Parameter assert.Equal(t, exp, params) + + data, _ = ioutil.ReadFile("testdata/workloads/webservice.cue") // test cue parameter with "// +ignore" annotation + params, err = GetParameters(string(data)) // Only test for func RetrieveComments + assert.NoError(t, err) + var flag bool + for _, para := range params { + if para.Name == "addRevisionLabel" { + flag = true + assert.Equal(t, para.Usage, "If addRevisionLabel is true, the appRevision label will be added to the underlying pods") + assert.Equal(t, para.Ignore, true) + } + } + assert.Equal(t, flag, true) } diff --git a/pkg/cue/testdata/workloads/webservice.cue b/pkg/cue/testdata/workloads/webservice.cue new file mode 100644 index 000000000..b0d9b0af4 --- /dev/null +++ b/pkg/cue/testdata/workloads/webservice.cue @@ -0,0 +1,56 @@ +output: { + apiVersion: "apps/v1" + kind: "Deployment" + spec: { + selector: matchLabels: { + "app.oam.dev/component": context.name + if parameter.addRevisionLabel { + "app.oam.dev/appRevision": context.appRevision + } + } + template: { + metadata: labels: { + "app.oam.dev/component": context.name + if parameter.addRevisionLabel { + "app.oam.dev/appRevision": context.appRevision + } + } + spec: { + containers: [{ + name: context.name + image: parameter.image + if parameter["env"] != _|_ { + env: parameter.env + } + }] + } + } + } +} +parameter: { + // +usage=Which image would you like to use for your service + // +short=i + image: string + // +usage=Define arguments by using environment variables + env?: [...{ + // +usage=Environment variable name + name: string + // +usage=The value of the environment variable + value?: string + // +usage=Specifies a source the value of this var should come from + valueFrom?: { + // +usage=Selects a key of a secret in the pod's namespace + secretKeyRef: { + // +usage=The name of the secret in the pod's namespace to select from + name: string + // +ignore + // +usage=The key of the secret to select from. Must be a valid secret key + secretKey: string + } + } + }] + // +ignore + // +usage=If addRevisionLabel is true, the appRevision label will be added to the underlying pods + addRevisionLabel: *false | bool +} + diff --git a/references/plugins/references.go b/references/plugins/references.go index 9cd9e4f7d..2442af614 100644 --- a/references/plugins/references.go +++ b/references/plugins/references.go @@ -469,8 +469,10 @@ func (ref *MarkdownReference) prepareParameter(tableName string, parameterList [ switch category { case types.CUECategory: for _, p := range parameterList { - printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default) - refContent += fmt.Sprintf(" %s | %s | %s | %t | %s \n", p.Name, p.Usage, p.PrintableType, p.Required, printableDefaultValue) + if !p.Ignore { + printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default) + refContent += fmt.Sprintf(" %s | %s | %s | %t | %s \n", p.Name, p.Usage, p.PrintableType, p.Required, printableDefaultValue) + } } case types.HelmCategory: for _, p := range parameterList { @@ -500,8 +502,10 @@ func (ref *ParseReference) prepareParameter(tableName string, parameterList []Re switch category { case types.CUECategory: for _, p := range parameterList { - printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default) - table.Append([]string{p.Name, p.Usage, p.PrintableType, strconv.FormatBool(p.Required), printableDefaultValue}) + if !p.Ignore { + printableDefaultValue := ref.getCUEPrintableDefaultValue(p.Default) + table.Append([]string{p.Name, p.Usage, p.PrintableType, strconv.FormatBool(p.Required), printableDefaultValue}) + } } case types.HelmCategory: for _, p := range parameterList { @@ -558,7 +562,7 @@ func (ref *ParseReference) parseParameters(paraValue cue.Value, paramKey string, if def, ok := val.Default(); ok && def.IsConcrete() { param.Default = velacue.GetDefault(def) } - param.Short, param.Usage, param.Alias = velacue.RetrieveComments(val) + param.Short, param.Usage, param.Alias, param.Ignore = velacue.RetrieveComments(val) param.Type = val.IncompleteKind() switch val.IncompleteKind() { case cue.StructKind: diff --git a/vela-templates/internal/cue/webservice.cue b/vela-templates/internal/cue/webservice.cue index 5c09dc086..3e3231a09 100644 --- a/vela-templates/internal/cue/webservice.cue +++ b/vela-templates/internal/cue/webservice.cue @@ -120,7 +120,8 @@ parameter: { // +short=p port: *80 | int - // If addRevisionLabel is true, the appRevision label will be added to the underlying pods + // +ignore + // +usage=If addRevisionLabel is true, the appRevision label will be added to the underlying pods addRevisionLabel: *false | bool // +usage=Commands to run in the container