diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e639fe5..801485998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,6 +137,8 @@ - **Dependencies:** Bump STACKIT SDK core module from `v0.25.0` to `v0.26.0` - [v0.9.0](services/intake/CHANGELOG.md#v090) - **Feature:** Added `_UNKNOWN_DEFAULT_OPEN_API` fallback value to all enums to handle unknown API values gracefully. + - [v0.10.0](services/intake/CHANGELOG.md#v0100) + - `v1betaapi`: **Improvement**: Use new `WaiterHandler` struct in the Git WaitHandler - `kms`: - [v1.6.2](services/kms/CHANGELOG.md#v162) - **Dependencies:** Bump STACKIT SDK core module from `v0.24.0` to `v0.24.1` diff --git a/services/intake/CHANGELOG.md b/services/intake/CHANGELOG.md index 6067e030b..3192502ed 100644 --- a/services/intake/CHANGELOG.md +++ b/services/intake/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.10.0 +- `v1betaapi`: **Improvement**: Use new `WaiterHandler` struct in the Intake WaitHandler + ## v0.9.0 - **Feature:** Added `_UNKNOWN_DEFAULT_OPEN_API` fallback value to all enums to handle unknown API values gracefully. diff --git a/services/intake/VERSION b/services/intake/VERSION index 7965b36d6..f78dc3652 100644 --- a/services/intake/VERSION +++ b/services/intake/VERSION @@ -1 +1 @@ -v0.9.0 \ No newline at end of file +v0.10.0 \ No newline at end of file diff --git a/services/intake/v1betaapi/wait/wait.go b/services/intake/v1betaapi/wait/wait.go index 5c1e0b9f3..e356a3c0f 100644 --- a/services/intake/v1betaapi/wait/wait.go +++ b/services/intake/v1betaapi/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" intake "github.com/stackitcloud/stackit-sdk-go/services/intake/v1betaapi" ) @@ -27,133 +25,117 @@ const ( INTAKEUSERRESPONSESTATE_DELETING = "deleting" ) -func CreateOrUpdateIntakeRunnerWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeRunnerId string) *wait.AsyncActionHandler[intake.IntakeRunnerResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeRunnerResponse, err error) { - runner, err := a.GetIntakeRunner(ctx, projectId, region, intakeRunnerId).Execute() - if err != nil { - return false, nil, err - } - - if runner == nil { - return false, nil, fmt.Errorf("API returned a nil response for Intake Runner %s", intakeRunnerId) - } - - if runner.Id == intakeRunnerId && runner.State == INTAKERUNNERRESPONSESTATE_ACTIVE { - return true, runner, nil - } - +func CreateOrUpdateIntakeRunnerWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeRunnerId string) *wait.AsyncActionHandler[intake.IntakeRunnerResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeRunnerResponse, string]{ + FetchInstance: client.GetIntakeRunner(ctx, projectId, region, intakeRunnerId).Execute, + GetState: func(response *intake.IntakeRunnerResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") + } + return response.State, nil + }, + ActiveState: []string{INTAKERUNNERRESPONSESTATE_ACTIVE}, + ErrorState: []string{}, // The API does not have a dedicated failure state for this resource, // so we rely on the timeout for cases where it never becomes active. - return false, nil, nil - }) + } + + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(15 * time.Minute) return handler } -func DeleteIntakeRunnerWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeRunnerId string) *wait.AsyncActionHandler[intake.IntakeRunnerResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeRunnerResponse, err error) { - _, err = a.GetIntakeRunner(ctx, projectId, region, intakeRunnerId).Execute() - if err == nil { - // Resource still exists - return false, nil, nil - } - - var oapiError *oapierror.GenericOpenAPIError - if errors.As(err, &oapiError) { - if oapiError.StatusCode == http.StatusNotFound { - // Success: Resource is gone - return true, nil, nil +func DeleteIntakeRunnerWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeRunnerId string) *wait.AsyncActionHandler[intake.IntakeRunnerResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeRunnerResponse, string]{ + FetchInstance: client.GetIntakeRunner(ctx, projectId, region, intakeRunnerId).Execute, + GetState: func(response *intake.IntakeRunnerResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") } - } - // An unexpected error occurred - return false, nil, err - }) + return response.State, nil + }, + ActiveState: []string{}, + ErrorState: []string{}, + DeleteHttpErrorStatusCodes: []int{http.StatusNotFound}, + } + + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(15 * time.Minute) return handler } -func CreateOrUpdateIntakeWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeId string) *wait.AsyncActionHandler[intake.IntakeResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeResponse, err error) { - ik, err := a.GetIntake(ctx, projectId, region, intakeId).Execute() - if err != nil { - return false, nil, err - } - - if ik == nil { - return false, nil, fmt.Errorf("API returned a nil response for Intake %s", intakeId) - } - - if ik.Id == intakeId && ik.State == INTAKERESPONSESTATE_ACTIVE { - return true, ik, nil - } - - if ik.Id == intakeId && ik.State == INTAKERESPONSESTATE_FAILED { - return true, ik, fmt.Errorf("create/update failed for Intake %s", intakeId) - } +func CreateOrUpdateIntakeWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeId string) *wait.AsyncActionHandler[intake.IntakeResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeResponse, string]{ + FetchInstance: client.GetIntake(ctx, projectId, region, intakeId).Execute, + GetState: func(response *intake.IntakeResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") + } + return response.State, nil + }, + ActiveState: []string{INTAKERUNNERRESPONSESTATE_ACTIVE}, + ErrorState: []string{INTAKERESPONSESTATE_FAILED}, + } - return false, nil, nil - }) + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } -func DeleteIntakeWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeId string) *wait.AsyncActionHandler[intake.IntakeResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeResponse, err error) { - _, err = a.GetIntake(ctx, projectId, region, intakeId).Execute() - if err == nil { - return false, nil, nil - } - - var oapiError *oapierror.GenericOpenAPIError - if errors.As(err, &oapiError) { - if oapiError.StatusCode == http.StatusNotFound { - return true, nil, nil +func DeleteIntakeWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeId string) *wait.AsyncActionHandler[intake.IntakeResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeResponse, string]{ + FetchInstance: client.GetIntake(ctx, projectId, region, intakeId).Execute, + GetState: func(response *intake.IntakeResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") } - } - return false, nil, err - }) + return response.State, nil + }, + ActiveState: []string{}, + ErrorState: []string{}, + DeleteHttpErrorStatusCodes: []int{http.StatusNotFound}, + } + + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(10 * time.Minute) return handler } -func CreateOrUpdateIntakeUserWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeId, intakeUserId string) *wait.AsyncActionHandler[intake.IntakeUserResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeUserResponse, err error) { - user, err := a.GetIntakeUser(ctx, projectId, region, intakeId, intakeUserId).Execute() - if err != nil { - return false, nil, err - } - - if user == nil { - return false, nil, fmt.Errorf("API returned a nil response for Intake User %s", intakeUserId) - } - - if user.Id == intakeUserId && user.State == INTAKEUSERRESPONSESTATE_ACTIVE { - return true, user, nil - } - - // The API does not have a dedicated failure state for this resource, we rely on the timeout for cases where - // it never becomes active. - return false, nil, nil - }) +func CreateOrUpdateIntakeUserWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeId, intakeUserId string) *wait.AsyncActionHandler[intake.IntakeUserResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeUserResponse, string]{ + FetchInstance: client.GetIntakeUser(ctx, projectId, region, intakeId, intakeUserId).Execute, + GetState: func(response *intake.IntakeUserResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") + } + return response.State, nil + }, + ActiveState: []string{INTAKEUSERRESPONSESTATE_ACTIVE}, + ErrorState: []string{}, + // The API does not have a dedicated failure state for this resource, + // so we rely on the timeout for cases where it never becomes active. + } + + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(5 * time.Minute) return handler } -func DeleteIntakeUserWaitHandler(ctx context.Context, a intake.DefaultAPI, projectId, region, intakeId, intakeUserId string) *wait.AsyncActionHandler[intake.IntakeUserResponse] { - handler := wait.New(func() (waitFinished bool, response *intake.IntakeUserResponse, err error) { - _, err = a.GetIntakeUser(ctx, projectId, region, intakeId, intakeUserId).Execute() - if err == nil { - return false, nil, nil - } - - var oapiError *oapierror.GenericOpenAPIError - if errors.As(err, &oapiError) { - if oapiError.StatusCode == http.StatusNotFound { - return true, nil, nil +func DeleteIntakeUserWaitHandler(ctx context.Context, client intake.DefaultAPI, projectId, region, intakeId, intakeUserId string) *wait.AsyncActionHandler[intake.IntakeUserResponse] { + waitConfig := wait.WaiterHelper[intake.IntakeUserResponse, string]{ + FetchInstance: client.GetIntakeUser(ctx, projectId, region, intakeId, intakeUserId).Execute, + GetState: func(response *intake.IntakeUserResponse) (string, error) { + if response == nil { + return "", errors.New("empty response") } - } - return false, nil, err - }) + return response.State, nil + }, + ActiveState: []string{}, + ErrorState: []string{}, + DeleteHttpErrorStatusCodes: []int{http.StatusNotFound}, + } + + handler := wait.New(waitConfig.Wait()) handler.SetTimeout(5 * time.Minute) return handler } diff --git a/services/intake/v1betaapi/wait/wait_test.go b/services/intake/v1betaapi/wait/wait_test.go index 3c15a551e..596d0458e 100644 --- a/services/intake/v1betaapi/wait/wait_test.go +++ b/services/intake/v1betaapi/wait/wait_test.go @@ -132,6 +132,17 @@ func TestCreateOrUpdateIntakeRunnerWaitHandler(t *testing.T) { State: INTAKERUNNERRESPONSESTATE_RECONCILING, }, }, + { + desc: "wrong state in response", + getFails: false, + wantErr: true, + wantResp: false, + returnRunner: true, + intakeRunnerResponse: &intake.IntakeRunnerResponse{ + Id: intakeRunnerId, + State: "wrong state", + }, + }, { desc: "nil state in response", getFails: false, @@ -292,6 +303,17 @@ func TestCreateOrUpdateIntakeWaitHandler(t *testing.T) { State: INTAKERESPONSESTATE_RECONCILING, }, }, + { + desc: "wrong state in response", + getFails: false, + wantErr: true, + wantResp: false, + returnIntake: true, + intakeResponse: &intake.IntakeResponse{ + Id: intakeId, + State: "wrong state", + }, + }, { desc: "nil state in response", getFails: false, @@ -441,6 +463,17 @@ func TestCreateOrUpdateIntakeUserWaitHandler(t *testing.T) { State: INTAKEUSERRESPONSESTATE_RECONCILING, }, }, + { + desc: "wrong state in response", + getFails: false, + wantErr: true, + wantResp: false, + returnUser: true, + intakeUserResponse: &intake.IntakeUserResponse{ + Id: intakeUserId, + State: "wrong state", + }, + }, { desc: "nil state in response", getFails: false,