Skip to content

Commit 5d3bfa3

Browse files
authored
Add sqlserverflex user create and reset-password commands (#384)
* Implement user create and reset-password * Update docs * Fix error message * Improve descriptions * Fix tests * Fixes after review * Fixes after review 2 * Update docs
1 parent 81f6c0d commit 5d3bfa3

18 files changed

+1067
-23
lines changed

docs/stackit_beta_sqlserverflex.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ stackit beta sqlserverflex [flags]
3131
* [stackit beta](./stackit_beta.md) - Contains beta STACKIT CLI commands
3232
* [stackit beta sqlserverflex instance](./stackit_beta_sqlserverflex_instance.md) - Provides functionality for SQLServer Flex instances
3333
* [stackit beta sqlserverflex options](./stackit_beta_sqlserverflex_options.md) - Lists SQL Server Flex options
34+
* [stackit beta sqlserverflex user](./stackit_beta_sqlserverflex_user.md) - Provides functionality for SQLServer Flex users
3435

docs/stackit_beta_sqlserverflex_options.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ stackit beta sqlserverflex options [flags]
2020
List SQL Server Flex available versions
2121
$ stackit beta sqlserverflex options --versions
2222
23-
List SQL Server Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit sqlserverflex options --flavors"
23+
List SQL Server Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit beta sqlserverflex options --flavors"
2424
$ stackit beta sqlserverflex options --storages --flavor-id <FLAVOR_ID>
2525
26-
List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit sqlserverflex instance list"
26+
List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit beta sqlserverflex instance list"
2727
$ stackit beta sqlserverflex options --user-roles --db-compatibilities --instance-id <INSTANCE_ID>
2828
```
2929

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## stackit beta sqlserverflex user
2+
3+
Provides functionality for SQLServer Flex users
4+
5+
### Synopsis
6+
7+
Provides functionality for SQLServer Flex users.
8+
9+
```
10+
stackit beta sqlserverflex user [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help Help for "stackit beta sqlserverflex user"
17+
```
18+
19+
### Options inherited from parent commands
20+
21+
```
22+
-y, --assume-yes If set, skips all confirmation prompts
23+
--async If set, runs the command asynchronously
24+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
25+
-p, --project-id string Project ID
26+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
27+
```
28+
29+
### SEE ALSO
30+
31+
* [stackit beta sqlserverflex](./stackit_beta_sqlserverflex.md) - Provides functionality for SQLServer Flex
32+
* [stackit beta sqlserverflex user create](./stackit_beta_sqlserverflex_user_create.md) - Creates an SQLServer Flex user
33+
* [stackit beta sqlserverflex user reset-password](./stackit_beta_sqlserverflex_user_reset-password.md) - Resets the password of an SQLServer Flex user
34+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
## stackit beta sqlserverflex user create
2+
3+
Creates an SQLServer Flex user
4+
5+
### Synopsis
6+
7+
Creates an SQLServer Flex user for an instance.
8+
The password is only visible upon creation and cannot be retrieved later.
9+
Alternatively, you can reset the password and access the new one by running:
10+
$ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID
11+
Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information.
12+
13+
```
14+
stackit beta sqlserverflex user create [flags]
15+
```
16+
17+
### Examples
18+
19+
```
20+
Create an SQLServer Flex user for instance with ID "xxx" and specify the username, role and database
21+
$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles my-role --database my-database
22+
23+
Create an SQLServer Flex user for instance with ID "xxx", specifying multiple roles
24+
$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "my-role-1,my-role-2
25+
```
26+
27+
### Options
28+
29+
```
30+
--database string Default database for the user
31+
-h, --help Help for "stackit beta sqlserverflex user create"
32+
--instance-id string ID of the instance
33+
--roles strings Roles of the user
34+
--username string Username of the user
35+
```
36+
37+
### Options inherited from parent commands
38+
39+
```
40+
-y, --assume-yes If set, skips all confirmation prompts
41+
--async If set, runs the command asynchronously
42+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
43+
-p, --project-id string Project ID
44+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
45+
```
46+
47+
### SEE ALSO
48+
49+
* [stackit beta sqlserverflex user](./stackit_beta_sqlserverflex_user.md) - Provides functionality for SQLServer Flex users
50+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## stackit beta sqlserverflex user reset-password
2+
3+
Resets the password of an SQLServer Flex user
4+
5+
### Synopsis
6+
7+
Resets the password of an SQLServer Flex user.
8+
sThe new password is visible after resetting and cannot be retrieved later.
9+
10+
```
11+
stackit beta sqlserverflex user reset-password USER_ID [flags]
12+
```
13+
14+
### Examples
15+
16+
```
17+
Reset the password of an SQLServer Flex user with ID "xxx" of instance with ID "yyy"
18+
$ stackit beta sqlserverflex user reset-password xxx --instance-id yyy
19+
```
20+
21+
### Options
22+
23+
```
24+
-h, --help Help for "stackit beta sqlserverflex user reset-password"
25+
--instance-id string ID of the instance
26+
```
27+
28+
### Options inherited from parent commands
29+
30+
```
31+
-y, --assume-yes If set, skips all confirmation prompts
32+
--async If set, runs the command asynchronously
33+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
34+
-p, --project-id string Project ID
35+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
36+
```
37+
38+
### SEE ALSO
39+
40+
* [stackit beta sqlserverflex user](./stackit_beta_sqlserverflex_user.md) - Provides functionality for SQLServer Flex users
41+

docs/stackit_mongodbflex_user_describe.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ stackit mongodbflex user describe USER_ID [flags]
1616

1717
```
1818
Get details of a MongoDB Flex user with ID "xxx" of instance with ID "yyy"
19-
$ stackit mongodbflex user list xxx --instance-id yyy
19+
$ stackit mongodbflex user describe xxx --instance-id yyy
2020
2121
Get details of a MongoDB Flex user with ID "xxx" of instance with ID "yyy" in JSON format
22-
$ stackit mongodbflex user list xxx --instance-id yyy --output-format json
22+
$ stackit mongodbflex user describe xxx --instance-id yyy --output-format json
2323
```
2424

2525
### Options

docs/stackit_postgresflex_user_describe.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ stackit postgresflex user describe USER_ID [flags]
1616

1717
```
1818
Get details of a PostgreSQL Flex user with ID "xxx" of instance with ID "yyy"
19-
$ stackit postgresflex user list xxx --instance-id yyy
19+
$ stackit postgresflex user describe xxx --instance-id yyy
2020
2121
Get details of a PostgreSQL Flex user with ID "xxx" of instance with ID "yyy" in JSON format
22-
$ stackit postgresflex user list xxx --instance-id yyy --output-format json
22+
$ stackit postgresflex user describe xxx --instance-id yyy --output-format json
2323
```
2424

2525
### Options

internal/cmd/beta/sqlserverflex/options/options.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ func NewCmd(p *print.Printer) *cobra.Command {
8787
`List SQL Server Flex available versions`,
8888
"$ stackit beta sqlserverflex options --versions"),
8989
examples.NewExample(
90-
`List SQL Server Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit sqlserverflex options --flavors"`,
90+
`List SQL Server Flex storage options for a given flavor. The flavor ID can be retrieved by running "$ stackit beta sqlserverflex options --flavors"`,
9191
"$ stackit beta sqlserverflex options --storages --flavor-id <FLAVOR_ID>"),
9292
examples.NewExample(
93-
`List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit sqlserverflex instance list"`,
93+
`List SQL Server Flex user roles and database compatibilities for a given instance. The IDs of existing instances can be obtained by running "$ stackit beta sqlserverflex instance list"`,
9494
"$ stackit beta sqlserverflex options --user-roles --db-compatibilities --instance-id <INSTANCE_ID>"),
9595
),
9696
RunE: func(cmd *cobra.Command, args []string) error {

internal/cmd/beta/sqlserverflex/sqlserverflex.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sqlserverflex
33
import (
44
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/instance"
55
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/options"
6+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/sqlserverflex/user"
67
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
78
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
89
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
@@ -25,4 +26,5 @@ func NewCmd(p *print.Printer) *cobra.Command {
2526
func addSubcommands(cmd *cobra.Command, p *print.Printer) {
2627
cmd.AddCommand(instance.NewCmd(p))
2728
cmd.AddCommand(options.NewCmd(p))
29+
cmd.AddCommand(user.NewCmd(p))
2830
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
8+
"github.com/goccy/go-yaml"
9+
"github.com/spf13/cobra"
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
16+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/client"
17+
sqlserverflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/utils"
18+
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex"
19+
)
20+
21+
const (
22+
instanceIdFlag = "instance-id"
23+
usernameFlag = "username"
24+
databaseFlag = "database"
25+
rolesFlag = "roles"
26+
)
27+
28+
type inputModel struct {
29+
*globalflags.GlobalFlagModel
30+
31+
InstanceId string
32+
Username *string
33+
Database *string
34+
Roles *[]string
35+
}
36+
37+
func NewCmd(p *print.Printer) *cobra.Command {
38+
cmd := &cobra.Command{
39+
Use: "create",
40+
Short: "Creates an SQLServer Flex user",
41+
Long: fmt.Sprintf("%s\n%s\n%s\n%s\n%s",
42+
"Creates an SQLServer Flex user for an instance.",
43+
"The password is only visible upon creation and cannot be retrieved later.",
44+
"Alternatively, you can reset the password and access the new one by running:",
45+
" $ stackit beta sqlserverflex user reset-password USER_ID --instance-id INSTANCE_ID",
46+
"Please refer to https://docs.stackit.cloud/stackit/en/creating-logins-and-users-in-sqlserver-flex-instances-210862358.html for additional information.",
47+
),
48+
Example: examples.Build(
49+
examples.NewExample(
50+
`Create an SQLServer Flex user for instance with ID "xxx" and specify the username, role and database`,
51+
"$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles my-role --database my-database"),
52+
examples.NewExample(
53+
`Create an SQLServer Flex user for instance with ID "xxx", specifying multiple roles`,
54+
`$ stackit beta sqlserverflex user create --instance-id xxx --username johndoe --roles "my-role-1,my-role-2`),
55+
),
56+
Args: args.NoArgs,
57+
RunE: func(cmd *cobra.Command, args []string) error {
58+
ctx := context.Background()
59+
model, err := parseInput(p, cmd)
60+
if err != nil {
61+
return err
62+
}
63+
64+
// Configure API client
65+
apiClient, err := client.ConfigureClient(p)
66+
if err != nil {
67+
return err
68+
}
69+
70+
instanceLabel, err := sqlserverflexUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId)
71+
if err != nil {
72+
p.Debug(print.ErrorLevel, "get instance name: %v", err)
73+
instanceLabel = model.InstanceId
74+
}
75+
76+
if !model.AssumeYes {
77+
prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel)
78+
err = p.PromptForConfirmation(prompt)
79+
if err != nil {
80+
return err
81+
}
82+
}
83+
84+
// Call API
85+
req := buildRequest(ctx, model, apiClient)
86+
resp, err := req.Execute()
87+
if err != nil {
88+
return fmt.Errorf("create SQLServer Flex user: %w", err)
89+
}
90+
user := resp.Item
91+
92+
return outputResult(p, model, instanceLabel, user)
93+
},
94+
}
95+
96+
configureFlags(cmd)
97+
return cmd
98+
}
99+
100+
func configureFlags(cmd *cobra.Command) {
101+
cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance")
102+
cmd.Flags().String(usernameFlag, "", "Username of the user")
103+
cmd.Flags().String(databaseFlag, "", "Default database for the user")
104+
cmd.Flags().StringSlice(rolesFlag, []string{}, "Roles of the user")
105+
106+
err := flags.MarkFlagsRequired(cmd, instanceIdFlag, usernameFlag)
107+
cobra.CheckErr(err)
108+
}
109+
110+
func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
111+
globalFlags := globalflags.Parse(p, cmd)
112+
if globalFlags.ProjectId == "" {
113+
return nil, &errors.ProjectIdError{}
114+
}
115+
116+
model := inputModel{
117+
GlobalFlagModel: globalFlags,
118+
InstanceId: flags.FlagToStringValue(p, cmd, instanceIdFlag),
119+
Username: flags.FlagToStringPointer(p, cmd, usernameFlag),
120+
Database: flags.FlagToStringPointer(p, cmd, databaseFlag),
121+
Roles: flags.FlagToStringSlicePointer(p, cmd, rolesFlag),
122+
}
123+
124+
if p.IsVerbosityDebug() {
125+
modelStr, err := print.BuildDebugStrFromInputModel(model)
126+
if err != nil {
127+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
128+
} else {
129+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
130+
}
131+
}
132+
133+
return &model, nil
134+
}
135+
136+
func buildRequest(ctx context.Context, model *inputModel, apiClient *sqlserverflex.APIClient) sqlserverflex.ApiCreateUserRequest {
137+
req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId)
138+
139+
var roles []sqlserverflex.Role
140+
if model.Roles != nil {
141+
for _, r := range *model.Roles {
142+
roles = append(roles, sqlserverflex.Role(r))
143+
}
144+
}
145+
146+
req = req.CreateUserPayload(sqlserverflex.CreateUserPayload{
147+
Username: model.Username,
148+
Database: model.Database,
149+
Roles: &roles,
150+
})
151+
return req
152+
}
153+
154+
func outputResult(p *print.Printer, model *inputModel, instanceLabel string, user *sqlserverflex.User) error {
155+
switch model.OutputFormat {
156+
case print.JSONOutputFormat:
157+
details, err := json.MarshalIndent(user, "", " ")
158+
if err != nil {
159+
return fmt.Errorf("marshal SQLServer Flex user: %w", err)
160+
}
161+
p.Outputln(string(details))
162+
163+
return nil
164+
case print.YAMLOutputFormat:
165+
details, err := yaml.MarshalWithOptions(user, yaml.IndentSequence(true))
166+
if err != nil {
167+
return fmt.Errorf("marshal SQLServer Flex user: %w", err)
168+
}
169+
p.Outputln(string(details))
170+
171+
return nil
172+
default:
173+
p.Outputf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *user.Id)
174+
p.Outputf("Username: %s\n", *user.Username)
175+
p.Outputf("Password: %s\n", *user.Password)
176+
if user.Roles != nil && len(*user.Roles) != 0 {
177+
p.Outputf("Roles: %v\n", *user.Roles)
178+
}
179+
if user.Database != nil && *user.Database != "" {
180+
p.Outputf("Database: %s\n", *user.Database)
181+
}
182+
if user.Host != nil && *user.Host != "" {
183+
p.Outputf("Host: %s\n", *user.Host)
184+
}
185+
if user.Port != nil {
186+
p.Outputf("Port: %d\n", *user.Port)
187+
}
188+
if user.Uri != nil && *user.Uri != "" {
189+
p.Outputf("URI: %s\n", *user.Uri)
190+
}
191+
192+
return nil
193+
}
194+
}

0 commit comments

Comments
 (0)