Skip to content

Commit 0e22b83

Browse files
author
João Palet
committed
Implement database create command
1 parent ac7b43d commit 0e22b83

6 files changed

Lines changed: 443 additions & 2 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
8+
"github.com/goccy/go-yaml"
9+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client"
16+
"github.com/stackitcloud/stackit-cli/internal/pkg/spinner"
17+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
18+
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex"
19+
20+
"github.com/spf13/cobra"
21+
)
22+
23+
const (
24+
databaseNameArg = "DATABASE_NAME"
25+
26+
instanceIdFlag = "instance-id"
27+
ownerFlag = "owner"
28+
)
29+
30+
type inputModel struct {
31+
*globalflags.GlobalFlagModel
32+
DatabaseName string
33+
InstanceId string
34+
Owner string
35+
}
36+
37+
func NewCmd(p *print.Printer) *cobra.Command {
38+
cmd := &cobra.Command{
39+
Use: fmt.Sprintf("create %s", databaseNameArg),
40+
Short: "Creates an SQLServer Flex database",
41+
Long: fmt.Sprintf("%s\n%s",
42+
"Creates an SQLServer Flex database.",
43+
`This operation cannot be triggered asynchronously (the "--async" flag will have no effect).`,
44+
),
45+
Args: args.SingleArg(databaseNameArg, nil),
46+
Example: examples.Build(
47+
examples.NewExample(
48+
`Create an SQLServer Flex database with name "my-database" on instance with ID "xxx"`,
49+
"$ stackit beta sqlserverflex database create my-database --instance-id xxx --owner some-username"),
50+
),
51+
RunE: func(cmd *cobra.Command, args []string) error {
52+
ctx := context.Background()
53+
model, err := parseInput(p, cmd, args)
54+
if err != nil {
55+
return err
56+
}
57+
58+
// Configure API client
59+
apiClient, err := client.ConfigureClient(p)
60+
if err != nil {
61+
return err
62+
}
63+
64+
if !model.AssumeYes {
65+
prompt := fmt.Sprintf("Are you sure you want to create database %q? (This cannot be undone)", model.DatabaseName)
66+
err = p.PromptForConfirmation(prompt)
67+
if err != nil {
68+
return err
69+
}
70+
}
71+
72+
// Call API
73+
req := buildRequest(ctx, model, apiClient)
74+
s := spinner.New(p)
75+
s.Start("Creating database")
76+
resp, err := req.Execute()
77+
if err != nil {
78+
s.StopWithError()
79+
return fmt.Errorf("create SQLServer Flex database: %w", err)
80+
}
81+
s.Stop()
82+
83+
return outputResult(p, model, resp)
84+
},
85+
}
86+
configureFlags(cmd)
87+
return cmd
88+
}
89+
90+
func configureFlags(cmd *cobra.Command) {
91+
cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "SQLServer Flex instance ID")
92+
cmd.Flags().String(ownerFlag, "", "Username of the owner user")
93+
err := flags.MarkFlagsRequired(cmd, instanceIdFlag, ownerFlag)
94+
cobra.CheckErr(err)
95+
}
96+
97+
func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
98+
databaseName := inputArgs[0]
99+
100+
globalFlags := globalflags.Parse(p, cmd)
101+
if globalFlags.ProjectId == "" {
102+
return nil, &errors.ProjectIdError{}
103+
}
104+
105+
model := inputModel{
106+
GlobalFlagModel: globalFlags,
107+
DatabaseName: databaseName,
108+
InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag),
109+
Owner: flags.FlagToStringValue(p, cmd, ownerFlag),
110+
}
111+
112+
if p.IsVerbosityDebug() {
113+
modelStr, err := print.BuildDebugStrFromInputModel(model)
114+
if err != nil {
115+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
116+
} else {
117+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
118+
}
119+
}
120+
121+
return &model, nil
122+
}
123+
124+
func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiCreateDatabaseRequest {
125+
req := apiClient.CreateDatabase(ctx, model.ProjectId, model.InstanceId)
126+
payload := sqlserverflex.CreateDatabasePayload{
127+
Name: &model.DatabaseName,
128+
Options: utils.Ptr(map[string]string{
129+
"owner": model.Owner,
130+
}),
131+
}
132+
req = req.CreateDatabasePayload(payload)
133+
return req
134+
}
135+
136+
func outputResult(p *print.Printer, model *inputModel, resp *sqlserverflex.CreateDatabaseResponse) error {
137+
switch model.OutputFormat {
138+
case print.JSONOutputFormat:
139+
details, err := json.MarshalIndent(resp, "", " ")
140+
if err != nil {
141+
return fmt.Errorf("marshal SQLServer Flex database: %w", err)
142+
}
143+
p.Outputln(string(details))
144+
145+
return nil
146+
case print.YAMLOutputFormat:
147+
details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true))
148+
if err != nil {
149+
return fmt.Errorf("marshal SQLServer Flex database: %w", err)
150+
}
151+
p.Outputln(string(details))
152+
153+
return nil
154+
default:
155+
operationState := "Created"
156+
if model.Async {
157+
operationState = "Triggered creation of"
158+
}
159+
p.Outputf("%s database %q\n", operationState, model.DatabaseName)
160+
return nil
161+
}
162+
}

0 commit comments

Comments
 (0)