Skip to content

Commit 0996a87

Browse files
committed
feat(kms): add wait handler for key ring creation
relates to stackitcloud/terraform-provider-stackit#897
1 parent 0c73780 commit 0996a87

File tree

5 files changed

+134
-3
lines changed

5 files changed

+134
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@
3131
- **Dependencies:** Bump `github.com/golang-jwt/jwt/v5` from `v5.2.2` to `v5.2.3`
3232
- `intake`: [v0.1.0](services/intake/CHANGELOG.md#v010)
3333
- **New**: STACKIT Intake module can be used to manage the STACKIT Intake. Manage your `IntakeRunners`, `Intakes` and `IntakeUsers`
34-
- `kms`: [v0.3.1](services/kms/CHANGELOG.md#v031)
35-
- **Dependencies:** Bump `github.com/golang-jwt/jwt/v5` from `v5.2.2` to `v5.2.3`
34+
- `kms`:
35+
- [v0.4.0](services/kms/CHANGELOG.md#v040)
36+
- **Feature:** Add new wait handler for key ring creation (`CreateKeyRingWaitHandler`)
37+
- [v0.3.1](services/kms/CHANGELOG.md#v031)
38+
- **Dependencies:** Bump `github.com/golang-jwt/jwt/v5` from `v5.2.2` to `v5.2.3`
3639
- `lbapplication`: [v0.5.1](services/lbapplication/CHANGELOG.md#v051)
3740
- **Dependencies:** Bump `github.com/golang-jwt/jwt/v5` from `v5.2.2` to `v5.2.3`
3841
- `loadbalancer`: [v1.5.1](services/loadbalancer/CHANGELOG.md#v151)

services/kms/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v0.4.0
2+
- **Feature:** Add new wait handler for key ring creation (`CreateKeyRingWaitHandler`)
3+
14
## v0.3.1
25
- **Dependencies:** Bump `github.com/golang-jwt/jwt/v5` from `v5.2.2` to `v5.2.3`
36

services/kms/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.3.1
1+
v0.4.0

services/kms/wait/wait.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,33 @@ const (
4646

4747
type ApiKmsClient interface {
4848
GetKeyExecute(ctx context.Context, projectId string, regionId string, keyRingId string, keyId string) (*kms.Key, error)
49+
GetKeyRingExecute(ctx context.Context, projectId string, regionId string, keyRingId string) (*kms.KeyRing, error)
4950
GetVersionExecute(ctx context.Context, projectId string, regionId string, keyRingId string, keyId string, versionNumber int64) (*kms.Version, error)
5051
GetWrappingKeyExecute(ctx context.Context, projectId string, regionId string, keyRingId string, wrappingKeyId string) (*kms.WrappingKey, error)
5152
}
5253

54+
func CreateKeyRingWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId string) *wait.AsyncActionHandler[kms.KeyRing] {
55+
handler := wait.New(func() (bool, *kms.KeyRing, error) {
56+
response, err := client.GetKeyRingExecute(ctx, projectId, region, keyRingId)
57+
if err != nil {
58+
return false, nil, err
59+
}
60+
61+
if response.State != nil {
62+
switch *response.State {
63+
case kms.KEYRINGSTATE_CREATING:
64+
return false, nil, nil
65+
default:
66+
return true, response, nil
67+
}
68+
}
69+
70+
return false, nil, nil
71+
})
72+
handler.SetTimeout(10 * time.Minute)
73+
return handler
74+
}
75+
5376
func CreateOrUpdateKeyWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, keyId string) *wait.AsyncActionHandler[kms.Key] {
5477
handler := wait.New(func() (bool, *kms.Key, error) {
5578
response, err := client.GetKeyExecute(ctx, projectId, region, keyRingId, keyId)

services/kms/wait/wait_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ type keyResponse struct {
3030
err error
3131
}
3232

33+
type keyRingResponse struct {
34+
keyRing *kms.KeyRing
35+
err error
36+
}
37+
3338
type versionResponse struct {
3439
version *kms.Version
3540
err error
@@ -42,9 +47,11 @@ type wrappingKeyResponse struct {
4247

4348
type apiKmsMocked struct {
4449
idxKeyResponse int
50+
idxKeyRingResponse int
4551
idxVersionResponse int
4652
idxWrappingKeyResponse int
4753
keyResponses []keyResponse
54+
keyRingResponses []keyRingResponse
4855
versionResponses []versionResponse
4956
wrappingKeyResponses []wrappingKeyResponse
5057
}
@@ -73,6 +80,14 @@ func (a *apiKmsMocked) GetKeyExecute(_ context.Context, _, _, _, _ string) (*kms
7380
return resp.key, resp.err
7481
}
7582

83+
// GetKeyRingExecute implements ApiKmsClient.
84+
func (a *apiKmsMocked) GetKeyRingExecute(_ context.Context, _, _, _ string) (*kms.KeyRing, error) {
85+
resp := a.keyRingResponses[a.idxKeyRingResponse]
86+
a.idxKeyRingResponse++
87+
a.idxKeyRingResponse %= len(a.keyRingResponses)
88+
return resp.keyRing, resp.err
89+
}
90+
7691
func fixtureKey(state kms.KeyState) *kms.Key {
7792
return &kms.Key{
7893
Algorithm: kms.ALGORITHM_AES_256_GCM.Ptr(),
@@ -89,6 +104,16 @@ func fixtureKey(state kms.KeyState) *kms.Key {
89104
}
90105
}
91106

107+
func fixtureKeyRing(state kms.KeyRingState) *kms.KeyRing {
108+
return &kms.KeyRing{
109+
CreatedAt: &testDate,
110+
Description: utils.Ptr("test-description"),
111+
DisplayName: utils.Ptr("test-displayname"),
112+
Id: &testKeyRingId,
113+
State: &state,
114+
}
115+
}
116+
92117
func fixtureWrappingKey(state kms.WrappingKeyState) *kms.WrappingKey {
93118
return &kms.WrappingKey{
94119
Algorithm: kms.WRAPPINGALGORITHM__2048_OAEP_SHA256.Ptr(),
@@ -118,6 +143,83 @@ func fixtureVersion(version int, disabled bool, state kms.VersionState) *kms.Ver
118143
}
119144
}
120145

146+
func TestCreateKeyRingWaitHandler(t *testing.T) {
147+
tests := []struct {
148+
name string
149+
responses []keyRingResponse
150+
want *kms.KeyRing
151+
wantErr bool
152+
}{
153+
{
154+
name: "create succeeded immediately",
155+
responses: []keyRingResponse{
156+
{fixtureKeyRing(kms.KEYRINGSTATE_ACTIVE), nil},
157+
},
158+
want: fixtureKeyRing(kms.KEYRINGSTATE_ACTIVE),
159+
wantErr: false,
160+
},
161+
{
162+
name: "create succeeded delayed",
163+
responses: []keyRingResponse{
164+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
165+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
166+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
167+
{fixtureKeyRing(kms.KEYRINGSTATE_ACTIVE), nil},
168+
},
169+
want: fixtureKeyRing(kms.KEYRINGSTATE_ACTIVE),
170+
wantErr: false,
171+
},
172+
{
173+
name: "create failed delayed",
174+
responses: []keyRingResponse{
175+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
176+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
177+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
178+
{fixtureKeyRing(kms.KEYRINGSTATE_DELETED), nil},
179+
},
180+
want: fixtureKeyRing(kms.KEYRINGSTATE_DELETED),
181+
wantErr: false,
182+
},
183+
{
184+
name: "timeout",
185+
responses: []keyRingResponse{
186+
{fixtureKeyRing(kms.KEYRINGSTATE_CREATING), nil},
187+
},
188+
want: nil,
189+
wantErr: true,
190+
},
191+
{
192+
name: "broken state",
193+
responses: []keyRingResponse{
194+
{fixtureKeyRing("bogus"), nil},
195+
},
196+
want: fixtureKeyRing("bogus"),
197+
wantErr: false,
198+
},
199+
}
200+
for _, tt := range tests {
201+
t.Run(tt.name, func(t *testing.T) {
202+
ctx := context.Background()
203+
client := &apiKmsMocked{
204+
keyRingResponses: tt.responses,
205+
}
206+
207+
handler := CreateKeyRingWaitHandler(ctx, client, testProject, testRegion, testKeyRingId)
208+
got, err := handler.SetTimeout(1 * time.Second).
209+
SetThrottle(250 * time.Millisecond).
210+
WaitWithContext(ctx)
211+
212+
if (err != nil) != tt.wantErr {
213+
t.Fatalf("unexpected error response. want %v but got %v ", tt.wantErr, err)
214+
}
215+
216+
if diff := cmp.Diff(tt.want, got); diff != "" {
217+
t.Errorf("differing key %s", diff)
218+
}
219+
})
220+
}
221+
}
222+
121223
func TestCreateOrUpdateKeyWaitHandler(t *testing.T) {
122224
tests := []struct {
123225
name string

0 commit comments

Comments
 (0)