Skip to content

Commit 863828c

Browse files
committed
feat(cdn): add cdn client, config, list command
1 parent 9b86268 commit 863828c

File tree

11 files changed

+689
-0
lines changed

11 files changed

+689
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/stackitcloud/stackit-sdk-go/core v0.19.0
1919
github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1
2020
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0
21+
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.6.0
2122
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1
2223
github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0
2324
github.com/stackitcloud/stackit-sdk-go/services/iaas v1.2.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1 h1:DaJkEN/6l+AJEQ3Dr+
567567
github.com/stackitcloud/stackit-sdk-go/services/alb v0.7.1/go.mod h1:SzA+UsSNv4D9IvNT7hwYPewgAvUgj5WXIU2tZ0XaMBI=
568568
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo=
569569
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw=
570+
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.6.0 h1:Q+qIdejeMsYMkbtVoI9BpGlKGdSVFRBhH/zj44SP8TM=
571+
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.6.0/go.mod h1:YGadfhuy8yoseczTxF7vN4t9ES2WxGQr0Pug14ii7y4=
570572
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1 h1:CnhAMLql0MNmAeq4roQKN8OpSKX4FSgTU6Eu6detB4I=
571573
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1/go.mod h1:7Bx85knfNSBxulPdJUFuBePXNee3cO+sOTYnUG6M+iQ=
572574
github.com/stackitcloud/stackit-sdk-go/services/git v0.9.0 h1:zuoJnsLnjxdQcQbs7gUXYzrN0Ip5NXj+6LFBp1EO6cg=

internal/cmd/beta/cdn/cdn.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package cdn
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution"
6+
"github.com/stackitcloud/stackit-cli/internal/cmd/params"
7+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
9+
)
10+
11+
func NewCmd(params *params.CmdParams) *cobra.Command {
12+
cmd := &cobra.Command{
13+
Use: "cdn",
14+
Short: "Manage CDN resources",
15+
Long: "Manage the lifecycle of CDN resources.",
16+
Args: args.NoArgs,
17+
Run: utils.CmdHelp,
18+
}
19+
addSubcommands(cmd, params)
20+
return cmd
21+
}
22+
23+
func addSubcommands(cmd *cobra.Command, params *params.CmdParams) {
24+
cmd.AddCommand(distribution.NewCommand(params))
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package distribution
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/cdn/distribution/list"
6+
"github.com/stackitcloud/stackit-cli/internal/cmd/params"
7+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
8+
)
9+
10+
func NewCommand(params *params.CmdParams) *cobra.Command {
11+
cmd := &cobra.Command{
12+
Use: "distribution",
13+
Short: "Manage CDN distributions",
14+
Long: "Manage the lifecycle of CDN distributions.",
15+
Args: cobra.NoArgs,
16+
Run: utils.CmdHelp,
17+
}
18+
addSubcommands(cmd, params)
19+
return cmd
20+
}
21+
22+
func addSubcommands(cmd *cobra.Command, params *params.CmdParams) {
23+
cmd.AddCommand(list.NewCmd(params))
24+
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package list
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/spf13/cobra"
9+
"github.com/stackitcloud/stackit-cli/internal/cmd/params"
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/cdn/client"
17+
"github.com/stackitcloud/stackit-cli/internal/pkg/tables"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
19+
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
20+
)
21+
22+
type inputModel struct {
23+
*globalflags.GlobalFlagModel
24+
SortBy string
25+
}
26+
27+
const (
28+
sortByFlag = "sort-by"
29+
)
30+
31+
func NewCmd(params *params.CmdParams) *cobra.Command {
32+
cmd := &cobra.Command{
33+
Use: "list",
34+
Short: "List CDN distributions",
35+
Long: "List all CDN distributions in your account.",
36+
Args: args.NoArgs,
37+
Example: examples.Build(
38+
examples.NewExample(
39+
`List all CDN distributions`,
40+
`$ stackit beta dns distribution list`,
41+
),
42+
examples.NewExample(
43+
`List all CDN distributions sorted by id`,
44+
`$ stackit beta dns distribution list --sort-by=id`,
45+
),
46+
),
47+
RunE: func(cmd *cobra.Command, args []string) error {
48+
ctx := context.Background() // should this be cancellable?
49+
50+
model, err := parseInput(params.Printer, cmd, args)
51+
if err != nil {
52+
return err
53+
}
54+
55+
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
56+
if err != nil {
57+
return err
58+
}
59+
60+
distributions, err := fetchDistributions(ctx, model, apiClient)
61+
if err != nil {
62+
return fmt.Errorf("fetch distributions: %w", err)
63+
}
64+
65+
return outputResult(params.Printer, model.OutputFormat, distributions)
66+
},
67+
}
68+
69+
configureFlags(cmd)
70+
return cmd
71+
}
72+
73+
var sortByFlagOptions = []string{"id", "created", "updated", "origin-url", "status"}
74+
75+
func configureFlags(cmd *cobra.Command) {
76+
// same default as apiClient
77+
cmd.Flags().Var(flags.EnumFlag(false, "created", sortByFlagOptions...), sortByFlag, fmt.Sprintf("Sort entries by a specific field, one of %q", sortByFlagOptions))
78+
}
79+
80+
func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) {
81+
globalFlags := globalflags.Parse(p, cmd)
82+
if globalFlags.ProjectId == "" {
83+
return nil, &errors.ProjectIdError{}
84+
}
85+
86+
model := inputModel{
87+
GlobalFlagModel: globalFlags,
88+
SortBy: flags.FlagWithDefaultToStringValue(p, cmd, sortByFlag),
89+
}
90+
91+
p.DebugInputModel(model)
92+
return &model, nil
93+
}
94+
95+
func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient, nextPageID cdn.ListDistributionsResponseGetNextPageIdentifierAttributeType) cdn.ApiListDistributionsRequest {
96+
req := apiClient.ListDistributions(ctx, model.GlobalFlagModel.ProjectId)
97+
req = req.SortBy(toAPISortBy(model.SortBy))
98+
req = req.PageSize(100)
99+
if nextPageID != nil {
100+
req = req.PageIdentifier(*nextPageID)
101+
}
102+
return req
103+
}
104+
105+
func toAPISortBy(sortBy string) string {
106+
switch sortBy {
107+
case "id":
108+
return "id"
109+
case "created":
110+
return "createdAt"
111+
case "updated":
112+
return "updatedAt"
113+
case "origin-url":
114+
return "originUrl"
115+
case "status":
116+
return "status"
117+
default:
118+
panic("invalid sortBy value, programmer error")
119+
}
120+
}
121+
122+
func outputResult(p *print.Printer, outputFormat string, distributions []cdn.Distribution) error {
123+
if distributions == nil {
124+
distributions = make([]cdn.Distribution, 0) // otherwise prints null in json output
125+
}
126+
return p.OutputResult(outputFormat, distributions, func() error {
127+
if len(distributions) == 0 {
128+
p.Outputln("No CDN distributions found")
129+
return nil
130+
}
131+
132+
table := tables.NewTable()
133+
table.SetHeader("ID", "REGIONS", "STATUS")
134+
for i := range distributions {
135+
d := &distributions[i]
136+
regions := make([]string, 0, len(*d.Config.Regions))
137+
for _, r := range *d.Config.Regions {
138+
regions = append(regions, string(r))
139+
}
140+
joinedRegions := strings.Join(regions, ", ")
141+
table.AddRow(
142+
utils.PtrString(d.Id),
143+
joinedRegions,
144+
utils.PtrString(d.Status),
145+
)
146+
}
147+
err := table.Display(p)
148+
if err != nil {
149+
return fmt.Errorf("render table: %w", err)
150+
}
151+
return nil
152+
})
153+
}
154+
155+
func fetchDistributions(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) ([]cdn.Distribution, error) {
156+
var nextPageID cdn.ListDistributionsResponseGetNextPageIdentifierAttributeType
157+
var distributions []cdn.Distribution
158+
for {
159+
request := buildRequest(ctx, model, apiClient, nextPageID)
160+
response, err := request.Execute()
161+
if err != nil {
162+
return nil, fmt.Errorf("list distributions: %w", err)
163+
}
164+
nextPageID = response.NextPageIdentifier
165+
if response.Distributions != nil {
166+
distributions = append(distributions, *response.Distributions...)
167+
}
168+
if nextPageID == nil {
169+
break
170+
}
171+
}
172+
return distributions, nil
173+
}

0 commit comments

Comments
 (0)