-
Notifications
You must be signed in to change notification settings - Fork 54
feat(sca): onboard service command #1632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7e5e64e
1213622
241c7d7
90fe33a
532ba63
a738569
1d07b8a
29f696e
d4cf417
9aec524
ca2af82
cafa158
d3e17db
8000289
d312060
401052d
c472836
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package alpha | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/types" | ||
|
|
||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/utils" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| func NewCmd(params *types.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "alpha", | ||
| Short: "Contains alpha STACKIT CLI commands", | ||
| Long: fmt.Sprintf("%s\n%s", | ||
| "Contains alpha STACKIT CLI commands.", | ||
| "The commands under this group are still in an alpha state, and functionality may be incomplete or have breaking changes."), | ||
| Args: args.NoArgs, | ||
| Run: utils.CmdHelp, | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| "See the currently available alpha commands", | ||
| "$ stackit alpha --help"), | ||
| examples.NewExample( | ||
| "Execute a alpha command", | ||
| "$ stackit alpha MY_COMMAND"), | ||
| ), | ||
| } | ||
| addSubcommands(cmd, params) | ||
| return cmd | ||
| } | ||
|
|
||
| func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { | ||
| cmd.AddCommand(sca.NewCmd(params)) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package application | ||
|
|
||
| import ( | ||
| "github.com/spf13/cobra" | ||
|
|
||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/create" | ||
| createfrompayload "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/create-from-payload" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/delete" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/describe" | ||
| generatepayload "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/generate-payload" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/list" | ||
| "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/update" | ||
| updatefrompayload "github.com/stackitcloud/stackit-cli/internal/cmd/alpha/sca/application/update-from-payload" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/types" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/utils" | ||
| ) | ||
|
|
||
| func NewCmd(params *types.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "application", | ||
| Short: "Provides functionality for SCA applications", | ||
| Long: "Provides functionality for STACKIT Container Applications (SCA) cluster.", | ||
| Args: args.NoArgs, | ||
| Run: utils.CmdHelp, | ||
| } | ||
| addSubcommands(cmd, params) | ||
| return cmd | ||
| } | ||
|
|
||
| func addSubcommands(cmd *cobra.Command, params *types.CmdParams) { | ||
| cmd.AddCommand(list.NewCmd(params)) | ||
| cmd.AddCommand(describe.NewCmd(params)) | ||
| cmd.AddCommand(create.NewCmd(params)) | ||
| cmd.AddCommand(createfrompayload.NewCmd(params)) | ||
| cmd.AddCommand(delete.NewCmd(params)) | ||
| cmd.AddCommand(generatepayload.NewCmd(params)) | ||
| cmd.AddCommand(update.NewCmd(params)) | ||
| cmd.AddCommand(updatefrompayload.NewCmd(params)) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| package createfrompayload | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "fmt" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| sca "github.com/stackitcloud/stackit-sdk-go/services/sca/v1alphaapi" | ||
| "github.com/stackitcloud/stackit-sdk-go/services/sca/v1alphaapi/wait" | ||
|
|
||
| "github.com/stackitcloud/stackit-cli/internal/pkg/args" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/errors" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/examples" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/flags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/print" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/services/sca/client" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" | ||
| "github.com/stackitcloud/stackit-cli/internal/pkg/types" | ||
| ) | ||
|
|
||
| const ( | ||
| environmentIDFlag = "environment-id" | ||
| nameFlag = "name" | ||
| payloadFlag = "payload" | ||
| ) | ||
|
|
||
| type inputModel struct { | ||
| *globalflags.GlobalFlagModel | ||
| EnvironmentID string | ||
| Payload *sca.CreateApplicationPayload | ||
| } | ||
|
|
||
| func NewCmd(params *types.CmdParams) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "create-from-payload", | ||
| Short: "Create a SCA application from payload", | ||
| Long: fmt.Sprintf("%s\n%s\n%s", | ||
| "Create a STACKIT Container Applications (SCA) application from payload.", | ||
| `The payload can be provided as a JSON string or a file path prefixed with "@".`, | ||
| "See https://docs.api.stackit.cloud/documentation/sca/version/v1alpha#tag/Applications/operation/Applications_CreateApplication for information regarding the payload structure.", | ||
| ), | ||
| Args: args.NoArgs, | ||
| Example: examples.Build( | ||
| examples.NewExample( | ||
| `Create a SCA application using an API payload sourced from the file "./payload.json"`, | ||
| "$ stackit alpha sca cluster create-from-payload --name application-name --payload @./payload.json"), | ||
| examples.NewExample( | ||
| `Create a SCA application using an API payload provided as a JSON string`, | ||
| `$ stackit alpha sca cluster create-from-payload --name application-name --payload "{...}"`), | ||
| examples.NewExample( | ||
| `Generate a payload with default values, and adapt it with custom values for the different configuration options`, | ||
| `$ stackit alpha sca application generate-payload --file-path ./payload.json`, | ||
| `<Modify payload in file, if needed>`, | ||
| `$ stackit alpha sca application create-from-payload --name application-name --payload @./payload.json`), | ||
| ), | ||
| RunE: func(cmd *cobra.Command, _ []string) error { | ||
| ctx := context.Background() | ||
|
|
||
| model, err := parseInput(params.Printer, cmd, nil) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // Configure API client | ||
| apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| globalFlags := globalflags.Parse(params.Printer, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return &errors.ProjectIdError{} | ||
| } | ||
|
|
||
| // Call API | ||
| req := buildRequest(ctx, model, apiClient) | ||
| resp, err := req.Execute() | ||
| if err != nil { | ||
| return fmt.Errorf("create application: %w", err) | ||
| } | ||
|
|
||
| if !model.Async { | ||
| err := spinner.Run(params.Printer, fmt.Sprintf("Creating application with id %q", resp.GetId()), func() error { | ||
| _, err := wait.CreateApplicationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.EnvironmentID, resp.GetId()).WaitWithContext(ctx) | ||
| return err | ||
| }) | ||
| if err != nil { | ||
| return fmt.Errorf("wait for application creation: %w", err) | ||
| } | ||
| } | ||
|
|
||
| return outputResult(params.Printer, model, resp) | ||
| }, | ||
| } | ||
|
|
||
| configureFlags(cmd) | ||
| return cmd | ||
| } | ||
|
|
||
| func buildRequest(ctx context.Context, model *inputModel, apiClient *sca.APIClient) sca.ApiCreateApplicationRequest { | ||
| return apiClient.DefaultAPI.CreateApplication(ctx, model.ProjectId, model.EnvironmentID). | ||
| CreateApplicationPayload(*model.Payload) | ||
| } | ||
|
|
||
| func outputResult(p *print.Printer, model *inputModel, application *sca.Application) error { | ||
| return p.OutputResult(model.OutputFormat, application, func() error { | ||
| if application == nil { | ||
| return fmt.Errorf("create application response is empty") | ||
| } | ||
| operationState := "Created" | ||
| if model.Async { | ||
| operationState = "Triggered creation of" | ||
| } | ||
| p.Outputf("%s application for environment %s. Application ID: %s\n", operationState, application.GetEnvironmentId(), application.GetId()) | ||
| return nil | ||
| }) | ||
| } | ||
|
|
||
| func configureFlags(cmd *cobra.Command) { | ||
| cmd.Flags().Var(flags.UUIDFlag(), environmentIDFlag, "Environment ID (uses default environment if not set)") | ||
| cmd.Flags().String(nameFlag, "", "Application display name") | ||
| cmd.Flags().Var(flags.ReadFromFileFlag(), payloadFlag, `Request payload (JSON). Can be a string or a file path, if prefixed with "@" (example: @./payload.json).`) | ||
|
|
||
| cobra.CheckErr(flags.MarkFlagsRequired(cmd, nameFlag, payloadFlag)) | ||
| } | ||
|
|
||
| func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { | ||
| globalFlags := globalflags.Parse(p, cmd) | ||
| if globalFlags.ProjectId == "" { | ||
| return nil, &errors.ProjectIdError{} | ||
| } | ||
|
|
||
| environmentID := flags.FlagToStringValue(p, cmd, environmentIDFlag) | ||
| if environmentID == "" { | ||
| environmentID = globalFlags.ProjectId | ||
| } | ||
|
|
||
| payloadValue := flags.FlagToStringPointer(p, cmd, payloadFlag) | ||
| var payload *sca.CreateApplicationPayload | ||
| if payloadValue != nil { | ||
| payload = &sca.CreateApplicationPayload{} | ||
| err := json.Unmarshal([]byte(*payloadValue), payload) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("encode payload: %w", err) | ||
| } | ||
| } | ||
|
|
||
| if payload == nil { | ||
| return nil, &errors.FlagValidationError{ | ||
| Flag: payloadFlag, | ||
| Details: "Received empty payload", | ||
| } | ||
| } | ||
|
Comment on lines
+150
to
+155
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docs state default payload is used when none is specified. At the moment payload is declared as optional and
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, i'll make it required, same for update-from-payload |
||
|
|
||
| payload.DisplayName = flags.FlagToStringValue(p, cmd, nameFlag) | ||
|
SerseusWasTaken marked this conversation as resolved.
|
||
|
|
||
| model := inputModel{ | ||
| GlobalFlagModel: globalFlags, | ||
| EnvironmentID: environmentID, | ||
| Payload: payload, | ||
| } | ||
|
|
||
| p.DebugInputModel(model) | ||
| return &model, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docs state default payload is used when none is set - this is not the case