Skip to content

Commit dd72209

Browse files
committed
feat(credentials): commands working
1 parent 7544571 commit dd72209

File tree

12 files changed

+1920
-0
lines changed

12 files changed

+1920
-0
lines changed

internal/cmd/beta/alb/alb.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package alb
22

33
import (
44
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/create"
5+
keypair "github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/credentials"
56
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/delete"
67
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/describe"
78
"github.com/stackitcloud/stackit-cli/internal/cmd/beta/alb/list"
@@ -34,6 +35,7 @@ func addSubcommands(cmd *cobra.Command, p *print.Printer) {
3435
template.NewCmd(p),
3536
create.NewCmd(p),
3637
update.NewCmd(p),
38+
keypair.NewCmd(p),
3739
describe.NewCmd(p),
3840
delete.NewCmd(p),
3941
pool.NewCmd(p),
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"os"
8+
9+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/alb/client"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
15+
"golang.org/x/term"
16+
17+
"github.com/goccy/go-yaml"
18+
"github.com/spf13/cobra"
19+
"github.com/stackitcloud/stackit-sdk-go/services/alb"
20+
)
21+
22+
const passwordEnv = "ALB_CREDENTIALS_PASSWORD"
23+
24+
const (
25+
usernameFlag = "username"
26+
displaynameFlag = "displayname"
27+
)
28+
29+
type inputModel struct {
30+
*globalflags.GlobalFlagModel
31+
Username *string
32+
Displayname *string
33+
Password *string
34+
}
35+
36+
func NewCmd(p *print.Printer) *cobra.Command {
37+
cmd := &cobra.Command{
38+
Use: "create",
39+
Short: "Creates a credential",
40+
Long: "Creates a credential.",
41+
Args: cobra.NoArgs,
42+
Example: examples.Build(
43+
examples.NewExample(
44+
`Create a new credential, the password is requested interactively or read from ENV variable `+passwordEnv,
45+
"$ stackit key-pair create --username some.user --displayname master-creds",
46+
),
47+
),
48+
RunE: func(cmd *cobra.Command, _ []string) error {
49+
ctx := context.Background()
50+
51+
password, err := readPassword()
52+
if err != nil {
53+
return err
54+
}
55+
model, err := parseInput(p, cmd, password)
56+
if err != nil {
57+
return err
58+
}
59+
60+
// Configure client
61+
apiClient, err := client.ConfigureClient(p)
62+
if err != nil {
63+
return err
64+
}
65+
66+
if !model.AssumeYes {
67+
prompt := "Are your sure you want to create a credential?"
68+
err = p.PromptForConfirmation(prompt)
69+
if err != nil {
70+
return err
71+
}
72+
}
73+
74+
// Call API
75+
req := buildRequest(ctx, model, apiClient)
76+
resp, err := req.Execute()
77+
if err != nil {
78+
return fmt.Errorf("create credential: %w", err)
79+
}
80+
81+
return outputResult(p, model.GlobalFlagModel.OutputFormat, resp)
82+
},
83+
}
84+
configureFlags(cmd)
85+
return cmd
86+
}
87+
88+
func configureFlags(cmd *cobra.Command) {
89+
cmd.Flags().StringP(usernameFlag, "u", "", "the username for the credentials")
90+
cmd.Flags().StringP(displaynameFlag, "d", "", "the displayname for the credentials")
91+
92+
cobra.CheckErr(cmd.MarkFlagRequired(usernameFlag))
93+
cobra.CheckErr(cmd.MarkFlagRequired(displaynameFlag))
94+
}
95+
96+
func readPassword() (string, error) {
97+
if password, found := os.LookupEnv(passwordEnv); found {
98+
return password, nil
99+
}
100+
101+
fmt.Printf("please provide the password: ")
102+
password, err := term.ReadPassword(int(os.Stdout.Fd()))
103+
if err != nil {
104+
return "", fmt.Errorf("cannot read password: %w", err)
105+
}
106+
fmt.Println()
107+
fmt.Printf("please confirm the password: ")
108+
confirmation, err := term.ReadPassword(int(os.Stdout.Fd()))
109+
if err != nil {
110+
return "", fmt.Errorf("cannot read password: %w", err)
111+
}
112+
fmt.Println()
113+
if string(password) != string(confirmation) {
114+
return "", fmt.Errorf("the password and the confirmation do not match")
115+
}
116+
117+
return string(password), nil
118+
}
119+
120+
func parseInput(p *print.Printer, cmd *cobra.Command, password string) (*inputModel, error) {
121+
globalFlags := globalflags.Parse(p, cmd)
122+
123+
model := inputModel{
124+
GlobalFlagModel: globalFlags,
125+
Username: flags.FlagToStringPointer(p, cmd, usernameFlag),
126+
Displayname: flags.FlagToStringPointer(p, cmd, displaynameFlag),
127+
Password: &password,
128+
}
129+
130+
if p.IsVerbosityDebug() {
131+
modelStr, err := print.BuildDebugStrFromInputModel(model)
132+
if err != nil {
133+
p.Debug(print.ErrorLevel, "convert model to string fo debugging: %v", err)
134+
} else {
135+
p.Debug(print.DebugLevel, "parsed input values: %s", modelStr)
136+
}
137+
}
138+
139+
return &model, nil
140+
}
141+
142+
func buildRequest(ctx context.Context, model *inputModel, apiClient *alb.APIClient) alb.ApiCreateCredentialsRequest {
143+
req := apiClient.CreateCredentials(ctx, model.ProjectId, model.Region)
144+
payload := alb.CreateCredentialsPayload{
145+
DisplayName: model.Displayname,
146+
Password: model.Password,
147+
Username: model.Username,
148+
}
149+
return req.CreateCredentialsPayload(payload)
150+
}
151+
152+
func outputResult(p *print.Printer, outputFormat string, item *alb.CreateCredentialsResponse) error {
153+
if item == nil {
154+
return fmt.Errorf("no credential found")
155+
}
156+
157+
switch outputFormat {
158+
case print.JSONOutputFormat:
159+
details, err := json.MarshalIndent(item, "", " ")
160+
if err != nil {
161+
return fmt.Errorf("marshal credential: %w", err)
162+
}
163+
p.Outputln(string(details))
164+
case print.YAMLOutputFormat:
165+
details, err := yaml.MarshalWithOptions(item, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
166+
if err != nil {
167+
return fmt.Errorf("marshal credential: %w", err)
168+
}
169+
p.Outputln(string(details))
170+
default:
171+
p.Outputf("Created credential %q",
172+
utils.PtrString(item.Credential),
173+
)
174+
}
175+
return nil
176+
}

0 commit comments

Comments
 (0)