Skip to content

Commit 9e049a0

Browse files
committed
feat(cdn): add distribution create cmd
1 parent 7e50687 commit 9e049a0

File tree

3 files changed

+412
-0
lines changed

3 files changed

+412
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/url"
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/projectname"
17+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/cdn/client"
18+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
19+
sdkUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
20+
"github.com/stackitcloud/stackit-sdk-go/services/cdn"
21+
)
22+
23+
const (
24+
regionsFlag = "regions"
25+
originURLFlag = "origin-url"
26+
)
27+
28+
type inputModel struct {
29+
*globalflags.GlobalFlagModel
30+
Regions []cdn.Region
31+
OriginURL string
32+
}
33+
34+
func NewCmd(params *params.CmdParams) *cobra.Command {
35+
cmd := &cobra.Command{
36+
Use: "create",
37+
Short: "Create a CDN distribution",
38+
Long: "Create a CDN distribution for a given originUrl in multiple regions.",
39+
Args: args.NoArgs,
40+
Example: examples.Build(
41+
examples.NewExample(
42+
`Create a distribution for regions EU and AF`,
43+
`$ stackit beta cdn distribution create --regions=EU,AF --origin-url=https://example.com`,
44+
),
45+
),
46+
RunE: func(cmd *cobra.Command, args []string) error {
47+
ctx := context.Background()
48+
model, err := parseInput(params.Printer, cmd, args)
49+
if err != nil {
50+
return err
51+
}
52+
53+
apiClient, err := client.ConfigureClient(params.Printer, params.CliVersion)
54+
if err != nil {
55+
return err
56+
}
57+
58+
projectLabel, err := projectname.GetProjectName(ctx, params.Printer, params.CliVersion, cmd)
59+
if err != nil {
60+
params.Printer.Debug(print.ErrorLevel, "get project name: %v", err)
61+
projectLabel = model.ProjectId
62+
}
63+
64+
if !model.AssumeYes {
65+
prompt := fmt.Sprintf("Are you sure you want to create a CDN distribution for project %q?", projectLabel)
66+
err = params.Printer.PromptForConfirmation(prompt)
67+
if err != nil {
68+
return err
69+
}
70+
}
71+
72+
req := buildRequest(ctx, model, apiClient)
73+
74+
resp, err := req.Execute()
75+
if err != nil {
76+
return fmt.Errorf("create CDN distribution: %w", err)
77+
}
78+
79+
return outputResult(params.Printer, model.OutputFormat, projectLabel, resp)
80+
},
81+
}
82+
configureFlags(cmd)
83+
return cmd
84+
}
85+
86+
func configureFlags(cmd *cobra.Command) {
87+
cmd.Flags().Var(flags.EnumSliceFlag(false, []string{}, sdkUtils.EnumSliceToStringSlice(cdn.AllowedRegionEnumValues)...), regionsFlag, fmt.Sprintf("Regions in which content should be cached, multiple of: %q", cdn.AllowedRegionEnumValues))
88+
cmd.Flags().String(originURLFlag, "", "The origin of the content that should be made available through the CDN. Note that the path and query parameters are ignored. Ports are allowed. If no protocol is provided, `https` is assumed. So `www.example.com:1234/somePath?q=123` is normalized to `https://www.example.com:1234`")
89+
err := flags.MarkFlagsRequired(cmd, regionsFlag, originURLFlag)
90+
cobra.CheckErr(err)
91+
}
92+
93+
func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) {
94+
globalFlags := globalflags.Parse(p, cmd)
95+
if globalFlags.ProjectId == "" {
96+
return nil, &errors.ProjectIdError{}
97+
}
98+
99+
regionStrings := flags.FlagToStringSliceValue(p, cmd, regionsFlag)
100+
regions := make([]cdn.Region, 0, len(regionStrings))
101+
for _, regionStr := range regionStrings {
102+
regions = append(regions, cdn.Region(regionStr))
103+
}
104+
105+
originUrlString := flags.FlagToStringValue(p, cmd, originURLFlag)
106+
_, err := url.Parse(originUrlString)
107+
if err != nil {
108+
return nil, fmt.Errorf("invalid originUrl: '%s' (%w)", originUrlString, err)
109+
}
110+
111+
model := inputModel{
112+
GlobalFlagModel: globalFlags,
113+
Regions: regions,
114+
OriginURL: originUrlString,
115+
}
116+
117+
return &model, nil
118+
}
119+
120+
func buildRequest(ctx context.Context, model *inputModel, apiClient *cdn.APIClient) cdn.ApiCreateDistributionRequest {
121+
req := apiClient.CreateDistribution(ctx, model.ProjectId)
122+
payload := cdn.NewCreateDistributionPayload(
123+
model.OriginURL,
124+
model.Regions,
125+
)
126+
return req.CreateDistributionPayload(*payload)
127+
}
128+
129+
func outputResult(p *print.Printer, outputFormat string, projectLabel string, resp *cdn.CreateDistributionResponse) error {
130+
if resp == nil {
131+
return fmt.Errorf("create distribution response is nil")
132+
}
133+
return p.OutputResult(outputFormat, resp, func() error {
134+
p.Outputf("Created CDN distribution for %q. Id: %s\n", projectLabel, utils.PtrString(resp.Distribution.Id))
135+
return nil
136+
})
137+
}

0 commit comments

Comments
 (0)