@@ -19,32 +19,60 @@ import (
19
19
)
20
20
21
21
const (
22
- flavorsFlag = "flavors"
23
- versionsFlag = "versions"
24
- storagesFlag = "storages"
25
- flavorIdFlag = "flavor-id"
22
+ flavorsFlag = "flavors"
23
+ versionsFlag = "versions"
24
+ storagesFlag = "storages"
25
+ userRolesFlag = "user-roles"
26
+ dbCollationsFlag = "db-collations"
27
+ dbCompatibilitiesFlag = "db-compatibilities"
28
+
29
+ flavorIdFlag = "flavor-id"
30
+ instanceIdFlag = "instance-id"
26
31
)
27
32
28
33
type inputModel struct {
29
34
* globalflags.GlobalFlagModel
30
35
31
- Flavors bool
32
- Versions bool
33
- Storages bool
34
- FlavorId * string
36
+ Flavors bool
37
+ Versions bool
38
+ Storages bool
39
+ UserRoles bool
40
+ DBCollations bool
41
+ DBCompatibilities bool
42
+
43
+ FlavorId * string
44
+ InstanceId * string
35
45
}
36
46
37
47
type options struct {
38
- Flavors * []sqlserverflex.InstanceFlavorEntry `json:"flavors,omitempty"`
39
- Versions * []string `json:"versions,omitempty"`
40
- Storages * flavorStorages `json:"flavorStorages,omitempty"`
48
+ Flavors * []sqlserverflex.InstanceFlavorEntry `json:"flavors,omitempty"`
49
+ Versions * []string `json:"versions,omitempty"`
50
+ Storages * flavorStorages `json:"flavorStorages,omitempty"`
51
+ UserRoles * instanceUserRoles `json:"userRoles,omitempty"`
52
+ DBCollations * instanceDBCollations `json:"dbCollations,omitempty"`
53
+ DBCompatibilities * instanceDBCompatibilities `json:"dbCompatibilities,omitempty"`
41
54
}
42
55
43
56
type flavorStorages struct {
44
57
FlavorId string `json:"flavorId"`
45
58
Storages * sqlserverflex.ListStoragesResponse `json:"storages"`
46
59
}
47
60
61
+ type instanceUserRoles struct {
62
+ InstanceId string `json:"instanceId"`
63
+ UserRoles []string `json:"userRoles"`
64
+ }
65
+
66
+ type instanceDBCollations struct {
67
+ InstanceId string `json:"instanceId"`
68
+ DBCollations []sqlserverflex.MssqlDatabaseCollation `json:"dbCollations"`
69
+ }
70
+
71
+ type instanceDBCompatibilities struct {
72
+ InstanceId string `json:"instanceId"`
73
+ DBCompatibilities []sqlserverflex.MssqlDatabaseCompatibility `json:"dbCompatibilities"`
74
+ }
75
+
48
76
func NewCmd (p * print.Printer ) * cobra.Command {
49
77
cmd := & cobra.Command {
50
78
Use : "options" ,
@@ -92,17 +120,27 @@ func configureFlags(cmd *cobra.Command) {
92
120
cmd .Flags ().Bool (flavorsFlag , false , "Lists supported flavors" )
93
121
cmd .Flags ().Bool (versionsFlag , false , "Lists supported versions" )
94
122
cmd .Flags ().Bool (storagesFlag , false , "Lists supported storages for a given flavor" )
123
+ cmd .Flags ().Bool (userRolesFlag , false , "Lists supported user roles for a given instance" )
124
+ cmd .Flags ().Bool (dbCollationsFlag , false , "Lists supported database collations for a given instance" )
125
+ cmd .Flags ().Bool (dbCompatibilitiesFlag , false , "Lists supported database compatibilities for a given instance" )
95
126
cmd .Flags ().String (flavorIdFlag , "" , `The flavor ID to show storages for. Only relevant when "--storages" is passed` )
127
+ cmd .Flags ().String (instanceIdFlag , "" , `The instance ID to show user roles, database collations and database compatibilities for. Only relevant when "--user-roles", "--db-collations" or "--db-compatibilities" is passed` )
96
128
}
97
129
98
130
func parseInput (p * print.Printer , cmd * cobra.Command ) (* inputModel , error ) {
99
131
globalFlags := globalflags .Parse (p , cmd )
132
+
100
133
flavors := flags .FlagToBoolValue (p , cmd , flavorsFlag )
101
134
versions := flags .FlagToBoolValue (p , cmd , versionsFlag )
102
135
storages := flags .FlagToBoolValue (p , cmd , storagesFlag )
136
+ userRoles := flags .FlagToBoolValue (p , cmd , userRolesFlag )
137
+ dbCollations := flags .FlagToBoolValue (p , cmd , dbCollationsFlag )
138
+ dbCompatibilities := flags .FlagToBoolValue (p , cmd , dbCompatibilitiesFlag )
139
+
103
140
flavorId := flags .FlagToStringPointer (p , cmd , flavorIdFlag )
141
+ instanceId := flags .FlagToStringPointer (p , cmd , instanceIdFlag )
104
142
105
- if ! flavors && ! versions && ! storages {
143
+ if ! flavors && ! versions && ! storages && ! userRoles && ! dbCollations && ! dbCompatibilities {
106
144
return nil , fmt .Errorf ("%s\n \n %s" ,
107
145
"please specify at least one category for which to list the available options." ,
108
146
"Get details on the available flags by re-running your command with the --help flag." )
@@ -115,12 +153,23 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
115
153
" $ stackit sqlserverflex options --flavors" )
116
154
}
117
155
156
+ if (userRoles || dbCollations || dbCompatibilities ) && instanceId == nil {
157
+ return nil , fmt .Errorf ("%s\n \n %s\n %s" ,
158
+ `please specify an instance ID to show user roles, database collations or database compatibilities for by setting the flag "--instance-id <INSTANCE_ID>".` ,
159
+ "You can get the available instances and their IDs by running:" ,
160
+ " $ stackit sqlserverflex instance list" )
161
+ }
162
+
118
163
model := inputModel {
119
- GlobalFlagModel : globalFlags ,
120
- Flavors : flavors ,
121
- Versions : versions ,
122
- Storages : storages ,
123
- FlavorId : flags .FlagToStringPointer (p , cmd , flavorIdFlag ),
164
+ GlobalFlagModel : globalFlags ,
165
+ Flavors : flavors ,
166
+ Versions : versions ,
167
+ Storages : storages ,
168
+ UserRoles : userRoles ,
169
+ DBCollations : dbCollations ,
170
+ DBCompatibilities : dbCompatibilities ,
171
+ FlavorId : flavorId ,
172
+ InstanceId : instanceId ,
124
173
}
125
174
126
175
if p .IsVerbosityDebug () {
@@ -139,12 +188,18 @@ type sqlServerFlexOptionsClient interface {
139
188
ListFlavorsExecute (ctx context.Context , projectId string ) (* sqlserverflex.ListFlavorsResponse , error )
140
189
ListVersionsExecute (ctx context.Context , projectId string ) (* sqlserverflex.ListVersionsResponse , error )
141
190
ListStoragesExecute (ctx context.Context , projectId , flavorId string ) (* sqlserverflex.ListStoragesResponse , error )
191
+ ListRolesExecute (ctx context.Context , projectId string , instanceId string ) (* sqlserverflex.ListRolesResponse , error )
192
+ ListCollationsExecute (ctx context.Context , projectId string , instanceId string ) (* sqlserverflex.ListCollationsResponse , error )
193
+ ListCompatibilityExecute (ctx context.Context , projectId string , instanceId string ) (* sqlserverflex.ListCompatibilityResponse , error )
142
194
}
143
195
144
196
func buildAndExecuteRequest (ctx context.Context , p * print.Printer , model * inputModel , apiClient sqlServerFlexOptionsClient ) error {
145
197
var flavors * sqlserverflex.ListFlavorsResponse
146
198
var versions * sqlserverflex.ListVersionsResponse
147
199
var storages * sqlserverflex.ListStoragesResponse
200
+ var userRoles * sqlserverflex.ListRolesResponse
201
+ var dbCollations * sqlserverflex.ListCollationsResponse
202
+ var dbCompatibilities * sqlserverflex.ListCompatibilityResponse
148
203
var err error
149
204
150
205
if model .Flavors {
@@ -165,11 +220,29 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM
165
220
return fmt .Errorf ("get SQL Server Flex storages: %w" , err )
166
221
}
167
222
}
223
+ if model .UserRoles {
224
+ userRoles , err = apiClient .ListRolesExecute (ctx , model .ProjectId , * model .InstanceId )
225
+ if err != nil {
226
+ return fmt .Errorf ("get SQL Server Flex user roles: %w" , err )
227
+ }
228
+ }
229
+ if model .DBCollations {
230
+ dbCollations , err = apiClient .ListCollationsExecute (ctx , model .ProjectId , * model .InstanceId )
231
+ if err != nil {
232
+ return fmt .Errorf ("get SQL Server Flex DB collations: %w" , err )
233
+ }
234
+ }
235
+ if model .DBCompatibilities {
236
+ dbCompatibilities , err = apiClient .ListCompatibilityExecute (ctx , model .ProjectId , * model .InstanceId )
237
+ if err != nil {
238
+ return fmt .Errorf ("get SQL Server Flex DB compatibilities: %w" , err )
239
+ }
240
+ }
168
241
169
- return outputResult (p , model , flavors , versions , storages )
242
+ return outputResult (p , model , flavors , versions , storages , userRoles , dbCollations , dbCompatibilities )
170
243
}
171
244
172
- func outputResult (p * print.Printer , model * inputModel , flavors * sqlserverflex.ListFlavorsResponse , versions * sqlserverflex.ListVersionsResponse , storages * sqlserverflex.ListStoragesResponse ) error {
245
+ func outputResult (p * print.Printer , model * inputModel , flavors * sqlserverflex.ListFlavorsResponse , versions * sqlserverflex.ListVersionsResponse , storages * sqlserverflex.ListStoragesResponse , userRoles * sqlserverflex. ListRolesResponse , dbCollations * sqlserverflex. ListCollationsResponse , dbCompatibilities * sqlserverflex. ListCompatibilityResponse ) error {
173
246
options := & options {}
174
247
if flavors != nil {
175
248
options .Flavors = flavors .Flavors
@@ -183,6 +256,24 @@ func outputResult(p *print.Printer, model *inputModel, flavors *sqlserverflex.Li
183
256
Storages : storages ,
184
257
}
185
258
}
259
+ if userRoles != nil && model .InstanceId != nil {
260
+ options .UserRoles = & instanceUserRoles {
261
+ InstanceId : * model .InstanceId ,
262
+ UserRoles : * userRoles .Roles ,
263
+ }
264
+ }
265
+ if dbCollations != nil && model .InstanceId != nil {
266
+ options .DBCollations = & instanceDBCollations {
267
+ InstanceId : * model .InstanceId ,
268
+ DBCollations : * dbCollations .Collations ,
269
+ }
270
+ }
271
+ if dbCompatibilities != nil && model .InstanceId != nil {
272
+ options .DBCompatibilities = & instanceDBCompatibilities {
273
+ InstanceId : * model .InstanceId ,
274
+ DBCompatibilities : * dbCompatibilities .Compatibilities ,
275
+ }
276
+ }
186
277
187
278
switch model .OutputFormat {
188
279
case print .JSONOutputFormat :
@@ -216,6 +307,15 @@ func outputResultAsTable(p *print.Printer, model *inputModel, options *options)
216
307
if model .Storages {
217
308
content += renderStorages (options .Storages .Storages )
218
309
}
310
+ if model .UserRoles {
311
+ content += renderUserRoles (options .UserRoles )
312
+ }
313
+ if model .DBCollations {
314
+ content += renderDBCollations (options .DBCollations )
315
+ }
316
+ if model .DBCompatibilities {
317
+ content += renderDBCompatibilities (options .DBCompatibilities )
318
+ }
219
319
220
320
err := p .PagerDisplay (content )
221
321
if err != nil {
@@ -271,3 +371,45 @@ func renderStorages(resp *sqlserverflex.ListStoragesResponse) string {
271
371
table .EnableAutoMergeOnColumns (1 , 2 , 3 )
272
372
return table .Render ()
273
373
}
374
+
375
+ func renderUserRoles (roles * instanceUserRoles ) string {
376
+ if len (roles .UserRoles ) == 0 {
377
+ return ""
378
+ }
379
+
380
+ table := tables .NewTable ()
381
+ table .SetTitle ("User Roles" )
382
+ table .SetHeader ("ROLE" )
383
+ for i := range roles .UserRoles {
384
+ table .AddRow (roles .UserRoles [i ])
385
+ }
386
+ return table .Render ()
387
+ }
388
+
389
+ func renderDBCollations (dbCollations * instanceDBCollations ) string {
390
+ if len (dbCollations .DBCollations ) == 0 {
391
+ return ""
392
+ }
393
+
394
+ table := tables .NewTable ()
395
+ table .SetTitle ("DB Collations" )
396
+ table .SetHeader ("NAME" , "DESCRIPTION" )
397
+ for i := range dbCollations .DBCollations {
398
+ table .AddRow (* dbCollations .DBCollations [i ].CollationName , * dbCollations .DBCollations [i ].Description )
399
+ }
400
+ return table .Render ()
401
+ }
402
+
403
+ func renderDBCompatibilities (dbCompatibilities * instanceDBCompatibilities ) string {
404
+ if len (dbCompatibilities .DBCompatibilities ) == 0 {
405
+ return ""
406
+ }
407
+
408
+ table := tables .NewTable ()
409
+ table .SetTitle ("DB Compatibilities" )
410
+ table .SetHeader ("COMPATIBILITY LEVEL" , "DESCRIPTION" )
411
+ for i := range dbCompatibilities .DBCompatibilities {
412
+ table .AddRow (* dbCompatibilities .DBCompatibilities [i ].CompatibilityLevel , * dbCompatibilities .DBCompatibilities [i ].Description )
413
+ }
414
+ return table .Render ()
415
+ }
0 commit comments