diff --git a/CHANGELOG.md b/CHANGELOG.md index ad399f28e..91fa1296f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -276,6 +276,8 @@ - **Dependencies:** Bump STACKIT SDK core module from `v0.24.1` to `v0.25.0` - [v0.27.2](services/opensearch/CHANGELOG.md#v0272) - **Dependencies:** Bump STACKIT SDK core module from `v0.25.0` to `v0.26.0` + - [v0.28.0](services/opensearch/CHANGELOG.md#v0280) + - **Improvement:** Use new WaiterHelper for opensearch waiters - `postgresflex`: - [v1.6.3](services/postgresflex/CHANGELOG.md#v163) - **Dependencies:** Bump STACKIT SDK core module from `v0.24.0` to `v0.24.1` diff --git a/services/opensearch/CHANGELOG.md b/services/opensearch/CHANGELOG.md index b78f283bb..4e2d6f3d1 100644 --- a/services/opensearch/CHANGELOG.md +++ b/services/opensearch/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.28.0 +- **Improvement:** Use new WaiterHelper for opensearch waiters + ## v0.27.2 - **Dependencies:** Bump STACKIT SDK core module from `v0.25.0` to `v0.26.0` diff --git a/services/opensearch/VERSION b/services/opensearch/VERSION index 95be22acf..e9183beda 100644 --- a/services/opensearch/VERSION +++ b/services/opensearch/VERSION @@ -1 +1 @@ -v0.27.2 \ No newline at end of file +v0.28.0 \ No newline at end of file diff --git a/services/opensearch/v1api/wait/wait.go b/services/opensearch/v1api/wait/wait.go index b3fd9318c..da02bb981 100644 --- a/services/opensearch/v1api/wait/wait.go +++ b/services/opensearch/v1api/wait/wait.go @@ -2,6 +2,7 @@ package wait import ( "context" + "errors" "fmt" "net/http" "strings" @@ -27,46 +28,12 @@ const ( // CreateInstanceWaitHandler will wait for instance creation func CreateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] { - handler := wait.New(func() (waitFinished bool, response *opensearch.Instance, err error) { - s, err := a.GetInstance(ctx, projectId, instanceId).Execute() - if err != nil { - return false, nil, err - } - if s.Status == nil { - return false, nil, fmt.Errorf("create failed for instance with id %s. The response is not valid: the status are missing", instanceId) - } - switch *s.Status { - case INSTANCESTATUS_ACTIVE: - return true, s, nil - case INSTANCESTATUS_FAILED: - return true, s, fmt.Errorf("create failed for instance with id %s: %s", instanceId, s.LastOperation.Description) - } - return false, nil, nil - }) - handler.SetTimeout(45 * time.Minute) - return handler + return createOrUpdateInstanceWaitHandler(ctx, a, projectId, instanceId) } // PartialUpdateInstanceWaitHandler will wait for instance update func PartialUpdateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] { - handler := wait.New(func() (waitFinished bool, response *opensearch.Instance, err error) { - s, err := a.GetInstance(ctx, projectId, instanceId).Execute() - if err != nil { - return false, nil, err - } - if s.Status == nil { - return false, nil, fmt.Errorf("update failed for instance with id %s. The response is not valid: the instance id or the status are missing", instanceId) - } - switch *s.Status { - case INSTANCESTATUS_ACTIVE: - return true, s, nil - case INSTANCESTATUS_FAILED: - return true, s, fmt.Errorf("update failed for instance with id %s: %s", instanceId, s.LastOperation.Description) - } - return false, nil, nil - }) - handler.SetTimeout(45 * time.Minute) - return handler + return createOrUpdateInstanceWaitHandler(ctx, a, projectId, instanceId) } // DeleteInstanceWaitHandler will wait for instance deletion @@ -144,3 +111,24 @@ func DeleteCredentialsWaitHandler(ctx context.Context, a opensearch.DefaultAPI, handler.SetTimeout(1 * time.Minute) return handler } + +func createOrUpdateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] { + waitConfig := wait.WaiterHelper[opensearch.Instance, string]{ + FetchInstance: a.GetInstance(ctx, projectId, instanceId).Execute, + GetState: func(s *opensearch.Instance) (string, error) { + if s == nil { + return "", errors.New("empty response") + } + if s.Status == nil { + return "", errors.New("status is missing") + } + return *s.Status, nil + }, + ActiveState: []string{INSTANCESTATUS_ACTIVE}, + ErrorState: []string{INSTANCESTATUS_FAILED}, + } + + handler := wait.New(waitConfig.Wait()) + handler.SetTimeout(45 * time.Minute) + return handler +} diff --git a/services/opensearch/v1api/wait/wait_test.go b/services/opensearch/v1api/wait/wait_test.go index b2c675830..6880cddc1 100644 --- a/services/opensearch/v1api/wait/wait_test.go +++ b/services/opensearch/v1api/wait/wait_test.go @@ -2,6 +2,7 @@ package wait import ( "context" + "fmt" "testing" "testing/synctest" "time" @@ -10,6 +11,7 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/core/utils" + "github.com/stackitcloud/stackit-sdk-go/core/wait" opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v1api" ) @@ -77,7 +79,7 @@ func newAPIMock(settings *mockSettings) opensearch.DefaultAPI { } } -func TestCreateInstanceWaitHandler(t *testing.T) { +func TestCreateOrUpdateInstanceWaitHandler(t *testing.T) { tests := []struct { desc string getFails bool @@ -86,14 +88,14 @@ func TestCreateInstanceWaitHandler(t *testing.T) { wantResp bool }{ { - desc: "create_succeeded", + desc: "succeeded", getFails: false, resourceState: utils.Ptr(INSTANCESTATUS_ACTIVE), wantErr: false, wantResp: true, }, { - desc: "create_failed", + desc: "failed", getFails: false, resourceState: utils.Ptr(INSTANCESTATUS_FAILED), wantErr: true, @@ -113,108 +115,46 @@ func TestCreateInstanceWaitHandler(t *testing.T) { wantResp: false, }, } - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - synctest.Test(t, func(t *testing.T) { - instanceId := "foo-bar" - - apiClient := newAPIMock(&mockSettings{ - instanceGetFails: tt.getFails, - instanceResourceId: instanceId, - instanceResourceState: tt.resourceState, - }) - - var wantRes *opensearch.Instance - if tt.wantResp { - wantRes = &opensearch.Instance{ - InstanceId: &instanceId, - Status: tt.resourceState, - } - } - - handler := CreateInstanceWaitHandler(context.Background(), apiClient, "pid", instanceId) - - gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background()) - - if (err != nil) != tt.wantErr { - t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr) - } - diff := cmp.Diff(gotRes, wantRes) - if diff != "" { - t.Fatalf("handler gotRes = %+v\n want %+v\n diff = %s", gotRes, wantRes, diff) - } - }) - }) - } -} -func TestUpdateInstanceWaitHandler(t *testing.T) { - tests := []struct { - desc string - getFails bool - resourceState *string - wantErr bool - wantResp bool - }{ - { - desc: "update_succeeded", - getFails: false, - resourceState: utils.Ptr(INSTANCESTATUS_ACTIVE), - wantErr: false, - wantResp: true, - }, - { - desc: "update_failed", - getFails: false, - resourceState: utils.Ptr(INSTANCESTATUS_FAILED), - wantErr: true, - wantResp: true, - }, - { - desc: "get_fails", - getFails: true, - wantErr: true, - wantResp: false, - }, - { - desc: "timeout", - getFails: false, - resourceState: utils.Ptr("ANOTHER STATE"), - wantErr: true, - wantResp: false, - }, + handlers := map[string]func(context.Context, opensearch.DefaultAPI, string, string) *wait.AsyncActionHandler[opensearch.Instance]{ + "common logic": createOrUpdateInstanceWaitHandler, + "create": CreateInstanceWaitHandler, + "update": PartialUpdateInstanceWaitHandler, } - for _, tt := range tests { - t.Run(tt.desc, func(t *testing.T) { - synctest.Test(t, func(t *testing.T) { - instanceId := "foo-bar" - - apiClient := newAPIMock(&mockSettings{ - instanceGetFails: tt.getFails, - instanceResourceId: instanceId, - instanceResourceState: tt.resourceState, - }) - var wantRes *opensearch.Instance - if tt.wantResp { - wantRes = &opensearch.Instance{ - InstanceId: &instanceId, - Status: tt.resourceState, + for handlerDesc, handlerFn := range handlers { + for _, tt := range tests { + t.Run(fmt.Sprintf("%s - %s", handlerDesc, tt.desc), func(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + instanceId := "foo-bar" + + apiClient := newAPIMock(&mockSettings{ + instanceGetFails: tt.getFails, + instanceResourceId: instanceId, + instanceResourceState: tt.resourceState, + }) + + var wantRes *opensearch.Instance + if tt.wantResp { + wantRes = &opensearch.Instance{ + InstanceId: &instanceId, + Status: tt.resourceState, + } } - } - handler := PartialUpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceId) + handler := handlerFn(context.Background(), apiClient, "pid", instanceId) + gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background()) - gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background()) - - if (err != nil) != tt.wantErr { - t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr) - } - if !cmp.Equal(gotRes, wantRes) { - t.Fatalf("handler gotRes = %v, want %v", gotRes, wantRes) - } + if (err != nil) != tt.wantErr { + t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr) + } + diff := cmp.Diff(gotRes, wantRes) + if diff != "" { + t.Fatalf("handler gotRes = %+v\n want %+v\n diff = %s", gotRes, wantRes, diff) + } + }) }) - }) + } } }