Skip to content

Commit a12943c

Browse files
committed
add tests, limit flag, renaming
1 parent c5c7637 commit a12943c

File tree

3 files changed

+120
-45
lines changed

3 files changed

+120
-45
lines changed

internal/cmd/public-ip/ranges/list/list.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@ import (
1010
"github.com/spf13/cobra"
1111
"github.com/stackitcloud/stackit-cli/internal/cmd/params"
1212
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
1314
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
1416
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
1517
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
1618
"github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client"
1719
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
1820
)
1921

22+
const (
23+
limitFlag = "limit"
24+
)
25+
2026
type inputModel struct {
2127
*globalflags.GlobalFlagModel
28+
Limit *int64
2229
}
2330

2431
func NewCmd(params *params.CmdParams) *cobra.Command {
@@ -36,6 +43,10 @@ func NewCmd(params *params.CmdParams) *cobra.Command {
3643
`Lists all STACKIT public-ip ranges, piping to a tool like fzf for interactive selection`,
3744
"$ stackit public-ip ranges list -o pretty | fzf",
3845
),
46+
examples.NewExample(
47+
`Lists up to 10 STACKIT public-ip ranges`,
48+
"$ stackit public-ip ranges list --limit 10",
49+
),
3950
),
4051
RunE: func(cmd *cobra.Command, _ []string) error {
4152
ctx := context.Background()
@@ -55,24 +66,48 @@ func NewCmd(params *params.CmdParams) *cobra.Command {
5566
resp, err := req.Execute()
5667

5768
if err != nil {
58-
return fmt.Errorf("list public ip ranges s: %w", err)
69+
return fmt.Errorf("list public IP ranges: %w", err)
5970
}
6071

6172
if resp.Items == nil || len(*resp.Items) == 0 {
6273
params.Printer.Info("No public IP ranges found\n")
6374
return nil
6475
}
6576

66-
return outputResult(params.Printer, model.OutputFormat, *resp)
77+
publicIpRanges := *resp.Items
78+
79+
// Truncate output
80+
if model.Limit != nil && len(publicIpRanges) > int(*model.Limit) {
81+
publicIpRanges = publicIpRanges[:*model.Limit]
82+
}
83+
84+
return outputResult(params.Printer, model.OutputFormat, publicIpRanges)
6785
},
6886
}
87+
88+
configureFlags(cmd)
6989
return cmd
7090
}
7191

92+
func configureFlags(cmd *cobra.Command) {
93+
cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list")
94+
}
95+
7296
func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
7397
globalFlags := globalflags.Parse(p, cmd)
7498

75-
model := inputModel{GlobalFlagModel: globalFlags}
99+
limit := flags.FlagToInt64Pointer(p, cmd, limitFlag)
100+
if limit != nil && *limit < 1 {
101+
return nil, &errors.FlagValidationError{
102+
Flag: limitFlag,
103+
Details: "must be greater than 0",
104+
}
105+
}
106+
107+
model := inputModel{
108+
GlobalFlagModel: globalFlags,
109+
Limit: limit,
110+
}
76111

77112
if p.IsVerbosityDebug() {
78113
modelStr, err := print.BuildDebugStrFromInputModel(model)
@@ -86,32 +121,32 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
86121
return &model, nil
87122
}
88123

89-
func outputResult(p *print.Printer, outputFormat string, networkListResponse iaas.PublicNetworkListResponse) error {
124+
func outputResult(p *print.Printer, outputFormat string, publicIpRanges []iaas.PublicNetwork) error {
90125
switch outputFormat {
91126
case print.JSONOutputFormat:
92-
details, err := json.MarshalIndent(networkListResponse, "", " ")
127+
details, err := json.MarshalIndent(publicIpRanges, "", " ")
93128
if err != nil {
94-
return fmt.Errorf("marshal public IP: %w", err)
129+
return fmt.Errorf("marshal public IP ranges: %w", err)
95130
}
96131
p.Outputln(string(details))
97132

98133
return nil
99134
case print.YAMLOutputFormat:
100-
details, err := yaml.MarshalWithOptions(networkListResponse, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
135+
details, err := yaml.MarshalWithOptions(publicIpRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
101136
if err != nil {
102-
return fmt.Errorf("marshal public IP: %w", err)
137+
return fmt.Errorf("marshal public IP ranges: %w", err)
103138
}
104139
p.Outputln(string(details))
105140

106141
return nil
107142
default:
108-
var publicIps []string
109-
for _, item := range *networkListResponse.Items {
143+
var cidrs []string
144+
for _, item := range publicIpRanges {
110145
if item.Cidr != nil && *item.Cidr != "" {
111-
publicIps = append(publicIps, *item.Cidr)
146+
cidrs = append(cidrs, *item.Cidr)
112147
}
113148
}
114-
p.Outputln(strings.Join(publicIps, "\n"))
149+
p.Outputln(strings.Join(cidrs, "\n"))
115150

116151
return nil
117152
}

internal/cmd/public-ip/ranges/list/list_test.go

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,45 @@ func TestParseInput(t *testing.T) {
4343
},
4444
isValid: true,
4545
},
46+
{
47+
description: "valid input with limit",
48+
globalFlags: map[string]string{
49+
"limit": "10",
50+
},
51+
expectedModel: &inputModel{
52+
GlobalFlagModel: &globalflags.GlobalFlagModel{
53+
Verbosity: globalflags.InfoVerbosity,
54+
},
55+
Limit: utils.Ptr(int64(10)),
56+
},
57+
isValid: true,
58+
},
59+
{
60+
description: "valid input without limit",
61+
globalFlags: map[string]string{},
62+
expectedModel: &inputModel{
63+
GlobalFlagModel: &globalflags.GlobalFlagModel{
64+
Verbosity: globalflags.InfoVerbosity,
65+
},
66+
},
67+
isValid: true,
68+
},
69+
{
70+
description: "invalid limit (zero)",
71+
globalFlags: map[string]string{
72+
"limit": "0",
73+
},
74+
expectedModel: nil,
75+
isValid: false,
76+
},
77+
{
78+
description: "invalid limit (negative)",
79+
globalFlags: map[string]string{
80+
"limit": "-1",
81+
},
82+
expectedModel: nil,
83+
isValid: false,
84+
},
4685
}
4786

4887
for _, tt := range tests {
@@ -78,80 +117,81 @@ func TestOutputResult(t *testing.T) {
78117
tests := []struct {
79118
name string
80119
outputFormat string
81-
networkList iaas.PublicNetworkListResponse
120+
publicIpRanges []iaas.PublicNetwork
82121
expectedOutput string
83122
wantErr bool
84123
}{
85124
{
86125
name: "JSON output single",
87126
outputFormat: "json",
88-
networkList: iaas.PublicNetworkListResponse{
89-
Items: &[]iaas.PublicNetwork{
90-
{Cidr: utils.Ptr("192.168.0.0/24")},
91-
},
127+
publicIpRanges: []iaas.PublicNetwork{
128+
{Cidr: utils.Ptr("192.168.0.0/24")},
92129
},
93130
wantErr: false,
94131
},
95132
{
96133
name: "JSON output multiple",
97134
outputFormat: "json",
98-
networkList: iaas.PublicNetworkListResponse{
99-
Items: &[]iaas.PublicNetwork{
100-
{Cidr: utils.Ptr("192.168.0.0/24")},
101-
{Cidr: utils.Ptr("192.167.0.0/24")},
102-
},
135+
publicIpRanges: []iaas.PublicNetwork{
136+
{Cidr: utils.Ptr("192.168.0.0/24")},
137+
{Cidr: utils.Ptr("192.167.0.0/24")},
103138
},
104139
wantErr: false,
105140
},
106141
{
107142
name: "YAML output single",
108143
outputFormat: "yaml",
109-
networkList: iaas.PublicNetworkListResponse{
110-
Items: &[]iaas.PublicNetwork{
111-
{Cidr: utils.Ptr("192.168.0.0/24")},
112-
},
144+
publicIpRanges: []iaas.PublicNetwork{
145+
{Cidr: utils.Ptr("192.168.0.0/24")},
113146
},
114147
wantErr: false,
115148
},
116149
{
117150
name: "YAML output multiple",
118151
outputFormat: "yaml",
119-
networkList: iaas.PublicNetworkListResponse{
120-
Items: &[]iaas.PublicNetwork{
121-
{Cidr: utils.Ptr("192.168.0.0/24")},
122-
{Cidr: utils.Ptr("192.167.0.0/24")},
123-
},
152+
publicIpRanges: []iaas.PublicNetwork{
153+
{Cidr: utils.Ptr("192.168.0.0/24")},
154+
{Cidr: utils.Ptr("192.167.0.0/24")},
124155
},
125156
wantErr: false,
126157
},
127158
{
128159
name: "pretty output single",
129160
outputFormat: "pretty",
130-
networkList: iaas.PublicNetworkListResponse{
131-
Items: &[]iaas.PublicNetwork{
132-
{Cidr: utils.Ptr("192.168.0.0/24")},
133-
},
161+
publicIpRanges: []iaas.PublicNetwork{
162+
{Cidr: utils.Ptr("192.168.0.0/24")},
134163
},
135164
wantErr: false,
136165
},
137166
{
138167
name: "pretty output multiple",
139168
outputFormat: "pretty",
140-
networkList: iaas.PublicNetworkListResponse{
141-
Items: &[]iaas.PublicNetwork{
142-
{Cidr: utils.Ptr("192.168.0.0/24")},
143-
{Cidr: utils.Ptr("192.167.0.0/24")},
144-
},
169+
publicIpRanges: []iaas.PublicNetwork{
170+
{Cidr: utils.Ptr("192.168.0.0/24")},
171+
{Cidr: utils.Ptr("192.167.0.0/24")},
145172
},
146173
wantErr: false,
147174
},
148175
{
149176
name: "default output",
150177
outputFormat: "",
151-
networkList: iaas.PublicNetworkListResponse{
152-
Items: &[]iaas.PublicNetwork{
153-
{Cidr: utils.Ptr("192.168.0.0/24")},
154-
},
178+
publicIpRanges: []iaas.PublicNetwork{
179+
{Cidr: utils.Ptr("192.168.0.0/24")},
180+
},
181+
wantErr: false,
182+
},
183+
{
184+
name: "empty list",
185+
outputFormat: "json",
186+
publicIpRanges: []iaas.PublicNetwork{},
187+
wantErr: false,
188+
},
189+
{
190+
name: "nil CIDR",
191+
outputFormat: "pretty",
192+
publicIpRanges: []iaas.PublicNetwork{
193+
{Cidr: nil},
194+
{Cidr: utils.Ptr("192.168.0.0/24")},
155195
},
156196
wantErr: false,
157197
},
@@ -161,7 +201,7 @@ func TestOutputResult(t *testing.T) {
161201
t.Run(tt.name, func(t *testing.T) {
162202
p := print.NewPrinter()
163203
p.Cmd = NewCmd(&params.CmdParams{Printer: p})
164-
err := outputResult(p, tt.outputFormat, tt.networkList)
204+
err := outputResult(p, tt.outputFormat, tt.publicIpRanges)
165205
if (err != nil) != tt.wantErr {
166206
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
167207
}
File renamed without changes.

0 commit comments

Comments
 (0)