Skip to content

Commit 5bcdbda

Browse files
committed
add tests for key-pair commands:
- create - delete - describe - list - update
1 parent 1a0ae0b commit 5bcdbda

File tree

5 files changed

+932
-0
lines changed

5 files changed

+932
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"os"
6+
"testing"
7+
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
9+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
11+
12+
"github.com/google/go-cmp/cmp"
13+
"github.com/google/go-cmp/cmp/cmpopts"
14+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
15+
)
16+
17+
type testCtxKey struct{}
18+
19+
var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo")
20+
var testClient = &iaas.APIClient{}
21+
22+
var testPublicKey = "ssh-rsa <key>"
23+
var testKeypairName = "foobar_key"
24+
25+
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
26+
flagValues := map[string]string{
27+
publicKeyFlag: testPublicKey,
28+
labelFlag: "foo=bar",
29+
nameFlag: testKeypairName,
30+
}
31+
for _, mod := range mods {
32+
mod(flagValues)
33+
}
34+
return flagValues
35+
}
36+
37+
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
38+
model := &inputModel{
39+
GlobalFlagModel: &globalflags.GlobalFlagModel{
40+
Verbosity: globalflags.VerbosityDefault,
41+
},
42+
Labels: utils.Ptr(map[string]string{
43+
"foo": "bar",
44+
}),
45+
PublicKey: utils.Ptr(testPublicKey),
46+
Name: utils.Ptr(testKeypairName),
47+
}
48+
for _, mod := range mods {
49+
mod(model)
50+
}
51+
return model
52+
}
53+
54+
func fixtureRequest(mods ...func(request *iaas.ApiCreateKeyPairRequest)) iaas.ApiCreateKeyPairRequest {
55+
request := testClient.CreateKeyPair(testCtx)
56+
request = request.CreateKeyPairPayload(fixturePayload())
57+
for _, mod := range mods {
58+
mod(&request)
59+
}
60+
return request
61+
}
62+
63+
func fixturePayload(mods ...func(payload *iaas.CreateKeyPairPayload)) iaas.CreateKeyPairPayload {
64+
payload := iaas.CreateKeyPairPayload{
65+
Labels: utils.Ptr(map[string]interface{}{
66+
"foo": "bar",
67+
}),
68+
PublicKey: utils.Ptr(testPublicKey),
69+
Name: utils.Ptr(testKeypairName),
70+
}
71+
for _, mod := range mods {
72+
mod(&payload)
73+
}
74+
return payload
75+
}
76+
77+
func TestParseInput(t *testing.T) {
78+
tests := []struct {
79+
description string
80+
flagValues map[string]string
81+
isValid bool
82+
expectedModel *inputModel
83+
}{
84+
{
85+
description: "base",
86+
flagValues: fixtureFlagValues(),
87+
isValid: true,
88+
expectedModel: fixtureInputModel(),
89+
},
90+
{
91+
description: "required only",
92+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
93+
delete(flagValues, nameFlag)
94+
delete(flagValues, labelFlag)
95+
}),
96+
isValid: true,
97+
expectedModel: fixtureInputModel(func(model *inputModel) {
98+
model.Name = nil
99+
model.Labels = nil
100+
}),
101+
},
102+
{
103+
description: "read public key from file",
104+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
105+
flagValues[publicKeyFlag] = "@./create_test.go"
106+
}),
107+
isValid: true,
108+
expectedModel: fixtureInputModel(func(model *inputModel) {
109+
file, err := os.ReadFile("./create_test.go")
110+
if err != nil {
111+
t.Fatal("could not create expected Model", err)
112+
}
113+
model.PublicKey = utils.Ptr(string(file))
114+
}),
115+
},
116+
{
117+
description: "no values",
118+
flagValues: map[string]string{},
119+
isValid: false,
120+
},
121+
}
122+
123+
for _, tt := range tests {
124+
t.Run(tt.description, func(t *testing.T) {
125+
p := print.NewPrinter()
126+
cmd := NewCmd(p)
127+
err := globalflags.Configure(cmd.Flags())
128+
if err != nil {
129+
t.Fatalf("configure global flags: %v", err)
130+
}
131+
132+
for flag, value := range tt.flagValues {
133+
err = cmd.Flags().Set(flag, value)
134+
if err != nil {
135+
if !tt.isValid {
136+
return
137+
}
138+
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
139+
}
140+
}
141+
142+
err = cmd.ValidateRequiredFlags()
143+
if err != nil {
144+
if !tt.isValid {
145+
return
146+
}
147+
t.Fatalf("error validating flags: %v", err)
148+
}
149+
150+
model, err := parseInput(p, cmd)
151+
if err != nil {
152+
if !tt.isValid {
153+
return
154+
}
155+
t.Fatalf("error parsing flags: %v", err)
156+
}
157+
158+
if !tt.isValid {
159+
t.Fatalf("did not fail on invalid input")
160+
}
161+
diff := cmp.Diff(model, tt.expectedModel)
162+
if diff != "" {
163+
t.Fatalf("Data does not match: %s", diff)
164+
}
165+
})
166+
}
167+
}
168+
169+
func TestBuildRequest(t *testing.T) {
170+
tests := []struct {
171+
description string
172+
model *inputModel
173+
expectedRequest iaas.ApiCreateKeyPairRequest
174+
}{
175+
{
176+
description: "base",
177+
model: fixtureInputModel(),
178+
expectedRequest: fixtureRequest(),
179+
},
180+
}
181+
182+
for _, tt := range tests {
183+
t.Run(tt.description, func(t *testing.T) {
184+
request := buildRequest(testCtx, tt.model, testClient)
185+
186+
diff := cmp.Diff(request, tt.expectedRequest,
187+
cmp.AllowUnexported(tt.expectedRequest),
188+
cmpopts.EquateComparable(testCtx),
189+
cmp.AllowUnexported(iaas.NullableString{}),
190+
)
191+
if diff != "" {
192+
t.Fatalf("Data does not match: %s", diff)
193+
}
194+
})
195+
}
196+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package delete
2+
3+
import (
4+
"context"
5+
"github.com/google/go-cmp/cmp"
6+
"github.com/google/go-cmp/cmp/cmpopts"
7+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
9+
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
10+
"testing"
11+
)
12+
13+
type testCtxKey struct{}
14+
15+
var testCtx = context.WithValue(context.Background(), testCtxKey{}, "test")
16+
var testClient = &iaas.APIClient{}
17+
var testKeypairName = "keypair-name"
18+
19+
func fixtureArgValues(mods ...func(argValues []string)) []string {
20+
argValues := []string{
21+
testKeypairName,
22+
}
23+
for _, mod := range mods {
24+
mod(argValues)
25+
}
26+
return argValues
27+
}
28+
29+
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
30+
flagValues := map[string]string{}
31+
for _, mod := range mods {
32+
mod(flagValues)
33+
}
34+
return flagValues
35+
}
36+
37+
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
38+
model := &inputModel{
39+
GlobalFlagModel: &globalflags.GlobalFlagModel{
40+
Verbosity: globalflags.VerbosityDefault,
41+
},
42+
KeypairName: testKeypairName,
43+
}
44+
for _, mod := range mods {
45+
mod(model)
46+
}
47+
return model
48+
}
49+
50+
func fixtureRequest(mods ...func(request *iaas.ApiDeleteKeyPairRequest)) iaas.ApiDeleteKeyPairRequest {
51+
request := testClient.DeleteKeyPair(testCtx, testKeypairName)
52+
for _, mod := range mods {
53+
mod(&request)
54+
}
55+
return request
56+
}
57+
58+
func TestParseInput(t *testing.T) {
59+
tests := []struct {
60+
description string
61+
argValues []string
62+
flagValues map[string]string
63+
isValid bool
64+
expectedModel *inputModel
65+
}{
66+
{
67+
description: "base",
68+
argValues: fixtureArgValues(),
69+
flagValues: fixtureFlagValues(),
70+
isValid: true,
71+
expectedModel: fixtureInputModel(),
72+
},
73+
{
74+
description: "no values",
75+
argValues: []string{},
76+
flagValues: map[string]string{},
77+
isValid: false,
78+
},
79+
{
80+
description: "no args",
81+
argValues: []string{},
82+
flagValues: fixtureFlagValues(),
83+
isValid: false,
84+
},
85+
{
86+
description: "no flags",
87+
argValues: fixtureArgValues(),
88+
flagValues: map[string]string{},
89+
isValid: true,
90+
expectedModel: fixtureInputModel(),
91+
},
92+
}
93+
94+
for _, tt := range tests {
95+
t.Run(tt.description, func(t *testing.T) {
96+
p := print.NewPrinter()
97+
cmd := NewCmd(p)
98+
err := globalflags.Configure(cmd.Flags())
99+
if err != nil {
100+
t.Fatalf("configure global flags: %v", err)
101+
}
102+
103+
for flag, value := range tt.flagValues {
104+
err = cmd.Flags().Set(flag, value)
105+
if err != nil {
106+
if !tt.isValid {
107+
return
108+
}
109+
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
110+
}
111+
}
112+
113+
err = cmd.ValidateArgs(tt.argValues)
114+
if err != nil {
115+
if !tt.isValid {
116+
return
117+
}
118+
t.Fatalf("error validating args: %v", err)
119+
}
120+
121+
err = cmd.ValidateRequiredFlags()
122+
if err != nil {
123+
if !tt.isValid {
124+
return
125+
}
126+
t.Fatalf("error validating flags: %v", err)
127+
}
128+
129+
model, err := parseInput(p, cmd, tt.argValues)
130+
if err != nil {
131+
if !tt.isValid {
132+
return
133+
}
134+
t.Fatalf("error parsing input: %v", err)
135+
}
136+
137+
if !tt.isValid {
138+
t.Fatalf("did not fail on invalid input")
139+
}
140+
diff := cmp.Diff(model, tt.expectedModel)
141+
if diff != "" {
142+
t.Fatalf("data does not match: %s", diff)
143+
}
144+
})
145+
}
146+
}
147+
148+
func TestBuildRequest(t *testing.T) {
149+
tests := []struct {
150+
description string
151+
model *inputModel
152+
expectedRequest iaas.ApiDeleteKeyPairRequest
153+
}{
154+
{
155+
description: "base",
156+
model: fixtureInputModel(),
157+
expectedRequest: fixtureRequest(),
158+
},
159+
}
160+
161+
for _, tt := range tests {
162+
t.Run(tt.description, func(t *testing.T) {
163+
request := buildRequest(testCtx, tt.model, testClient)
164+
165+
diff := cmp.Diff(request, tt.expectedRequest,
166+
cmp.AllowUnexported(tt.expectedRequest),
167+
cmpopts.EquateComparable(testCtx),
168+
)
169+
if diff != "" {
170+
t.Fatalf("Data does not match: %s", diff)
171+
}
172+
})
173+
}
174+
}

0 commit comments

Comments
 (0)