From 28e094c207a0ad54f6f111baa428f1bb75b31773 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 25 Feb 2025 20:20:06 +0000 Subject: [PATCH] Fixed accessing required path parameters in CLI generation when --json flag (#2373) ## Changes CLI generation template was using RequiredPathField from incorrect request entity (body field from request and not request itself). Thus for some of the commands required path parameters were not required when --json was specified. ## Tests Regenerated commands work correctly --- .codegen/service.go.tmpl | 8 +-- acceptance/cmd/workspace/apps/input.json | 14 ++++++ .../cmd/workspace/apps/out.requests.txt | 19 +++++++ acceptance/cmd/workspace/apps/output.txt | 49 +++++++++++++++++++ acceptance/cmd/workspace/apps/script | 5 ++ acceptance/cmd/workspace/apps/test.toml | 31 ++++++++++++ cmd/account/budget-policy/budget-policy.go | 9 ---- cmd/workspace/apps/apps.go | 7 --- cmd/workspace/lakeview/lakeview.go | 21 -------- 9 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 acceptance/cmd/workspace/apps/input.json create mode 100644 acceptance/cmd/workspace/apps/out.requests.txt create mode 100644 acceptance/cmd/workspace/apps/output.txt create mode 100644 acceptance/cmd/workspace/apps/script create mode 100644 acceptance/cmd/workspace/apps/test.toml diff --git a/.codegen/service.go.tmpl b/.codegen/service.go.tmpl index 2f4987b13..33833dfa1 100644 --- a/.codegen/service.go.tmpl +++ b/.codegen/service.go.tmpl @@ -179,7 +179,7 @@ func new{{.PascalName}}() *cobra.Command { {{- $wait := and .Wait (and (not .IsCrudRead) (not (eq .SnakeName "get_run"))) -}} {{- $hasRequiredArgs := and (not $hasIdPrompt) $hasPosArgs -}} {{- $hasSingleRequiredRequestBodyFieldWithPrompt := and (and $hasIdPrompt $request) (eq 1 (len $request.RequiredRequestBodyFields)) -}} - {{- $onlyPathArgsRequiredAsPositionalArguments := and $request (eq (len .RequiredPositionalArguments) (len $request.RequiredPathFields)) -}} + {{- $onlyPathArgsRequiredAsPositionalArguments := and .Request (eq (len .RequiredPositionalArguments) (len .Request.RequiredPathFields)) -}} {{- $hasDifferentArgsWithJsonFlag := and (not $onlyPathArgsRequiredAsPositionalArguments) (and $canUseJson (or $request.HasRequiredRequestBodyFields )) -}} {{- $hasCustomArgHandler := or $hasRequiredArgs $hasDifferentArgsWithJsonFlag -}} @@ -218,12 +218,12 @@ func new{{.PascalName}}() *cobra.Command { cmd.Args = func(cmd *cobra.Command, args []string) error { {{- if $hasDifferentArgsWithJsonFlag }} if cmd.Flags().Changed("json") { - err := root.ExactArgs({{len $request.RequiredPathFields}})(cmd, args) + err := root.ExactArgs({{len .Request.RequiredPathFields}})(cmd, args) if err != nil { - {{- if eq 0 (len $request.RequiredPathFields) }} + {{- if eq 0 (len .Request.RequiredPathFields) }} return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide{{- range $index, $field := $request.RequiredFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input") {{- else }} - return fmt.Errorf("when --json flag is specified, provide only{{- range $index, $field := $request.RequiredPathFields}}{{if $index}},{{end}} {{$field.ConstantName}}{{end}} as positional arguments. Provide{{- range $index, $field := $request.RequiredRequestBodyFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input") + return fmt.Errorf("when --json flag is specified, provide only{{- range $index, $field := .Request.RequiredPathFields}}{{if $index}},{{end}} {{$field.ConstantName}}{{end}} as positional arguments. Provide{{- range $index, $field := $request.RequiredRequestBodyFields}}{{if $index}},{{end}} '{{$field.Name}}'{{end}} in your JSON input") {{- end }} } return nil diff --git a/acceptance/cmd/workspace/apps/input.json b/acceptance/cmd/workspace/apps/input.json new file mode 100644 index 000000000..76f3e589c --- /dev/null +++ b/acceptance/cmd/workspace/apps/input.json @@ -0,0 +1,14 @@ +{ + "description": "My app description.", + "resources": [ + { + "name": "api-key", + "description": "API key for external service.", + "secret": { + "scope": "my-scope", + "key": "my-key", + "permission": "READ" + } + } + ] +} diff --git a/acceptance/cmd/workspace/apps/out.requests.txt b/acceptance/cmd/workspace/apps/out.requests.txt new file mode 100644 index 000000000..04891dc74 --- /dev/null +++ b/acceptance/cmd/workspace/apps/out.requests.txt @@ -0,0 +1,19 @@ +{ + "method": "PATCH", + "path": "/api/2.0/apps/test-name", + "body": { + "description": "My app description.", + "name": "", + "resources": [ + { + "description": "API key for external service.", + "name": "api-key", + "secret": { + "key": "my-key", + "permission": "READ", + "scope": "my-scope" + } + } + ] + } +} diff --git a/acceptance/cmd/workspace/apps/output.txt b/acceptance/cmd/workspace/apps/output.txt new file mode 100644 index 000000000..4d9f80f44 --- /dev/null +++ b/acceptance/cmd/workspace/apps/output.txt @@ -0,0 +1,49 @@ + +=== Apps update with correct input +>>> [CLI] apps update test-name --json @input.json +{ + "app_status": { + "message":"Application is running.", + "state":"DEPLOYING" + }, + "compute_status": { + "message":"App compute is active.", + "state":"ERROR" + }, + "description":"My app description.", + "id":"12345", + "name":"test-name", + "resources": [ + { + "description":"API key for external service.", + "name":"api-key", + "secret": { + "key":"my-key", + "permission":"READ", + "scope":"my-scope" + } + } + ], + "url":"test-name-123.cloud.databricksapps.com" +} + +=== Apps update with missing parameter +>>> [CLI] apps update --json @input.json +Error: accepts 1 arg(s), received 0 + +Usage: + databricks apps update NAME [flags] + +Flags: + --description string The description of the app. + -h, --help help for update + --json JSON either inline JSON string or @path/to/file.json with request body (default JSON (0 bytes)) + +Global Flags: + --debug enable debug logging + -o, --output type output type: text or json (default text) + -p, --profile string ~/.databrickscfg profile + -t, --target string bundle target to use (if applicable) + + +Exit code: 1 diff --git a/acceptance/cmd/workspace/apps/script b/acceptance/cmd/workspace/apps/script new file mode 100644 index 000000000..221ffc4c0 --- /dev/null +++ b/acceptance/cmd/workspace/apps/script @@ -0,0 +1,5 @@ +title "Apps update with correct input" +trace $CLI apps update test-name --json @input.json + +title "Apps update with missing parameter" +trace $CLI apps update --json @input.json diff --git a/acceptance/cmd/workspace/apps/test.toml b/acceptance/cmd/workspace/apps/test.toml new file mode 100644 index 000000000..4f919b315 --- /dev/null +++ b/acceptance/cmd/workspace/apps/test.toml @@ -0,0 +1,31 @@ +LocalOnly = true +RecordRequests = true + +[[Server]] +Pattern = "PATCH /api/2.0/apps/test-name" +Response.Body = ''' +{ + "name": "test-name", + "description": "My app description.", + "compute_status": { + "state": "ERROR", + "message": "App compute is active." + }, + "app_status": { + "state": "DEPLOYING", + "message": "Application is running." + }, + "url": "test-name-123.cloud.databricksapps.com", + "resources": [ + { + "name": "api-key", + "description": "API key for external service.", + "secret": { + "scope": "my-scope", + "key": "my-key", + "permission": "READ" + } + } + ], + "id": "12345" +}''' diff --git a/cmd/account/budget-policy/budget-policy.go b/cmd/account/budget-policy/budget-policy.go index 3a6f8cfa4..fb9f8e5a6 100755 --- a/cmd/account/budget-policy/budget-policy.go +++ b/cmd/account/budget-policy/budget-policy.go @@ -3,8 +3,6 @@ package budget_policy import ( - "fmt" - "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/flags" @@ -323,13 +321,6 @@ func newUpdate() *cobra.Command { cmd.Annotations = make(map[string]string) cmd.Args = func(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("json") { - err := root.ExactArgs(0)(cmd, args) - if err != nil { - return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide 'policy_id' in your JSON input") - } - return nil - } check := root.ExactArgs(1) return check(cmd, args) } diff --git a/cmd/workspace/apps/apps.go b/cmd/workspace/apps/apps.go index f7c08ece1..6eb85d873 100755 --- a/cmd/workspace/apps/apps.go +++ b/cmd/workspace/apps/apps.go @@ -956,13 +956,6 @@ func newUpdate() *cobra.Command { cmd.Annotations = make(map[string]string) cmd.Args = func(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("json") { - err := root.ExactArgs(0)(cmd, args) - if err != nil { - return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide 'name' in your JSON input") - } - return nil - } check := root.ExactArgs(1) return check(cmd, args) } diff --git a/cmd/workspace/lakeview/lakeview.go b/cmd/workspace/lakeview/lakeview.go index 6686f16da..eb2f5d8fa 100755 --- a/cmd/workspace/lakeview/lakeview.go +++ b/cmd/workspace/lakeview/lakeview.go @@ -163,13 +163,6 @@ func newCreateSchedule() *cobra.Command { cmd.Annotations = make(map[string]string) cmd.Args = func(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("json") { - err := root.ExactArgs(0)(cmd, args) - if err != nil { - return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide 'cron_schedule' in your JSON input") - } - return nil - } check := root.ExactArgs(1) return check(cmd, args) } @@ -242,13 +235,6 @@ func newCreateSubscription() *cobra.Command { cmd.Annotations = make(map[string]string) cmd.Args = func(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("json") { - err := root.ExactArgs(0)(cmd, args) - if err != nil { - return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide 'subscriber' in your JSON input") - } - return nil - } check := root.ExactArgs(2) return check(cmd, args) } @@ -1195,13 +1181,6 @@ func newUpdateSchedule() *cobra.Command { cmd.Annotations = make(map[string]string) cmd.Args = func(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("json") { - err := root.ExactArgs(0)(cmd, args) - if err != nil { - return fmt.Errorf("when --json flag is specified, no positional arguments are required. Provide 'cron_schedule' in your JSON input") - } - return nil - } check := root.ExactArgs(2) return check(cmd, args) }