Skip to content

Commit 14481e4

Browse files
h3adexBenjosh95
andauthored
feat: provide functionality to list public ip-ranges (#993)
Co-authored-by: Benjosh95 <benjamin.fuertsch@inovex.de>
1 parent edf55a4 commit 14481e4

File tree

9 files changed

+524
-0
lines changed

9 files changed

+524
-0
lines changed

docs/stackit_public-ip.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ stackit public-ip [flags]
3636
* [stackit public-ip describe](./stackit_public-ip_describe.md) - Shows details of a Public IP
3737
* [stackit public-ip disassociate](./stackit_public-ip_disassociate.md) - Disassociates a Public IP from a network interface or a virtual IP
3838
* [stackit public-ip list](./stackit_public-ip_list.md) - Lists all Public IPs of a project
39+
* [stackit public-ip ranges](./stackit_public-ip_ranges.md) - Provides functionality for STACKIT public-ip ranges
3940
* [stackit public-ip update](./stackit_public-ip_update.md) - Updates a Public IP
4041

docs/stackit_public-ip_ranges.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## stackit public-ip ranges
2+
3+
Provides functionality for STACKIT public-ip ranges
4+
5+
### Synopsis
6+
7+
Provides functionality for STACKIT public-ip ranges
8+
9+
```
10+
stackit public-ip ranges [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help Help for "stackit public-ip ranges"
17+
```
18+
19+
### Options inherited from parent commands
20+
21+
```
22+
-y, --assume-yes If set, skips all confirmation prompts
23+
--async If set, runs the command asynchronously
24+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
25+
-p, --project-id string Project ID
26+
--region string Target region for region-specific requests
27+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
28+
```
29+
30+
### SEE ALSO
31+
32+
* [stackit public-ip](./stackit_public-ip.md) - Provides functionality for public IPs
33+
* [stackit public-ip ranges list](./stackit_public-ip_ranges_list.md) - Lists all STACKIT public-ip ranges
34+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## stackit public-ip ranges list
2+
3+
Lists all STACKIT public-ip ranges
4+
5+
### Synopsis
6+
7+
Lists all STACKIT public-ip ranges.
8+
9+
```
10+
stackit public-ip ranges list [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Lists all STACKIT public-ip ranges
17+
$ stackit public-ip ranges list
18+
19+
Lists all STACKIT public-ip ranges, piping to a tool like fzf for interactive selection
20+
$ stackit public-ip ranges list -o pretty | fzf
21+
22+
Lists up to 10 STACKIT public-ip ranges
23+
$ stackit public-ip ranges list --limit 10
24+
```
25+
26+
### Options
27+
28+
```
29+
-h, --help Help for "stackit public-ip ranges list"
30+
--limit int Maximum number of entries to list
31+
```
32+
33+
### Options inherited from parent commands
34+
35+
```
36+
-y, --assume-yes If set, skips all confirmation prompts
37+
--async If set, runs the command asynchronously
38+
-o, --output-format string Output format, one of ["json" "pretty" "none" "yaml"]
39+
-p, --project-id string Project ID
40+
--region string Target region for region-specific requests
41+
--verbosity string Verbosity of the CLI, one of ["debug" "info" "warning" "error"] (default "info")
42+
```
43+
44+
### SEE ALSO
45+
46+
* [stackit public-ip ranges](./stackit_public-ip_ranges.md) - Provides functionality for STACKIT public-ip ranges
47+

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/describe"
99
"github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/disassociate"
1010
"github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/list"
11+
"github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/ranges"
1112
"github.com/stackitcloud/stackit-cli/internal/cmd/public-ip/update"
1213
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
1314
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
@@ -35,4 +36,5 @@ func addSubcommands(cmd *cobra.Command, params *params.CmdParams) {
3536
cmd.AddCommand(update.NewCmd(params))
3637
cmd.AddCommand(associate.NewCmd(params))
3738
cmd.AddCommand(disassociate.NewCmd(params))
39+
cmd.AddCommand(ranges.NewCmd(params))
3840
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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/cmd/params"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
16+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
17+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/iaas/client"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
19+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
20+
)
21+
22+
const (
23+
limitFlag = "limit"
24+
)
25+
26+
type inputModel struct {
27+
*globalflags.GlobalFlagModel
28+
Limit *int64
29+
}
30+
31+
func NewCmd(params *params.CmdParams) *cobra.Command {
32+
cmd := &cobra.Command{
33+
Use: "list",
34+
Short: "Lists all STACKIT public-ip ranges",
35+
Long: "Lists all STACKIT public-ip ranges.",
36+
Args: args.NoArgs,
37+
Example: examples.Build(
38+
examples.NewExample(
39+
`Lists all STACKIT public-ip ranges`,
40+
"$ stackit public-ip ranges list",
41+
),
42+
examples.NewExample(
43+
`Lists all STACKIT public-ip ranges, piping to a tool like fzf for interactive selection`,
44+
"$ stackit public-ip ranges list -o pretty | fzf",
45+
),
46+
examples.NewExample(
47+
`Lists up to 10 STACKIT public-ip ranges`,
48+
"$ stackit public-ip ranges list --limit 10",
49+
),
50+
),
51+
RunE: func(cmd *cobra.Command, _ []string) error {
52+
ctx := context.Background()
53+
model, err := parseInput(params.Printer, cmd)
54+
if err != nil {
55+
return err
56+
}
57+
58+
// Configure API client
59+
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
60+
if err != nil {
61+
return err
62+
}
63+
64+
// Call API
65+
req := apiClient.ListPublicIPRanges(ctx)
66+
resp, err := req.Execute()
67+
if err != nil {
68+
return fmt.Errorf("list public IP ranges: %w", err)
69+
}
70+
publicIpRanges := utils.GetSliceFromPointer(resp.Items)
71+
72+
// Truncate output
73+
if model.Limit != nil && len(publicIpRanges) > int(*model.Limit) {
74+
publicIpRanges = publicIpRanges[:*model.Limit]
75+
}
76+
77+
return outputResult(params.Printer, model.OutputFormat, publicIpRanges)
78+
},
79+
}
80+
81+
configureFlags(cmd)
82+
return cmd
83+
}
84+
85+
func configureFlags(cmd *cobra.Command) {
86+
cmd.Flags().Int64(limitFlag, 0, "Maximum number of entries to list")
87+
}
88+
89+
func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
90+
globalFlags := globalflags.Parse(p, cmd)
91+
92+
limit := flags.FlagToInt64Pointer(p, cmd, limitFlag)
93+
if limit != nil && *limit < 1 {
94+
return nil, &errors.FlagValidationError{
95+
Flag: limitFlag,
96+
Details: "must be greater than 0",
97+
}
98+
}
99+
100+
model := inputModel{
101+
GlobalFlagModel: globalFlags,
102+
Limit: limit,
103+
}
104+
105+
if p.IsVerbosityDebug() {
106+
modelStr, err := print.BuildDebugStrFromInputModel(model)
107+
if err != nil {
108+
p.Debug(print.ErrorLevel, "convert model to string for debugging: %v", err)
109+
} else {
110+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
111+
}
112+
}
113+
114+
return &model, nil
115+
}
116+
117+
func outputResult(p *print.Printer, outputFormat string, publicIpRanges []iaas.PublicNetwork) error {
118+
switch outputFormat {
119+
case print.JSONOutputFormat:
120+
details, err := json.MarshalIndent(publicIpRanges, "", " ")
121+
if err != nil {
122+
return fmt.Errorf("marshal public IP ranges: %w", err)
123+
}
124+
p.Outputln(string(details))
125+
126+
return nil
127+
case print.YAMLOutputFormat:
128+
details, err := yaml.MarshalWithOptions(publicIpRanges, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
129+
if err != nil {
130+
return fmt.Errorf("marshal public IP ranges: %w", err)
131+
}
132+
p.Outputln(string(details))
133+
134+
return nil
135+
default:
136+
if len(publicIpRanges) == 0 {
137+
p.Outputln("No public IP ranges found")
138+
return nil
139+
}
140+
141+
for _, item := range publicIpRanges {
142+
if item.Cidr != nil && *item.Cidr != "" {
143+
p.Outputln(*item.Cidr)
144+
}
145+
}
146+
147+
return nil
148+
}
149+
}

0 commit comments

Comments
 (0)