Skip to content

Commit b54e73c

Browse files
committed
Add update command to network-area route
Support to update labels for a network-area route. Signed-off-by: Alexander Dahmen <[email protected]>
1 parent 747c0fd commit b54e73c

File tree

6 files changed

+494
-2
lines changed

6 files changed

+494
-2
lines changed

docs/stackit_beta_network-area_route.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ stackit beta network-area route [flags]
3333
* [stackit beta network-area route delete](./stackit_beta_network-area_route_delete.md) - Deletes a static route in a STACKIT Network Area (SNA)
3434
* [stackit beta network-area route describe](./stackit_beta_network-area_route_describe.md) - Shows details of a static route in a STACKIT Network Area (SNA)
3535
* [stackit beta network-area route list](./stackit_beta_network-area_route_list.md) - Lists all static routes in a STACKIT Network Area (SNA)
36+
* [stackit beta network-area route update](./stackit_beta_network-area_route_update.md) - Updates a static route in a STACKIT Network Area (SNA)
3637

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
## stackit beta network-area route update
2+
3+
Updates a static route in a STACKIT Network Area (SNA)
4+
5+
### Synopsis
6+
7+
Updates a static route in a STACKIT Network Area (SNA).
8+
This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release.
9+
10+
11+
```
12+
stackit beta network-area route update [flags]
13+
```
14+
15+
### Examples
16+
17+
```
18+
Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"
19+
$ stackit beta network-area route update xxx --label key=value,foo=bar --organization-id yyy --network-area-id zzz
20+
```
21+
22+
### Options
23+
24+
```
25+
-h, --help Help for "stackit beta network-area route update"
26+
--label stringToString Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels (default [])
27+
--network-area-id string STACKIT Network Area ID
28+
--organization-id string Organization ID
29+
```
30+
31+
### Options inherited from parent commands
32+
33+
```
34+
-y, --assume-yes If set, skips all confirmation prompts
35+
--async If set, runs the command asynchronously
36+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
37+
-p, --project-id string Project ID
38+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
39+
```
40+
41+
### SEE ALSO
42+
43+
* [stackit beta network-area route](./stackit_beta_network-area_route.md) - Provides functionality for static routes in STACKIT Network Areas
44+

internal/cmd/beta/network-area/route/describe/describe.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"strings"
78

89
"github.com/goccy/go-yaml"
910
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
@@ -134,9 +135,18 @@ func outputResult(p *print.Printer, outputFormat string, route *iaas.Route) erro
134135
table := tables.NewTable()
135136
table.AddRow("ID", *route.RouteId)
136137
table.AddSeparator()
137-
table.AddRow("Prefix", *route.Prefix)
138+
table.AddRow("PREFIX", *route.Prefix)
138139
table.AddSeparator()
139-
table.AddRow("Nexthop", *route.Nexthop)
140+
table.AddRow("NEXTHOP", *route.Nexthop)
141+
table.AddSeparator()
142+
if route.Labels != nil && len(*route.Labels) > 0 {
143+
labels := []string{}
144+
for key, value := range *route.Labels {
145+
labels = append(labels, fmt.Sprintf("%s: %s", key, value))
146+
}
147+
table.AddSeparator()
148+
table.AddRow("LABELS", strings.Join(labels, "\n"))
149+
}
140150

141151
err := table.Display(p)
142152
if err != nil {

internal/cmd/beta/network-area/route/routes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/delete"
66
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/describe"
77
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/list"
8+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/network-area/route/update"
89
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
910
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
1011
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
@@ -29,4 +30,5 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) {
2930
cmd.AddCommand(delete.NewCmd(p))
3031
cmd.AddCommand(describe.NewCmd(p))
3132
cmd.AddCommand(list.NewCmd(p))
33+
cmd.AddCommand(update.NewCmd(p))
3234
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package update
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/iaas/client"
17+
iaasUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/utils"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
19+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
20+
)
21+
22+
const (
23+
routeIdArg = "ROUTE_ID"
24+
25+
organizationIdFlag = "organization-id"
26+
networkAreaIdFlag = "network-area-id"
27+
28+
labelFlag = "labels"
29+
)
30+
31+
type inputModel struct {
32+
*globalflags.GlobalFlagModel
33+
OrganizationId *string
34+
NetworkAreaId *string
35+
RouteId string
36+
Labels *map[string]string
37+
}
38+
39+
func NewCmd(p *print.Printer) *cobra.Command {
40+
cmd := &cobra.Command{
41+
Use: "update",
42+
Short: "Updates a static route in a STACKIT Network Area (SNA)",
43+
Long: fmt.Sprintf("%s\n%s\n",
44+
"Updates a static route in a STACKIT Network Area (SNA).",
45+
"This command is currently asynchonous only due to limitations in the waiting functionality of the SDK. This will be updated in a future release.",
46+
),
47+
Args: args.SingleArg(routeIdArg, utils.ValidateUUID),
48+
Example: examples.Build(
49+
examples.NewExample(
50+
`Updates the label(s) of a static route with ID "xxx" in a STACKIT Network Area with ID "yyy" in organization with ID "zzz"`,
51+
"$ stackit beta network-area route update xxx --labels key=value,foo=bar --organization-id yyy --network-area-id zzz",
52+
),
53+
),
54+
RunE: func(cmd *cobra.Command, args []string) error {
55+
ctx := context.Background()
56+
model, err := parseInput(p, cmd, args)
57+
if err != nil {
58+
return err
59+
}
60+
61+
// Configure API client
62+
apiClient, err := client.ConfigureClient(p)
63+
if err != nil {
64+
return err
65+
}
66+
67+
// Get network area label
68+
networkAreaLabel, err := iaasUtils.GetNetworkAreaName(ctx, apiClient, *model.OrganizationId, *model.NetworkAreaId)
69+
if err != nil {
70+
p.Debug(print.ErrorLevel, "get network area name: %v", err)
71+
networkAreaLabel = *model.NetworkAreaId
72+
}
73+
74+
// Call API
75+
req := buildRequest(ctx, model, apiClient)
76+
resp, err := req.Execute()
77+
if err != nil {
78+
return fmt.Errorf("create static route: %w", err)
79+
}
80+
81+
return outputResult(p, model, networkAreaLabel, *resp)
82+
},
83+
}
84+
configureFlags(cmd)
85+
return cmd
86+
}
87+
88+
func configureFlags(cmd *cobra.Command) {
89+
cmd.Flags().Var(flags.UUIDFlag(), organizationIdFlag, "Organization ID")
90+
cmd.Flags().Var(flags.UUIDFlag(), networkAreaIdFlag, "STACKIT Network Area ID")
91+
cmd.Flags().StringToString(labelFlag, nil, "Labels are key-value string pairs which can be attached to a route. A label can be provided with the format key=value and the flag can be used multiple times to provide a list of labels")
92+
93+
err := flags.MarkFlagsRequired(cmd, organizationIdFlag, networkAreaIdFlag)
94+
cobra.CheckErr(err)
95+
}
96+
97+
func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inputModel, error) {
98+
routeId := inputArgs[0]
99+
globalFlags := globalflags.Parse(p, cmd)
100+
101+
labels := flags.FlagToStringToStringPointer(p, cmd, labelFlag)
102+
103+
if labels == nil {
104+
return nil, &errors.EmptyUpdateError{}
105+
}
106+
107+
model := inputModel{
108+
GlobalFlagModel: globalFlags,
109+
OrganizationId: flags.FlagToStringPointer(p, cmd, organizationIdFlag),
110+
NetworkAreaId: flags.FlagToStringPointer(p, cmd, networkAreaIdFlag),
111+
RouteId: routeId,
112+
Labels: labels,
113+
}
114+
115+
if p.IsVerbosityDebug() {
116+
modelStr, err := print.BuildDebugStrFromInputModel(model)
117+
if err != nil {
118+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
119+
} else {
120+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
121+
}
122+
}
123+
124+
return &model, nil
125+
}
126+
127+
func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APIClient) iaas.ApiUpdateNetworkAreaRouteRequest {
128+
req := apiClient.UpdateNetworkAreaRoute(ctx, *model.OrganizationId, *model.NetworkAreaId, model.RouteId)
129+
130+
// convert map[string]string to map[string]interface{}
131+
labelsMap := make(map[string]interface{})
132+
for k, v := range *model.Labels {
133+
labelsMap[k] = v
134+
}
135+
136+
payload := iaas.UpdateNetworkAreaRoutePayload{
137+
Labels: &labelsMap,
138+
}
139+
req = req.UpdateNetworkAreaRoutePayload(payload)
140+
141+
return req
142+
}
143+
144+
func outputResult(p *print.Printer, model *inputModel, networkAreaLabel string, route iaas.Route) error {
145+
switch model.OutputFormat {
146+
case print.JSONOutputFormat:
147+
details, err := json.MarshalIndent(route, "", " ")
148+
if err != nil {
149+
return fmt.Errorf("marshal static route: %w", err)
150+
}
151+
p.Outputln(string(details))
152+
153+
return nil
154+
case print.YAMLOutputFormat:
155+
details, err := yaml.MarshalWithOptions(route, yaml.IndentSequence(true))
156+
if err != nil {
157+
return fmt.Errorf("marshal static route: %w", err)
158+
}
159+
p.Outputln(string(details))
160+
161+
return nil
162+
default:
163+
p.Outputf("Updated static route for SNA %q.\nStatic route ID: %s\n", networkAreaLabel, *route.RouteId)
164+
return nil
165+
}
166+
}

0 commit comments

Comments
 (0)