Skip to content

Commit db5dfa3

Browse files
committed
feat(alb): list command
1 parent f589bb4 commit db5dfa3

File tree

9 files changed

+472
-0
lines changed

9 files changed

+472
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ require (
5252
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
5353
github.com/mattn/go-isatty v0.0.20 // indirect
5454
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
55+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 // indirect
5556
github.com/x448/float16 v0.8.4 // indirect
5657
)
5758

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
113113
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
114114
github.com/stackitcloud/stackit-sdk-go/core v0.16.2 h1:F8A4P/LLlQSbz0S0+G3m8rb3BUOK6EcR/CKx5UQY5jQ=
115115
github.com/stackitcloud/stackit-sdk-go/core v0.16.2/go.mod h1:8KIw3czdNJ9sdil9QQimxjR6vHjeINFrRv0iZ67wfn0=
116+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1 h1:7VOUNsnNBL2iQsZ3lJogNzKx4lrYEawDYllcXV1gEik=
117+
github.com/stackitcloud/stackit-sdk-go/services/alb v0.2.1/go.mod h1:J2/Jk+leR6AjBotd7USJJzX+AEIHH11yxnmx+6ciJEk=
116118
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1 h1:2lq6SG8qOgPOx2OIA5Bca8mwRSlect3Yljk57bXqd5I=
117119
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.6.1/go.mod h1:in9kC4GIBU5DpzXKFDL7RDl0fKyvN/RUIc7YbyWYEUA=
118120
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.1 h1:W5zQhg/nA2RVSkUtRjsGcJMdYlOicoE5gBGE9zMT9Eo=

internal/cmd/beta/alb/alb.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package alb
2+
3+
import (
4+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/list"
5+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
6+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
7+
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
9+
10+
"github.com/spf13/cobra"
11+
)
12+
13+
func NewCmd(p *print.Printer) *cobra.Command {
14+
cmd := &cobra.Command{
15+
Use: "alb",
16+
Short: "Manages application loadbalancers",
17+
Long: "Manage the lifecycle of application loadbalancers.",
18+
Args: args.NoArgs,
19+
Run: utils.CmdHelp,
20+
}
21+
addSubcommands(cmd, p)
22+
return cmd
23+
}
24+
25+
func addSubcommands(cmd *cobra.Command, p *print.Printer) {
26+
cmd.AddCommand(
27+
list.NewCmd(p),
28+
)
29+
}

internal/cmd/beta/alb/list/list.go

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package list
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/projectname"
17+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/tables"
19+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
20+
"github.com/stackitcloud/stackit-sdk-go/services/alb"
21+
)
22+
23+
type inputModel struct {
24+
*globalflags.GlobalFlagModel
25+
Limit *int64
26+
}
27+
28+
const (
29+
labelSelectorFlag = "label-selector"
30+
limitFlag = "limit"
31+
)
32+
33+
func NewCmd(p *print.Printer) *cobra.Command {
34+
cmd := &cobra.Command{
35+
Use: "list",
36+
Short: "Lists albs",
37+
Long: "Lists application load balancers.",
38+
Args: args.NoArgs,
39+
Example: examples.Build(
40+
examples.NewExample(
41+
`List all load balancers`,
42+
`$ stackit beta alb list`,
43+
),
44+
examples.NewExample(
45+
`List the first 10 application load balancers`,
46+
`$ stackit beta alb list --limit=10`,
47+
),
48+
),
49+
RunE: func(cmd *cobra.Command, _ []string) error {
50+
ctx := context.Background()
51+
model, err := parseInput(p, cmd)
52+
if err != nil {
53+
return err
54+
}
55+
56+
// Configure API client
57+
apiClient, err := client.ConfigureClient(p)
58+
if err != nil {
59+
return err
60+
}
61+
62+
projectLabel, err := projectname.GetProjectName(ctx, p, cmd)
63+
if err != nil {
64+
p.Debug(print.ErrorLevel, "get project name: %v", err)
65+
projectLabel = model.ProjectId
66+
} else if projectLabel == "" {
67+
projectLabel = model.ProjectId
68+
}
69+
70+
// Call API
71+
request := buildRequest(ctx, model, apiClient)
72+
73+
response, err := request.Execute()
74+
if err != nil {
75+
return fmt.Errorf("list load balancerse: %w", err)
76+
}
77+
78+
if items := response.LoadBalancers; items != nil && len(*items) == 0 {
79+
p.Info("No load balancers found for project %q", projectLabel)
80+
} else {
81+
if model.Limit != nil && len(*items) > int(*model.Limit) {
82+
*items = (*items)[:*model.Limit]
83+
}
84+
if err := outputResult(p, model.OutputFormat, *items); err != nil {
85+
return fmt.Errorf("output loadbalancers: %w", err)
86+
}
87+
}
88+
89+
return nil
90+
},
91+
}
92+
93+
configureFlags(cmd)
94+
return cmd
95+
}
96+
97+
func configureFlags(cmd *cobra.Command) {
98+
cmd.Flags().Int64(limitFlag, 0, "Limit the output to the first n elements")
99+
}
100+
101+
func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
102+
globalFlags := globalflags.Parse(p, cmd)
103+
if globalFlags.ProjectId == "" {
104+
return nil, &errors.ProjectIdError{}
105+
}
106+
107+
limit := flags.FlagToInt64Pointer(p, cmd, limitFlag)
108+
if limit != nil && *limit < 1 {
109+
return nil, &errors.FlagValidationError{
110+
Flag: limitFlag,
111+
Details: "must be greater than 0",
112+
}
113+
}
114+
115+
model := inputModel{
116+
GlobalFlagModel: globalFlags,
117+
Limit: limit,
118+
}
119+
120+
if p.IsVerbosityDebug() {
121+
modelStr, err := print.BuildDebugStrFromInputModel(model)
122+
if err != nil {
123+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
124+
} else {
125+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
126+
}
127+
}
128+
129+
return &model, nil
130+
}
131+
132+
func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiListLoadBalancersRequest {
133+
request := apiClient.ListLoadBalancers(ctx, model.ProjectId, model.Region)
134+
135+
return request
136+
}
137+
func outputResult(p *print.Printer, outputFormat string, items []alb.LoadBalancer) error {
138+
switch outputFormat {
139+
case print.JSONOutputFormat:
140+
details, err := json.MarshalIndent(items, "", " ")
141+
if err != nil {
142+
return fmt.Errorf("marshal loadbalancer list: %w", err)
143+
}
144+
p.Outputln(string(details))
145+
146+
return nil
147+
case print.YAMLOutputFormat:
148+
details, err := yaml.MarshalWithOptions(items, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
149+
if err != nil {
150+
return fmt.Errorf("marshal loadbalancer list: %w", err)
151+
}
152+
p.Outputln(string(details))
153+
154+
return nil
155+
default:
156+
table := tables.NewTable()
157+
table.SetHeader("NAME", "EXTERNAL ADDRESS", "REGION", "STATUS", "VERSION")
158+
for _, item := range items {
159+
table.AddRow(utils.PtrString(item.Name),
160+
utils.PtrString(item.ExternalAddress),
161+
utils.PtrString(item.Region),
162+
utils.PtrString(item.Status),
163+
utils.PtrString(item.Version),
164+
utils.PtrString(item.ExternalAddress),
165+
)
166+
}
167+
err := table.Display(p)
168+
if err != nil {
169+
return fmt.Errorf("render table: %w", err)
170+
}
171+
172+
return nil
173+
}
174+
}

0 commit comments

Comments
 (0)