Skip to content

Commit c03d6b0

Browse files
authored
feat(objectstorage): add command to list available regions (#316)
1 parent 127cf6e commit c03d6b0

4 files changed

Lines changed: 72 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Add `gateway plans` command for listing gateway plans.
13+
- Add `objectstorage regions` command for listing managed object storage regions.
1314

1415
### Changed
1516

internal/commands/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ func BuildCommands(rootCmd *cobra.Command, conf *config.Config) {
197197
commands.BuildCommand(objectstorage.DeleteCommand(), objectStorageCommand.Cobra(), conf)
198198
commands.BuildCommand(objectstorage.ListCommand(), objectStorageCommand.Cobra(), conf)
199199
commands.BuildCommand(objectstorage.ShowCommand(), objectStorageCommand.Cobra(), conf)
200+
commands.BuildCommand(objectstorage.RegionsCommand(), objectStorageCommand.Cobra(), conf)
200201

201202
// Network Gateway operations
202203
gatewayCommand := commands.BuildCommand(gateway.BaseGatewayCommand(), rootCmd, conf)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package objectstorage
2+
3+
import (
4+
"sort"
5+
6+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
7+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/format"
8+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/output"
9+
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
10+
)
11+
12+
// RegionsCommand creates the "objectstorage regions" command
13+
func RegionsCommand() commands.Command {
14+
return &regionsCommand{
15+
BaseCommand: commands.New("regions", "List objectstorage regions", "upctl objectstorage regions"),
16+
}
17+
}
18+
19+
type regionsCommand struct {
20+
*commands.BaseCommand
21+
}
22+
23+
// ExecuteWithoutArguments implements commands.NoArgumentCommand
24+
func (s *regionsCommand) ExecuteWithoutArguments(exec commands.Executor) (output.Output, error) {
25+
regions, err := exec.All().GetManagedObjectStorageRegions(exec.Context(), &request.GetManagedObjectStorageRegionsRequest{})
26+
if err != nil {
27+
return nil, err
28+
}
29+
30+
sort.Slice(regions, func(i, j int) bool {
31+
return regions[i].Name < regions[j].Name
32+
})
33+
34+
rows := []output.TableRow{}
35+
for _, r := range regions {
36+
zones := []string{}
37+
for _, z := range r.Zones {
38+
zones = append(zones, z.Name)
39+
}
40+
sort.Strings(zones)
41+
42+
rows = append(rows, output.TableRow{
43+
r.Name,
44+
r.PrimaryZone,
45+
zones,
46+
})
47+
}
48+
49+
return output.MarshaledWithHumanOutput{
50+
Value: regions,
51+
Output: output.Table{
52+
Columns: []output.TableColumn{
53+
{Key: "name", Header: "Name"},
54+
{Key: "primary_zone", Header: "Primary zone"},
55+
{Key: "zones", Header: "Zones", Format: format.StringSliceSingleLineAnd},
56+
},
57+
Rows: rows,
58+
},
59+
}, nil
60+
}

internal/format/stringslice.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ import (
99
)
1010

1111
func StringSliceOr(val interface{}) (text.Colors, string, error) {
12-
return formatStringSlice(val, "or")
12+
return formatStringSlice(val, "or", false)
1313
}
1414

1515
func StringSliceAnd(val interface{}) (text.Colors, string, error) {
16-
return formatStringSlice(val, "and")
16+
return formatStringSlice(val, "and", false)
1717
}
1818

19-
func formatStringSlice(val interface{}, andOrOr string) (text.Colors, string, error) {
19+
func StringSliceSingleLineAnd(val interface{}) (text.Colors, string, error) {
20+
return formatStringSlice(val, "and", true)
21+
}
22+
23+
func formatStringSlice(val interface{}, andOrOr string, singleLine bool) (text.Colors, string, error) {
2024
if val == nil {
2125
return nil, "", nil
2226
}
@@ -26,7 +30,7 @@ func formatStringSlice(val interface{}, andOrOr string) (text.Colors, string, er
2630
}
2731

2832
if ifaceSliceVal, ok := toIfaceSlice(val); ok {
29-
return nil, stringSliceString(ifaceSliceVal, andOrOr), nil
33+
return nil, stringSliceString(ifaceSliceVal, andOrOr, singleLine), nil
3034
}
3135

3236
return nil, fmt.Sprintf("%+v", val), nil
@@ -54,7 +58,7 @@ func maxStringLen(strings []string) int {
5458
return max
5559
}
5660

57-
func stringSliceString(values []interface{}, andOrOr string) string {
61+
func stringSliceString(values []interface{}, andOrOr string, singleLine bool) string {
5862
if len(values) == 0 {
5963
return ""
6064
}
@@ -69,7 +73,7 @@ func stringSliceString(values []interface{}, andOrOr string) string {
6973
}
7074

7175
whitespace := " "
72-
if maxStringLen(strs) > 15 || len(strs) > 3 {
76+
if !singleLine && (maxStringLen(strs) > 15 || len(strs) > 3) {
7377
whitespace = "\n"
7478
}
7579

0 commit comments

Comments
 (0)