diff --git a/CHANGELOG.md b/CHANGELOG.md index 174fad508..8b7cb5932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -158,6 +158,8 @@ - **Dependencies:** Bump STACKIT SDK core module from `v0.25.0` to `v0.26.0` - [v1.8.0](services/kms/CHANGELOG.md#v180) - **Feature:** Added `_UNKNOWN_DEFAULT_OPEN_API` fallback value to all enums to handle unknown API values gracefully. + - [v1.9.0](services/kms/CHANGELOG.md#v190) + - **Improvement:** Use new WaitHandler struct for all wait handlers - `lbapplication`: - [v0.5.7](services/lbapplication/CHANGELOG.md#v057) - **Dependencies:** Bump STACKIT SDK core module from `v0.24.0` to `v0.24.1` diff --git a/services/kms/CHANGELOG.md b/services/kms/CHANGELOG.md index e56d0ddab..4b887de52 100644 --- a/services/kms/CHANGELOG.md +++ b/services/kms/CHANGELOG.md @@ -1,3 +1,6 @@ +## v1.9.0 +- **Improvement:** Use new WaitHandler struct for all wait handlers + ## v1.8.0 - **Feature:** Added `_UNKNOWN_DEFAULT_OPEN_API` fallback value to all enums to handle unknown API values gracefully. diff --git a/services/kms/VERSION b/services/kms/VERSION index 4e2cea3bb..e2f650c40 100644 --- a/services/kms/VERSION +++ b/services/kms/VERSION @@ -1 +1 @@ -v1.8.0 \ No newline at end of file +v1.9.0 \ No newline at end of file diff --git a/services/kms/v1api/wait/wait.go b/services/kms/v1api/wait/wait.go index 01466913d..029dab667 100644 --- a/services/kms/v1api/wait/wait.go +++ b/services/kms/v1api/wait/wait.go @@ -3,11 +3,9 @@ package wait import ( "context" "errors" - "fmt" "net/http" "time" - "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/core/wait" kms "github.com/stackitcloud/stackit-sdk-go/services/kms/v1api" ) @@ -39,149 +37,96 @@ const ( ) func CreateKeyRingWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId string) *wait.AsyncActionHandler[kms.KeyRing] { - handler := wait.New(func() (bool, *kms.KeyRing, error) { - response, err := client.GetKeyRing(ctx, projectId, region, keyRingId).Execute() - if err != nil { - return false, nil, err - } - - if response != nil { - switch response.State { - case KEYRINGSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.KeyRing, string]{ + FetchInstance: client.GetKeyRing(ctx, projectId, region, keyRingId).Execute, + GetState: func(d *kms.KeyRing) (string, error) { + if d == nil || d.State == "" { + return "", errors.New("keyring or state is nil") } - } - - return false, nil, nil - }) + return d.State, nil + }, + ActiveState: []string{KEYRINGSTATE_ACTIVE, KEYRINGSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } func CreateOrUpdateKeyWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId, keyId string) *wait.AsyncActionHandler[kms.Key] { - handler := wait.New(func() (bool, *kms.Key, error) { - response, err := client.GetKey(ctx, projectId, region, keyRingId, keyId).Execute() - if err != nil { - return false, nil, err - } - - if response != nil { - switch response.State { - case KEYSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.Key, string]{ + FetchInstance: client.GetKey(ctx, projectId, region, keyRingId, keyId).Execute, + GetState: func(d *kms.Key) (string, error) { + if d == nil || d.State == "" { + return "", errors.New("key or state is nil") } - } - - return false, nil, nil - }) + return d.State, nil + }, + ActiveState: []string{KEYSTATE_ACTIVE, KEYSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } func DeleteKeyWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId, keyId string) *wait.AsyncActionHandler[kms.Key] { - handler := wait.New(func() (bool, *kms.Key, error) { - _, err := client.GetKey(ctx, projectId, region, keyRingId, keyId).Execute() - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, nil - } - } - return true, nil, err - } - return false, nil, nil - }) + waitConfig := wait.WaiterHelper[kms.Key, string]{ + FetchInstance: client.GetKey(ctx, projectId, region, keyRingId, keyId).Execute, + GetState: func(_ *kms.Key) (string, error) { + return "", nil + }, + DeleteHttpErrorStatusCodes: []int{http.StatusNotFound, http.StatusGone}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } func EnableKeyVersionWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId, keyId string, version int64) *wait.AsyncActionHandler[kms.Version] { - handler := wait.New(func() (bool, *kms.Version, error) { - response, err := client.GetVersion(ctx, projectId, region, keyRingId, keyId, version).Execute() - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, fmt.Errorf("enabling failed for key %s version %d: version or key not found", keyId, version) - } - } - return false, nil, err - } - - if response != nil { - switch response.State { - case VERSIONSTATE_ACTIVE: - return true, response, nil - case VERSIONSTATE_CREATING: - return false, nil, nil - case VERSIONSTATE_DESTROYED, VERSIONSTATE_KEY_MATERIAL_INVALID: - return true, response, fmt.Errorf("enabling failed for key %s version %d: state %s", keyId, version, response.State) - default: - return true, response, fmt.Errorf("key version %d for key %s has unexpected state %s", version, keyId, response.State) + waitConfig := wait.WaiterHelper[kms.Version, string]{ + FetchInstance: client.GetVersion(ctx, projectId, region, keyRingId, keyId, version).Execute, + GetState: func(d *kms.Version) (string, error) { + if d == nil || d.State == "" { + return "", errors.New("version or state is nil") } - } - - return false, nil, nil - }) + return d.State, nil + }, + ActiveState: []string{VERSIONSTATE_ACTIVE}, + ErrorState: []string{VERSIONSTATE_DESTROYED, VERSIONSTATE_KEY_MATERIAL_INVALID, VERSIONSTATE_DISABLED, VERSIONSTATE_KEY_MATERIAL_UNAVAILABLE}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } func DisableKeyVersionWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId, keyId string, version int64) *wait.AsyncActionHandler[kms.Version] { - handler := wait.New(func() (bool, *kms.Version, error) { - response, err := client.GetVersion(ctx, projectId, region, keyRingId, keyId, version).Execute() - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, fmt.Errorf("disabling failed for key %s version %d: version or key not found", keyId, version) - } - } - return false, nil, err - } - - if response != nil { - switch response.State { - case VERSIONSTATE_DISABLED: - return true, response, nil - case VERSIONSTATE_ACTIVE, VERSIONSTATE_CREATING, VERSIONSTATE_KEY_MATERIAL_UNAVAILABLE: - return false, nil, nil - case VERSIONSTATE_DESTROYED, VERSIONSTATE_KEY_MATERIAL_INVALID: - return true, response, fmt.Errorf("disabling failed for key %s version %d: state %s", keyId, version, response.State) - default: - return true, response, fmt.Errorf("key version %d for key %s has unexpected state %s", version, keyId, response.State) + waitConfig := wait.WaiterHelper[kms.Version, string]{ + FetchInstance: client.GetVersion(ctx, projectId, region, keyRingId, keyId, version).Execute, + GetState: func(d *kms.Version) (string, error) { + if d == nil || d.State == "" { + return "", errors.New("version or state is nil") } - } - - return false, nil, nil - }) + return d.State, nil + }, + ActiveState: []string{VERSIONSTATE_DISABLED}, + ErrorState: []string{VERSIONSTATE_DESTROYED, VERSIONSTATE_KEY_MATERIAL_INVALID}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } func CreateWrappingKeyWaitHandler(ctx context.Context, client kms.DefaultAPI, projectId, region, keyRingId, wrappingKeyId string) *wait.AsyncActionHandler[kms.WrappingKey] { - handler := wait.New(func() (bool, *kms.WrappingKey, error) { - response, err := client.GetWrappingKey(ctx, projectId, region, keyRingId, wrappingKeyId).Execute() - if err != nil { - return false, nil, err - } - - if response != nil { - switch response.State { - case WRAPPINGKEYSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.WrappingKey, string]{ + FetchInstance: client.GetWrappingKey(ctx, projectId, region, keyRingId, wrappingKeyId).Execute, + GetState: func(d *kms.WrappingKey) (string, error) { + if d == nil || d.State == "" { + return "", errors.New("wrappingkey or state is nil") } - } - - return false, nil, nil - }) + return d.State, nil + }, + ActiveState: []string{WRAPPINGKEYSTATE_ACTIVE, WRAPPINGKEYSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } diff --git a/services/kms/v1api/wait/wait_test.go b/services/kms/v1api/wait/wait_test.go index 0db665716..38a7f310f 100644 --- a/services/kms/v1api/wait/wait_test.go +++ b/services/kms/v1api/wait/wait_test.go @@ -191,8 +191,8 @@ func TestCreateKeyRingWaitHandler(t *testing.T) { responses: []keyRingResponse{ {fixtureKeyRing("bogus"), nil}, }, - want: fixtureKeyRing("bogus"), - wantErr: false, + want: nil, + wantErr: true, }, } for _, tt := range tests { @@ -267,8 +267,8 @@ func TestCreateOrUpdateKeyWaitHandler(t *testing.T) { []keyResponse{ {fixtureKey("bogus"), nil}, }, - fixtureKey("bogus"), - false, + nil, + true, }, // no special update tests needed as the states are the same } @@ -432,7 +432,7 @@ func TestEnableKeyVersionWaitHandler(t *testing.T) { []versionResponse{ {fixtureVersion(1, false, "bogus"), nil}, }, - fixtureVersion(1, false, "bogus"), + nil, true, }, { @@ -666,8 +666,8 @@ func TestCreateWrappingWaitHandler(t *testing.T) { []wrappingKeyResponse{ {fixtureWrappingKey("bogus"), nil}, }, - fixtureWrappingKey("bogus"), - false, + nil, + true, }, // no special update tests needed as the states are the same } diff --git a/services/kms/wait/wait.go b/services/kms/wait/wait.go index cc43d0c79..1bf1e0df7 100644 --- a/services/kms/wait/wait.go +++ b/services/kms/wait/wait.go @@ -3,11 +3,9 @@ package wait import ( "context" "errors" - "fmt" "net/http" "time" - "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/core/wait" "github.com/stackitcloud/stackit-sdk-go/services/kms" ) @@ -55,154 +53,113 @@ type ApiKmsClient interface { // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func CreateKeyRingWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId string) *wait.AsyncActionHandler[kms.KeyRing] { - handler := wait.New(func() (bool, *kms.KeyRing, error) { - response, err := client.GetKeyRingExecute(ctx, projectId, region, keyRingId) - if err != nil { - return false, nil, err - } - - if response != nil && response.State != nil { - switch *response.State { - case kms.KEYRINGSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.KeyRing, kms.KeyRingState]{ + FetchInstance: func() (*kms.KeyRing, error) { + return client.GetKeyRingExecute(ctx, projectId, region, keyRingId) + }, + GetState: func(d *kms.KeyRing) (kms.KeyRingState, error) { + if d == nil || d.State == nil { + return "", errors.New("keyring or state is nil") } - } - - return false, nil, nil - }) + return *d.State, nil + }, + ActiveState: []kms.KeyRingState{kms.KEYRINGSTATE_ACTIVE, kms.KEYRINGSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func CreateOrUpdateKeyWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, keyId string) *wait.AsyncActionHandler[kms.Key] { - handler := wait.New(func() (bool, *kms.Key, error) { - response, err := client.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) - if err != nil { - return false, nil, err - } - - if response != nil && response.State != nil { - switch *response.State { - case kms.KEYSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.Key, kms.KeyState]{ + FetchInstance: func() (*kms.Key, error) { + return client.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) + }, + GetState: func(d *kms.Key) (kms.KeyState, error) { + if d == nil || d.State == nil { + return "", errors.New("key or state is nil") } - } - - return false, nil, nil - }) + return *d.State, nil + }, + ActiveState: []kms.KeyState{kms.KEYSTATE_ACTIVE, kms.KEYSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func DeleteKeyWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, keyId string) *wait.AsyncActionHandler[kms.Key] { - handler := wait.New(func() (bool, *kms.Key, error) { - _, err := client.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, nil - } - } - return true, nil, err - } - return false, nil, nil - }) + waitConfig := wait.WaiterHelper[kms.Key, kms.KeyState]{ + FetchInstance: func() (*kms.Key, error) { + return client.GetKeyExecute(ctx, projectId, region, keyRingId, keyId) + }, + GetState: func(_ *kms.Key) (kms.KeyState, error) { + return "", nil + }, + DeleteHttpErrorStatusCodes: []int{http.StatusNotFound, http.StatusGone}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func EnableKeyVersionWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, keyId string, version int64) *wait.AsyncActionHandler[kms.Version] { - handler := wait.New(func() (bool, *kms.Version, error) { - response, err := client.GetVersionExecute(ctx, projectId, region, keyRingId, keyId, version) - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, fmt.Errorf("enabling failed for key %s version %d: version or key not found", keyId, version) - } - } - return false, nil, err - } - - if response != nil && response.State != nil { - switch *response.State { - case kms.VERSIONSTATE_ACTIVE: - return true, response, nil - case kms.VERSIONSTATE_CREATING: - return false, nil, nil - case kms.VERSIONSTATE_DESTROYED, kms.VERSIONSTATE_KEY_MATERIAL_INVALID: - return true, response, fmt.Errorf("enabling failed for key %s version %d: state %s", keyId, version, *response.State) - default: - return true, response, fmt.Errorf("key version %d for key %s has unexpected state %s", version, keyId, *response.State) + waitConfig := wait.WaiterHelper[kms.Version, kms.VersionState]{ + FetchInstance: func() (*kms.Version, error) { + return client.GetVersionExecute(ctx, projectId, region, keyRingId, keyId, version) + }, + GetState: func(d *kms.Version) (kms.VersionState, error) { + if d == nil || d.State == nil { + return "", errors.New("version or state is nil") } - } - - return false, nil, nil - }) + return *d.State, nil + }, + ActiveState: []kms.VersionState{kms.VERSIONSTATE_ACTIVE}, + ErrorState: []kms.VersionState{kms.VERSIONSTATE_DESTROYED, kms.VERSIONSTATE_KEY_MATERIAL_INVALID}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func DisableKeyVersionWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, keyId string, version int64) *wait.AsyncActionHandler[kms.Version] { - handler := wait.New(func() (bool, *kms.Version, error) { - response, err := client.GetVersionExecute(ctx, projectId, region, keyRingId, keyId, version) - if err != nil { - var apiErr *oapierror.GenericOpenAPIError - if errors.As(err, &apiErr) { - if statusCode := apiErr.StatusCode; statusCode == http.StatusNotFound || statusCode == http.StatusGone { - return true, nil, fmt.Errorf("disabling failed for key %s version %d: version or key not found", keyId, version) - } - } - return false, nil, err - } - - if response != nil && response.State != nil { - switch *response.State { - case kms.VERSIONSTATE_DISABLED: - return true, response, nil - case kms.VERSIONSTATE_ACTIVE, kms.VERSIONSTATE_CREATING, kms.VERSIONSTATE_KEY_MATERIAL_UNAVAILABLE: - return false, nil, nil - case kms.VERSIONSTATE_DESTROYED, kms.VERSIONSTATE_KEY_MATERIAL_INVALID: - return true, response, fmt.Errorf("disabling failed for key %s version %d: state %s", keyId, version, *response.State) - default: - return true, response, fmt.Errorf("key version %d for key %s has unexpected state %s", version, keyId, *response.State) + waitConfig := wait.WaiterHelper[kms.Version, kms.VersionState]{ + FetchInstance: func() (*kms.Version, error) { + return client.GetVersionExecute(ctx, projectId, region, keyRingId, keyId, version) + }, + GetState: func(d *kms.Version) (kms.VersionState, error) { + if d == nil || d.State == nil { + return "", errors.New("version or state is nil") } - } - - return false, nil, nil - }) + return *d.State, nil + }, + ActiveState: []kms.VersionState{kms.VERSIONSTATE_DISABLED}, + ErrorState: []kms.VersionState{kms.VERSIONSTATE_DESTROYED, kms.VERSIONSTATE_KEY_MATERIAL_INVALID}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } // Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead func CreateWrappingKeyWaitHandler(ctx context.Context, client ApiKmsClient, projectId, region, keyRingId, wrappingKeyId string) *wait.AsyncActionHandler[kms.WrappingKey] { - handler := wait.New(func() (bool, *kms.WrappingKey, error) { - response, err := client.GetWrappingKeyExecute(ctx, projectId, region, keyRingId, wrappingKeyId) - if err != nil { - return false, nil, err - } - - if response != nil && response.State != nil { - switch *response.State { - case kms.WRAPPINGKEYSTATE_CREATING: - return false, nil, nil - default: - return true, response, nil + waitConfig := wait.WaiterHelper[kms.WrappingKey, kms.WrappingKeyState]{ + FetchInstance: func() (*kms.WrappingKey, error) { + return client.GetWrappingKeyExecute(ctx, projectId, region, keyRingId, wrappingKeyId) + }, + GetState: func(d *kms.WrappingKey) (kms.WrappingKeyState, error) { + if d == nil || d.State == nil { + return "", errors.New("wrappingkey or state is nil") } - } - - return false, nil, nil - }) + return *d.State, nil + }, + ActiveState: []kms.WrappingKeyState{kms.WRAPPINGKEYSTATE_ACTIVE, kms.WRAPPINGKEYSTATE_DELETED}, + } + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } diff --git a/services/kms/wait/wait_test.go b/services/kms/wait/wait_test.go index 3824d2ded..9426a29e6 100644 --- a/services/kms/wait/wait_test.go +++ b/services/kms/wait/wait_test.go @@ -193,8 +193,8 @@ func TestCreateKeyRingWaitHandler(t *testing.T) { responses: []keyRingResponse{ {fixtureKeyRing("bogus"), nil}, }, - want: fixtureKeyRing("bogus"), - wantErr: false, + want: nil, + wantErr: true, }, } for _, tt := range tests { @@ -270,8 +270,8 @@ func TestCreateOrUpdateKeyWaitHandler(t *testing.T) { []keyResponse{ {fixtureKey("bogus"), nil}, }, - fixtureKey("bogus"), - false, + nil, + true, }, // no special update tests needed as the states are the same } @@ -434,7 +434,7 @@ func TestEnableKeyVersionWaitHandler(t *testing.T) { []versionResponse{ {fixtureVersion(1, false, "bogus"), nil}, }, - fixtureVersion(1, false, "bogus"), + nil, true, }, { @@ -450,7 +450,7 @@ func TestEnableKeyVersionWaitHandler(t *testing.T) { []versionResponse{ {fixtureVersion(1, true, kms.VERSIONSTATE_DISABLED), nil}, }, - fixtureVersion(1, true, kms.VERSIONSTATE_DISABLED), + nil, true, }, { @@ -458,7 +458,7 @@ func TestEnableKeyVersionWaitHandler(t *testing.T) { []versionResponse{ {fixtureVersion(1, false, kms.VERSIONSTATE_KEY_MATERIAL_UNAVAILABLE), nil}, }, - fixtureVersion(1, false, kms.VERSIONSTATE_KEY_MATERIAL_UNAVAILABLE), + nil, true, }, { @@ -667,8 +667,8 @@ func TestCreateWrappingWaitHandler(t *testing.T) { []wrappingKeyResponse{ {fixtureWrappingKey("bogus"), nil}, }, - fixtureWrappingKey("bogus"), - false, + nil, + true, }, // no special update tests needed as the states are the same }