fix: builder and sdk changes (#81)
Some checks failed
Publish / Check GoReleaser config (push) Successful in 8s
Publish / Publish provider (push) Failing after 20s

## Description

<!-- **Please link some issue here describing what you are trying to achieve.**

In case there is no issue present for your PR, please consider creating one.
At least please give us some description what you are trying to achieve and why your change is needed. -->

relates to #1234

## Checklist

- [ ] Issue was linked above
- [ ] Code format was applied: `make fmt`
- [ ] Examples were added / adjusted (see `examples/` directory)
- [x] Docs are up-to-date: `make generate-docs` (will be checked by CI)
- [ ] Unit tests got implemented or updated
- [ ] Acceptance tests got implemented or updated (see e.g. [here](f5f99d1709/stackit/internal/services/dns/dns_acc_test.go))
- [x] Unit tests are passing: `make test` (will be checked by CI)
- [x] No linter issues: `make lint` (will be checked by CI)

Co-authored-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
Co-authored-by: marcel.henselin <marcel.henselin@stackit.cloud>
Reviewed-on: #81
This commit is contained in:
Marcel_Henselin 2026-03-11 13:13:46 +00:00
parent 635a9abf20
commit 1033d7e034
Signed by: tf-provider.git.onstackit.cloud
GPG key ID: 6D7E8A1ED8955A9C
145 changed files with 5944 additions and 5298 deletions

View file

@ -11,13 +11,13 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalpha2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/datasources_gen"
pgDsGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/datasources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
)
// Ensure the implementation satisfies the expected interfaces.
@ -32,13 +32,13 @@ func NewDatabaseDataSource() datasource.DataSource {
// dataSourceModel maps the data source schema data.
type dataSourceModel struct {
postgresflexalpha2.DatabaseModel
pgDsGen.DatabaseModel
TerraformID types.String `tfsdk:"id"`
}
// databaseDataSource is the data source implementation.
type databaseDataSource struct {
client *postgresflexalpha.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -73,7 +73,7 @@ func (r *databaseDataSource) Configure(
// Schema defines the schema for the data source.
func (r *databaseDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
s := postgresflexalpha2.DatabaseDataSourceSchema(ctx)
s := pgDsGen.DatabaseDataSourceSchema(ctx)
s.Attributes["id"] = schema.StringAttribute{
Description: "Terraform's internal resource ID. It is structured as \\\"`project_id`,`region`,`instance_id`," +
"`database_id`\\\".\",",
@ -144,7 +144,7 @@ func (r *databaseDataSource) getDatabaseByNameOrID(
model *dataSourceModel,
projectId, region, instanceId string,
diags *diag.Diagnostics,
) (*postgresflexalpha.ListDatabase, error) {
) (*v3alpha1api.ListDatabase, error) {
isIdSet := !model.DatabaseId.IsNull() && !model.DatabaseId.IsUnknown()
isNameSet := !model.Name.IsNull() && !model.Name.IsUnknown()
@ -159,12 +159,12 @@ func (r *databaseDataSource) getDatabaseByNameOrID(
if isIdSet {
databaseId := model.DatabaseId.ValueInt64()
ctx = tflog.SetField(ctx, "database_id", databaseId)
return getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId)
return getDatabaseById(ctx, r.client.DefaultAPI, projectId, region, instanceId, databaseId)
}
databaseName := model.Name.ValueString()
ctx = tflog.SetField(ctx, "name", databaseName)
return getDatabaseByName(ctx, r.client, projectId, region, instanceId, databaseName)
return getDatabaseByName(ctx, r.client.DefaultAPI, projectId, region, instanceId, databaseName)
}
// handleReadError centralizes API error handling for the Read operation.

View file

@ -5,7 +5,7 @@ import (
"fmt"
"strings"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
// databaseClientReader represents the contract to listing databases from postgresflex.APIClient.
@ -15,7 +15,7 @@ type databaseClientReader interface {
projectId string,
region string,
instanceId string,
) postgresflex.ApiListDatabasesRequestRequest
) v3alpha1api.ApiListDatabasesRequestRequest
}
// getDatabaseById gets a database by its ID.
@ -24,9 +24,9 @@ func getDatabaseById(
client databaseClientReader,
projectId, region, instanceId string,
databaseId int64,
) (*postgresflex.ListDatabase, error) {
filter := func(db postgresflex.ListDatabase) bool {
return db.Id != nil && *db.Id == databaseId
) (*v3alpha1api.ListDatabase, error) {
filter := func(db v3alpha1api.ListDatabase) bool {
return int64(db.Id) == databaseId
}
return getDatabase(ctx, client, projectId, region, instanceId, filter)
}
@ -36,9 +36,9 @@ func getDatabaseByName(
ctx context.Context,
client databaseClientReader,
projectId, region, instanceId, databaseName string,
) (*postgresflex.ListDatabase, error) {
filter := func(db postgresflex.ListDatabase) bool {
return db.Name != nil && *db.Name == databaseName
) (*v3alpha1api.ListDatabase, error) {
filter := func(db v3alpha1api.ListDatabase) bool {
return db.Name == databaseName
}
return getDatabase(ctx, client, projectId, region, instanceId, filter)
}
@ -49,8 +49,8 @@ func getDatabase(
ctx context.Context,
client databaseClientReader,
projectId, region, instanceId string,
filter func(db postgresflex.ListDatabase) bool,
) (*postgresflex.ListDatabase, error) {
filter func(db v3alpha1api.ListDatabase) bool,
) (*v3alpha1api.ListDatabase, error) {
if projectId == "" || region == "" || instanceId == "" {
return nil, fmt.Errorf("all parameters (project, region, instance) are required")
}
@ -59,18 +59,18 @@ func getDatabase(
for page := int32(1); ; page++ {
res, err := client.ListDatabasesRequest(ctx, projectId, region, instanceId).
Page(page).Size(pageSize).Sort(postgresflex.DATABASESORT_DATABASE_ID_ASC).Execute()
Page(page).Size(pageSize).Sort(v3alpha1api.DATABASESORT_DATABASE_ID_ASC).Execute()
if err != nil {
return nil, fmt.Errorf("requesting database list (page %d): %w", page, err)
}
// If the API returns no databases, we have reached the end of the list.
if res.Databases == nil || len(*res.Databases) == 0 {
if len(res.Databases) == 0 {
break
}
// Iterate over databases to find a match
for _, db := range *res.Databases {
for _, db := range res.Databases {
if filter(db) {
foundDb := db
return &foundDb, nil
@ -82,10 +82,6 @@ func getDatabase(
}
// cleanString removes leading and trailing quotes which are sometimes returned by the API.
func cleanString(s *string) *string {
if s == nil {
return nil
}
res := strings.Trim(*s, "\"")
return &res
func cleanString(s string) string {
return strings.Trim(s, "\"")
}

View file

@ -5,127 +5,99 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
type mockRequest struct {
executeFunc func() (*postgresflex.ListDatabasesResponse, error)
}
func (m *mockRequest) Page(_ int32) postgresflex.ApiListDatabasesRequestRequest { return m }
func (m *mockRequest) Size(_ int32) postgresflex.ApiListDatabasesRequestRequest { return m }
func (m *mockRequest) Sort(_ postgresflex.DatabaseSort) postgresflex.ApiListDatabasesRequestRequest {
return m
}
func (m *mockRequest) Execute() (*postgresflex.ListDatabasesResponse, error) {
return m.executeFunc()
}
type mockDBClient struct {
executeRequest func() postgresflex.ApiListDatabasesRequestRequest
}
var _ databaseClientReader = (*mockDBClient)(nil)
func (m *mockDBClient) ListDatabasesRequest(
_ context.Context,
_, _, _ string,
) postgresflex.ApiListDatabasesRequestRequest {
return m.executeRequest()
}
func TestGetDatabase(t *testing.T) {
mockResp := func(page int64) (*postgresflex.ListDatabasesResponse, error) {
mockResp := func(page int32) (*v3alpha1api.ListDatabasesResponse, error) {
if page == 1 {
return &postgresflex.ListDatabasesResponse{
Databases: &[]postgresflex.ListDatabase{
{Id: utils.Ptr(int64(1)), Name: utils.Ptr("first")},
{Id: utils.Ptr(int64(2)), Name: utils.Ptr("second")},
return &v3alpha1api.ListDatabasesResponse{
Databases: []v3alpha1api.ListDatabase{
{Id: int32(1), Name: "first"},
{Id: int32(2), Name: "second"},
},
Pagination: &postgresflex.Pagination{
Page: utils.Ptr(int64(1)),
TotalPages: utils.Ptr(int64(2)),
Size: utils.Ptr(int64(3)),
Pagination: v3alpha1api.Pagination{
Page: int32(1),
TotalPages: int32(2),
Size: int32(3),
},
}, nil
}
if page == 2 {
return &postgresflex.ListDatabasesResponse{
Databases: &[]postgresflex.ListDatabase{{Id: utils.Ptr(int64(3)), Name: utils.Ptr("three")}},
Pagination: &postgresflex.Pagination{
Page: utils.Ptr(int64(2)),
TotalPages: utils.Ptr(int64(2)),
Size: utils.Ptr(int64(3)),
return &v3alpha1api.ListDatabasesResponse{
Databases: []v3alpha1api.ListDatabase{{Id: int32(3), Name: "three"}},
Pagination: v3alpha1api.Pagination{
Page: int32(2),
TotalPages: int32(2),
Size: int32(3),
},
}, nil
}
return &postgresflex.ListDatabasesResponse{
Databases: &[]postgresflex.ListDatabase{},
Pagination: &postgresflex.Pagination{
Page: utils.Ptr(int64(3)),
TotalPages: utils.Ptr(int64(2)),
Size: utils.Ptr(int64(3)),
return &v3alpha1api.ListDatabasesResponse{
Databases: []v3alpha1api.ListDatabase{},
Pagination: v3alpha1api.Pagination{
Page: int32(3),
TotalPages: int32(2),
Size: int32(3),
},
}, nil
}
tests := []struct {
description string
projectId string
projectID string
region string
instanceId string
instanceID string
wantErr bool
wantDbName string
wantDbId int64
wantDbID int32
}{
{
description: "Success - Found by name on first page",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantErr: false,
wantDbName: "second",
},
{
description: "Success - Found by id on first page",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantErr: false,
wantDbId: 2,
wantDbID: 2,
},
{
description: "Success - Found by name on second page",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantErr: false,
wantDbName: "three",
},
{
description: "Success - Found by id on second page",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantErr: false,
wantDbId: 1,
wantDbID: 1,
},
{
description: "Error - API failure",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantErr: true,
},
{
description: "Error - Missing parameters",
projectId: "", region: "reg", instanceId: "inst",
projectID: "", region: "reg", instanceID: "inst",
wantErr: true,
},
{
description: "Error - Search by name not found after all pages",
projectId: "pid", region: "reg", instanceId: "inst",
projectID: "pid", region: "reg", instanceID: "inst",
wantDbName: "non-existent",
wantErr: true,
},
{
description: "Error - Search by id not found after all pages",
projectId: "pid", region: "reg", instanceId: "inst",
wantDbId: 999999,
projectID: "pid", region: "reg", instanceID: "inst",
wantDbID: 999999,
wantErr: true,
},
}
@ -133,47 +105,46 @@ func TestGetDatabase(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.description, func(t *testing.T) {
var currentPage int64
client := &mockDBClient{
executeRequest: func() postgresflex.ApiListDatabasesRequestRequest {
return &mockRequest{
executeFunc: func() (*postgresflex.ListDatabasesResponse, error) {
currentPage++
return mockResp(currentPage)
},
}
},
var currentPage int32
mockCall := func(_ v3alpha1api.ApiListDatabasesRequestRequest) (*v3alpha1api.ListDatabasesResponse, error) {
currentPage++
return mockResp(currentPage)
}
var actual *postgresflex.ListDatabase
client := &v3alpha1api.DefaultAPIServiceMock{
ListDatabasesRequestExecuteMock: &mockCall,
}
var actual *v3alpha1api.ListDatabase
var errDB error
if tt.wantDbName != "" {
actual, errDB = getDatabaseByName(
t.Context(),
client,
tt.projectId,
tt.projectID,
tt.region,
tt.instanceId,
tt.instanceID,
tt.wantDbName,
)
} else if tt.wantDbId != 0 {
} else if tt.wantDbID != 0 {
actual, errDB = getDatabaseById(
t.Context(),
client,
tt.projectId,
tt.projectID,
tt.region,
tt.instanceId,
tt.wantDbId,
tt.instanceID,
int64(tt.wantDbID),
)
} else {
actual, errDB = getDatabase(
context.Background(),
client,
tt.projectId,
tt.projectID,
tt.region,
tt.instanceId,
func(_ postgresflex.ListDatabase) bool { return false },
tt.instanceID,
func(_ v3alpha1api.ListDatabase) bool { return false },
)
}
@ -182,14 +153,14 @@ func TestGetDatabase(t *testing.T) {
return
}
if !tt.wantErr && tt.wantDbName != "" && actual != nil {
if *actual.Name != tt.wantDbName {
t.Errorf("getDatabaseByNameOrID() got name = %v, want %v", *actual.Name, tt.wantDbName)
if actual.Name != tt.wantDbName {
t.Errorf("getDatabaseByNameOrID() got name = %v, want %v", actual.Name, tt.wantDbName)
}
}
if !tt.wantErr && tt.wantDbId != 0 && actual != nil {
if *actual.Id != tt.wantDbId {
t.Errorf("getDatabaseByNameOrID() got id = %v, want %v", *actual.Id, tt.wantDbId)
if !tt.wantErr && tt.wantDbID != 0 && actual != nil {
if actual.Id != tt.wantDbID {
t.Errorf("getDatabaseByNameOrID() got id = %v, want %v", actual.Id, tt.wantDbID)
}
}
},
@ -200,23 +171,18 @@ func TestGetDatabase(t *testing.T) {
func TestCleanString(t *testing.T) {
testcases := []struct {
name string
given *string
expected *string
given string
expected string
}{
{
name: "should remove quotes",
given: utils.Ptr("\"quoted\""),
expected: utils.Ptr("quoted"),
},
{
name: "should handle nil",
given: nil,
expected: nil,
given: "\"quoted\"",
expected: "quoted",
},
{
name: "should not change unquoted string",
given: utils.Ptr("unquoted"),
expected: utils.Ptr("unquoted"),
given: "unquoted",
expected: "unquoted",
},
}

View file

@ -5,21 +5,21 @@ import (
"strconv"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
// mapFields maps fields from a ListDatabase API response to a resourceModel for the data source.
func mapFields(
source *postgresflexalpha.ListDatabase,
source *v3alpha1api.ListDatabase,
model *dataSourceModel,
region string,
) error {
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -29,8 +29,8 @@ func mapFields(
var databaseId int64
if model.DatabaseId.ValueInt64() != 0 {
databaseId = model.DatabaseId.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = int64(source.Id)
} else {
return fmt.Errorf("database id not present")
}
@ -38,7 +38,7 @@ func mapFields(
model.Id = types.Int64Value(databaseId)
model.DatabaseId = types.Int64Value(databaseId)
model.Name = types.StringValue(source.GetName())
model.Owner = types.StringPointerValue(cleanString(source.Owner))
model.Owner = types.StringValue(cleanString(source.Owner))
model.Region = types.StringValue(region)
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
@ -53,11 +53,11 @@ func mapFields(
}
// mapResourceFields maps fields from a GetDatabase API response to a resourceModel for the resource.
func mapResourceFields(source *postgresflexalpha.GetDatabaseResponse, model *resourceModel) error {
func mapResourceFields(source *v3alpha1api.GetDatabaseResponse, model *resourceModel) error {
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -67,8 +67,8 @@ func mapResourceFields(source *postgresflexalpha.GetDatabaseResponse, model *res
var databaseId int64
if model.Id.ValueInt64() != 0 {
databaseId = model.Id.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = int64(source.Id)
} else {
return fmt.Errorf("database id not present")
}
@ -76,18 +76,18 @@ func mapResourceFields(source *postgresflexalpha.GetDatabaseResponse, model *res
model.Id = types.Int64Value(databaseId)
model.DatabaseId = types.Int64Value(databaseId)
model.Name = types.StringValue(source.GetName())
model.Owner = types.StringPointerValue(cleanString(source.Owner))
model.Owner = types.StringValue(cleanString(source.Owner))
return nil
}
// toCreatePayload converts the resource model to an API create payload.
func toCreatePayload(model *resourceModel) (*postgresflexalpha.CreateDatabaseRequestPayload, error) {
func toCreatePayload(model *resourceModel) (*v3alpha1api.CreateDatabaseRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
return &postgresflexalpha.CreateDatabaseRequestPayload{
Name: model.Name.ValueStringPointer(),
return &v3alpha1api.CreateDatabaseRequestPayload{
Name: model.Name.ValueString(),
Owner: model.Owner.ValueStringPointer(),
}, nil
}

View file

@ -7,7 +7,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflexalpha "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
datasource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/datasources_gen"
)
@ -31,9 +32,9 @@ func TestMapFields(t *testing.T) {
name: "should map fields correctly",
given: given{
source: &postgresflexalpha.ListDatabase{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("\"my-owner\""),
Id: int32(1),
Name: "my-db",
Owner: "my-owner",
},
model: &dataSourceModel{
DatabaseModel: datasource.DatabaseModel{
@ -62,8 +63,8 @@ func TestMapFields(t *testing.T) {
name: "should preserve existing model ID",
given: given{
source: &postgresflexalpha.ListDatabase{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
Id: int32(1),
Name: "my-db",
},
model: &dataSourceModel{
DatabaseModel: datasource.DatabaseModel{
@ -77,9 +78,10 @@ func TestMapFields(t *testing.T) {
expected: expected{
model: &dataSourceModel{
DatabaseModel: datasource.DatabaseModel{
Id: types.Int64Value(1),
Name: types.StringValue("my-db"),
Owner: types.StringNull(), DatabaseId: types.Int64Value(1),
Id: types.Int64Value(1),
Name: types.StringValue("my-db"),
Owner: types.StringValue(""),
DatabaseId: types.Int64Value(1),
Region: types.StringValue("eu01"),
InstanceId: types.StringValue("my-instance"),
ProjectId: types.StringValue("my-project"),
@ -99,7 +101,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil source ID",
given: given{
source: &postgresflexalpha.ListDatabase{Id: nil},
source: &postgresflexalpha.ListDatabase{Id: 0},
model: &dataSourceModel{},
},
expected: expected{err: true},
@ -107,7 +109,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil model",
given: given{
source: &postgresflexalpha.ListDatabase{Id: utils.Ptr(int64(1))},
source: &postgresflexalpha.ListDatabase{Id: int32(1)},
model: nil,
},
expected: expected{err: true},
@ -150,9 +152,9 @@ func TestMapResourceFields(t *testing.T) {
name: "should map fields correctly",
given: given{
source: &postgresflexalpha.GetDatabaseResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("my-owner"),
Id: int32(1),
Name: "my-db",
Owner: "my-owner",
},
model: &resourceModel{},
},
@ -216,7 +218,7 @@ func TestToCreatePayload(t *testing.T) {
},
expected: expected{
payload: &postgresflexalpha.CreateDatabaseRequestPayload{
Name: utils.Ptr("my-db"),
Name: "my-db",
Owner: utils.Ptr("my-owner"),
},
},

View file

@ -14,14 +14,14 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalpha2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/resources_gen"
postgresflexalphaResGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database/resources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
postgresflexalpha3 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
postgresflexalphaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
)
var (
@ -43,7 +43,7 @@ func NewDatabaseResource() resource.Resource {
}
// resourceModel describes the resource data model.
type resourceModel = postgresflexalpha2.DatabaseModel
type resourceModel = postgresflexalphaResGen.DatabaseModel
// DatabaseResourceIdentityModel describes the resource's identity attributes.
type DatabaseResourceIdentityModel struct {
@ -55,7 +55,7 @@ type DatabaseResourceIdentityModel struct {
// databaseResource is the resource implementation.
type databaseResource struct {
client *postgresflexalpha.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -122,7 +122,7 @@ var modifiersFileByte []byte
// Schema defines the schema for the resource.
func (r *databaseResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
s := postgresflexalpha2.DatabaseResourceSchema(ctx)
s := postgresflexalphaResGen.DatabaseResourceSchema(ctx)
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
if err != nil {
@ -198,7 +198,7 @@ func (r *databaseResource) Create(
return
}
// Create new database
databaseResp, err := r.client.CreateDatabaseRequest(
databaseResp, err := r.client.DefaultAPI.CreateDatabaseRequest(
ctx,
projectId,
region,
@ -209,16 +209,17 @@ func (r *databaseResource) Create(
return
}
if databaseResp == nil || databaseResp.Id == nil {
dbID, ok := databaseResp.GetIdOk()
if !ok {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
funcErrorSummary,
"API didn't return database Id. A database might have been created",
"API didn't return database Id. A database might although have been created",
)
return
}
databaseId := *databaseResp.Id
databaseId := int64(*dbID)
ctx = tflog.SetField(ctx, "database_id", databaseId)
ctx = core.LogResponse(ctx)
@ -234,7 +235,7 @@ func (r *databaseResource) Create(
return
}
database, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, instanceId, region, databaseId).
database, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region, databaseId).
SetTimeout(15 * time.Minute).
SetSleepBeforeWait(15 * time.Second).
WaitWithContext(ctx)
@ -293,7 +294,7 @@ func (r *databaseResource) Read(
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "database_id", databaseId)
databaseResp, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, instanceId, region, databaseId).
databaseResp, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region, databaseId).
SetTimeout(15 * time.Minute).
SetSleepBeforeWait(15 * time.Second).
WaitWithContext(ctx)
@ -321,13 +322,12 @@ func (r *databaseResource) Read(
return
}
// TODO: use values from api to identify drift
// Save identity into Terraform state
identity := DatabaseResourceIdentityModel{
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
DatabaseID: types.Int64Value(databaseId),
DatabaseID: types.Int64Value(int64(databaseResp.GetId())),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -361,13 +361,7 @@ func (r *databaseResource) Update(
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
region := model.Region.ValueString()
databaseId64 := model.DatabaseId.ValueInt64()
if databaseId64 > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error in type conversion", "int value too large (databaseId)")
return
}
databaseId := int32(databaseId64) // nolint:gosec // check is performed above
databaseId := model.DatabaseId.ValueInt64()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
@ -383,7 +377,7 @@ func (r *databaseResource) Update(
}
modified := false
var payload postgresflexalpha.UpdateDatabasePartiallyRequestPayload
var payload v3alpha1api.UpdateDatabasePartiallyRequestPayload
if stateModel.Name != model.Name {
payload.Name = model.Name.ValueStringPointer()
modified = true
@ -399,13 +393,18 @@ func (r *databaseResource) Update(
return
}
if databaseId > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "error updating database", "databaseID out of bounds for int32")
return
}
databaseID32 := int32(databaseId) //nolint:gosec // TODO
// Update existing database
err := r.client.UpdateDatabasePartiallyRequest(
err := r.client.DefaultAPI.UpdateDatabasePartiallyRequest(
ctx,
projectId,
region,
instanceId,
databaseId,
databaseID32,
).UpdateDatabasePartiallyRequestPayload(payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "error updating database", err.Error())
@ -414,7 +413,7 @@ func (r *databaseResource) Update(
ctx = core.LogResponse(ctx)
databaseResp, err := postgresflexalpha3.GetDatabaseByIdWaitHandler(ctx, r.client, projectId, instanceId, region, databaseId64).
databaseResp, err := postgresflexalphaWait.GetDatabaseByIdWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region, databaseId).
SetTimeout(15 * time.Minute).
SetSleepBeforeWait(15 * time.Second).
WaitWithContext(ctx)
@ -442,7 +441,7 @@ func (r *databaseResource) Update(
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
DatabaseID: types.Int64Value(databaseId64),
DatabaseID: types.Int64Value(databaseId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -500,7 +499,7 @@ func (r *databaseResource) Delete(
ctx = tflog.SetField(ctx, "database_id", databaseId)
// Delete existing record set
err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseId)
err := r.client.DefaultAPI.DeleteDatabaseRequest(ctx, projectId, region, instanceId, databaseId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting database", fmt.Sprintf("Calling API: %v", err))
}

View file

@ -1,4 +1,4 @@
package postgresFlexAlphaFlavor
package postgresflexalphaflavor
import (
"context"
@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
postgresflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavors/datasources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
@ -30,13 +30,13 @@ type FlavorModel struct {
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
StorageClass types.String `tfsdk:"storage_class"`
Cpu types.Int64 `tfsdk:"cpu"`
Cpu types.Int32 `tfsdk:"cpu"`
Description types.String `tfsdk:"description"`
Id types.String `tfsdk:"id"`
FlavorId types.String `tfsdk:"flavor_id"`
MaxGb types.Int64 `tfsdk:"max_gb"`
Memory types.Int64 `tfsdk:"ram"`
MinGb types.Int64 `tfsdk:"min_gb"`
MaxGb types.Int32 `tfsdk:"max_gb"`
Memory types.Int32 `tfsdk:"ram"`
MinGb types.Int32 `tfsdk:"min_gb"`
NodeType types.String `tfsdk:"node_type"`
StorageClasses types.List `tfsdk:"storage_classes"`
}
@ -48,7 +48,7 @@ func NewFlavorDataSource() datasource.DataSource {
// flavorDataSource is the data source implementation.
type flavorDataSource struct {
client *postgresflexalpha.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -86,12 +86,12 @@ func (r *flavorDataSource) Schema(ctx context.Context, _ datasource.SchemaReques
Description: "The flavor description.",
MarkdownDescription: "The flavor description.",
},
"cpu": schema.Int64Attribute{
"cpu": schema.Int32Attribute{
Required: true,
Description: "The cpu count of the instance.",
MarkdownDescription: "The cpu count of the instance.",
},
"ram": schema.Int64Attribute{
"ram": schema.Int32Attribute{
Required: true,
Description: "The memory of the instance in Gibibyte.",
MarkdownDescription: "The memory of the instance in Gibibyte.",
@ -116,12 +116,12 @@ func (r *flavorDataSource) Schema(ctx context.Context, _ datasource.SchemaReques
Description: "The flavor id of the instance flavor.",
MarkdownDescription: "The flavor id of the instance flavor.",
},
"max_gb": schema.Int64Attribute{
"max_gb": schema.Int32Attribute{
Computed: true,
Description: "maximum storage which can be ordered for the flavor in Gigabyte.",
MarkdownDescription: "maximum storage which can be ordered for the flavor in Gigabyte.",
},
"min_gb": schema.Int64Attribute{
"min_gb": schema.Int32Attribute{
Computed: true,
Description: "minimum storage which is required to order in Gigabyte.",
MarkdownDescription: "minimum storage which is required to order in Gigabyte.",
@ -138,10 +138,10 @@ func (r *flavorDataSource) Schema(ctx context.Context, _ datasource.SchemaReques
"class": schema.StringAttribute{
Computed: true,
},
"max_io_per_sec": schema.Int64Attribute{
"max_io_per_sec": schema.Int32Attribute{
Computed: true,
},
"max_through_in_mb": schema.Int64Attribute{
"max_through_in_mb": schema.Int32Attribute{
Computed: true,
},
},
@ -171,25 +171,25 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
flavors, err := getAllFlavors(ctx, r.client, projectId, region)
flavors, err := getAllFlavors(ctx, r.client.DefaultAPI, projectId, region)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
return
}
var foundFlavors []postgresflexalpha.ListFlavors
var foundFlavors []v3alpha1api.ListFlavors
for _, flavor := range flavors {
if model.Cpu.ValueInt64() != *flavor.Cpu {
if model.Cpu.ValueInt32() != flavor.Cpu {
continue
}
if model.Memory.ValueInt64() != *flavor.Memory {
if model.Memory.ValueInt32() != flavor.Memory {
continue
}
if model.NodeType.ValueString() != *flavor.NodeType {
if model.NodeType.ValueString() != flavor.NodeType {
continue
}
for _, sc := range *flavor.StorageClasses {
if model.StorageClass.ValueString() != *sc.Class {
for _, sc := range flavor.StorageClasses {
if model.StorageClass.ValueString() != sc.Class {
continue
}
foundFlavors = append(foundFlavors, flavor)
@ -205,11 +205,11 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
}
f := foundFlavors[0]
model.Description = types.StringValue(*f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, *f.Id)
model.FlavorId = types.StringValue(*f.Id)
model.MaxGb = types.Int64Value(*f.MaxGB)
model.MinGb = types.Int64Value(*f.MinGB)
model.Description = types.StringValue(f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, f.Id)
model.FlavorId = types.StringValue(f.Id)
model.MaxGb = types.Int32Value(f.MaxGB)
model.MinGb = types.Int32Value(f.MinGB)
if f.StorageClasses == nil {
model.StorageClasses = types.ListNull(postgresflexalphaGen.StorageClassesType{
@ -219,15 +219,15 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
})
} else {
var scList []attr.Value
for _, sc := range *f.StorageClasses {
for _, sc := range f.StorageClasses {
scList = append(
scList,
postgresflexalphaGen.NewStorageClassesValueMust(
postgresflexalphaGen.StorageClassesValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"class": types.StringValue(*sc.Class),
"max_io_per_sec": types.Int64Value(*sc.MaxIoPerSec),
"max_through_in_mb": types.Int64Value(*sc.MaxThroughInMb),
"class": types.StringValue(sc.Class),
"max_io_per_sec": types.Int32Value(sc.MaxIoPerSec),
"max_through_in_mb": types.Int32Value(sc.MaxThroughInMb),
},
),
)

View file

@ -23,7 +23,7 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
"flavors": schema.ListNestedAttribute{
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"cpu": schema.Int64Attribute{
"cpu": schema.Int32Attribute{
Computed: true,
Description: "The cpu count of the instance.",
MarkdownDescription: "The cpu count of the instance.",
@ -38,17 +38,17 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
Description: "The id of the instance flavor.",
MarkdownDescription: "The id of the instance flavor.",
},
"max_gb": schema.Int64Attribute{
"max_gb": schema.Int32Attribute{
Computed: true,
Description: "maximum storage which can be ordered for the flavor in Gigabyte.",
MarkdownDescription: "maximum storage which can be ordered for the flavor in Gigabyte.",
},
"memory": schema.Int64Attribute{
"memory": schema.Int32Attribute{
Computed: true,
Description: "The memory of the instance in Gibibyte.",
MarkdownDescription: "The memory of the instance in Gibibyte.",
},
"min_gb": schema.Int64Attribute{
"min_gb": schema.Int32Attribute{
Computed: true,
Description: "minimum storage which is required to order in Gigabyte.",
MarkdownDescription: "minimum storage which is required to order in Gigabyte.",
@ -64,10 +64,10 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
"class": schema.StringAttribute{
Computed: true,
},
"max_io_per_sec": schema.Int64Attribute{
"max_io_per_sec": schema.Int32Attribute{
Computed: true,
},
"max_through_in_mb": schema.Int64Attribute{
"max_through_in_mb": schema.Int32Attribute{
Computed: true,
},
},
@ -92,7 +92,7 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
Description: "List of flavors available for the project.",
MarkdownDescription: "List of flavors available for the project.",
},
"page": schema.Int64Attribute{
"page": schema.Int32Attribute{
Optional: true,
Computed: true,
Description: "Number of the page of items list to be returned.",
@ -100,19 +100,19 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
},
"pagination": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"page": schema.Int64Attribute{
"page": schema.Int32Attribute{
Computed: true,
},
"size": schema.Int64Attribute{
"size": schema.Int32Attribute{
Computed: true,
},
"sort": schema.StringAttribute{
Computed: true,
},
"total_pages": schema.Int64Attribute{
"total_pages": schema.Int32Attribute{
Computed: true,
},
"total_rows": schema.Int64Attribute{
"total_rows": schema.Int32Attribute{
Computed: true,
},
},
@ -138,7 +138,7 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
),
},
},
"size": schema.Int64Attribute{
"size": schema.Int32Attribute{
Optional: true,
Computed: true,
Description: "Number of items to be returned on each page.",
@ -178,11 +178,11 @@ func FlavorsDataSourceSchema(ctx context.Context) schema.Schema {
type FlavorsModel struct {
Flavors types.List `tfsdk:"flavors"`
Page types.Int64 `tfsdk:"page"`
Page types.Int32 `tfsdk:"page"`
Pagination PaginationValue `tfsdk:"pagination"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Size types.Int64 `tfsdk:"size"`
Size types.Int32 `tfsdk:"size"`
Sort types.String `tfsdk:"sort"`
}
@ -221,12 +221,12 @@ func (t FlavorsType) ValueFromObject(ctx context.Context, in basetypes.ObjectVal
return nil, diags
}
cpuVal, ok := cpuAttribute.(basetypes.Int64Value)
cpuVal, ok := cpuAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`cpu expected to be basetypes.Int64Value, was: %T`, cpuAttribute))
fmt.Sprintf(`cpu expected to be basetypes.Int32Value, was: %T`, cpuAttribute))
}
descriptionAttribute, ok := attributes["description"]
@ -275,12 +275,12 @@ func (t FlavorsType) ValueFromObject(ctx context.Context, in basetypes.ObjectVal
return nil, diags
}
maxGbVal, ok := maxGbAttribute.(basetypes.Int64Value)
maxGbVal, ok := maxGbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_gb expected to be basetypes.Int64Value, was: %T`, maxGbAttribute))
fmt.Sprintf(`max_gb expected to be basetypes.Int32Value, was: %T`, maxGbAttribute))
}
memoryAttribute, ok := attributes["memory"]
@ -293,12 +293,12 @@ func (t FlavorsType) ValueFromObject(ctx context.Context, in basetypes.ObjectVal
return nil, diags
}
memoryVal, ok := memoryAttribute.(basetypes.Int64Value)
memoryVal, ok := memoryAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`memory expected to be basetypes.Int64Value, was: %T`, memoryAttribute))
fmt.Sprintf(`memory expected to be basetypes.Int32Value, was: %T`, memoryAttribute))
}
minGbAttribute, ok := attributes["min_gb"]
@ -311,12 +311,12 @@ func (t FlavorsType) ValueFromObject(ctx context.Context, in basetypes.ObjectVal
return nil, diags
}
minGbVal, ok := minGbAttribute.(basetypes.Int64Value)
minGbVal, ok := minGbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`min_gb expected to be basetypes.Int64Value, was: %T`, minGbAttribute))
fmt.Sprintf(`min_gb expected to be basetypes.Int32Value, was: %T`, minGbAttribute))
}
nodeTypeAttribute, ok := attributes["node_type"]
@ -445,12 +445,12 @@ func NewFlavorsValue(attributeTypes map[string]attr.Type, attributes map[string]
return NewFlavorsValueUnknown(), diags
}
cpuVal, ok := cpuAttribute.(basetypes.Int64Value)
cpuVal, ok := cpuAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`cpu expected to be basetypes.Int64Value, was: %T`, cpuAttribute))
fmt.Sprintf(`cpu expected to be basetypes.Int32Value, was: %T`, cpuAttribute))
}
descriptionAttribute, ok := attributes["description"]
@ -499,12 +499,12 @@ func NewFlavorsValue(attributeTypes map[string]attr.Type, attributes map[string]
return NewFlavorsValueUnknown(), diags
}
maxGbVal, ok := maxGbAttribute.(basetypes.Int64Value)
maxGbVal, ok := maxGbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_gb expected to be basetypes.Int64Value, was: %T`, maxGbAttribute))
fmt.Sprintf(`max_gb expected to be basetypes.Int32Value, was: %T`, maxGbAttribute))
}
memoryAttribute, ok := attributes["memory"]
@ -517,12 +517,12 @@ func NewFlavorsValue(attributeTypes map[string]attr.Type, attributes map[string]
return NewFlavorsValueUnknown(), diags
}
memoryVal, ok := memoryAttribute.(basetypes.Int64Value)
memoryVal, ok := memoryAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`memory expected to be basetypes.Int64Value, was: %T`, memoryAttribute))
fmt.Sprintf(`memory expected to be basetypes.Int32Value, was: %T`, memoryAttribute))
}
minGbAttribute, ok := attributes["min_gb"]
@ -535,12 +535,12 @@ func NewFlavorsValue(attributeTypes map[string]attr.Type, attributes map[string]
return NewFlavorsValueUnknown(), diags
}
minGbVal, ok := minGbAttribute.(basetypes.Int64Value)
minGbVal, ok := minGbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`min_gb expected to be basetypes.Int64Value, was: %T`, minGbAttribute))
fmt.Sprintf(`min_gb expected to be basetypes.Int32Value, was: %T`, minGbAttribute))
}
nodeTypeAttribute, ok := attributes["node_type"]
@ -664,12 +664,12 @@ func (t FlavorsType) ValueType(ctx context.Context) attr.Value {
var _ basetypes.ObjectValuable = FlavorsValue{}
type FlavorsValue struct {
Cpu basetypes.Int64Value `tfsdk:"cpu"`
Cpu basetypes.Int32Value `tfsdk:"cpu"`
Description basetypes.StringValue `tfsdk:"description"`
Id basetypes.StringValue `tfsdk:"id"`
MaxGb basetypes.Int64Value `tfsdk:"max_gb"`
Memory basetypes.Int64Value `tfsdk:"memory"`
MinGb basetypes.Int64Value `tfsdk:"min_gb"`
MaxGb basetypes.Int32Value `tfsdk:"max_gb"`
Memory basetypes.Int32Value `tfsdk:"memory"`
MinGb basetypes.Int32Value `tfsdk:"min_gb"`
NodeType basetypes.StringValue `tfsdk:"node_type"`
StorageClasses basetypes.ListValue `tfsdk:"storage_classes"`
state attr.ValueState
@ -681,12 +681,12 @@ func (v FlavorsValue) ToTerraformValue(ctx context.Context) (tftypes.Value, erro
var val tftypes.Value
var err error
attrTypes["cpu"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["cpu"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["description"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["id"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["max_gb"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["memory"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["min_gb"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["max_gb"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["memory"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["min_gb"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["node_type"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["storage_classes"] = basetypes.ListType{
ElemType: StorageClassesValue{}.Type(ctx),
@ -821,12 +821,12 @@ func (v FlavorsValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue,
}
attributeTypes := map[string]attr.Type{
"cpu": basetypes.Int64Type{},
"cpu": basetypes.Int32Type{},
"description": basetypes.StringType{},
"id": basetypes.StringType{},
"max_gb": basetypes.Int64Type{},
"memory": basetypes.Int64Type{},
"min_gb": basetypes.Int64Type{},
"max_gb": basetypes.Int32Type{},
"memory": basetypes.Int32Type{},
"min_gb": basetypes.Int32Type{},
"node_type": basetypes.StringType{},
"storage_classes": basetypes.ListType{
ElemType: StorageClassesValue{}.Type(ctx),
@ -917,12 +917,12 @@ func (v FlavorsValue) Type(ctx context.Context) attr.Type {
func (v FlavorsValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"cpu": basetypes.Int64Type{},
"cpu": basetypes.Int32Type{},
"description": basetypes.StringType{},
"id": basetypes.StringType{},
"max_gb": basetypes.Int64Type{},
"memory": basetypes.Int64Type{},
"min_gb": basetypes.Int64Type{},
"max_gb": basetypes.Int32Type{},
"memory": basetypes.Int32Type{},
"min_gb": basetypes.Int32Type{},
"node_type": basetypes.StringType{},
"storage_classes": basetypes.ListType{
ElemType: StorageClassesValue{}.Type(ctx),
@ -983,12 +983,12 @@ func (t StorageClassesType) ValueFromObject(ctx context.Context, in basetypes.Ob
return nil, diags
}
maxIoPerSecVal, ok := maxIoPerSecAttribute.(basetypes.Int64Value)
maxIoPerSecVal, ok := maxIoPerSecAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_io_per_sec expected to be basetypes.Int64Value, was: %T`, maxIoPerSecAttribute))
fmt.Sprintf(`max_io_per_sec expected to be basetypes.Int32Value, was: %T`, maxIoPerSecAttribute))
}
maxThroughInMbAttribute, ok := attributes["max_through_in_mb"]
@ -1001,12 +1001,12 @@ func (t StorageClassesType) ValueFromObject(ctx context.Context, in basetypes.Ob
return nil, diags
}
maxThroughInMbVal, ok := maxThroughInMbAttribute.(basetypes.Int64Value)
maxThroughInMbVal, ok := maxThroughInMbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_through_in_mb expected to be basetypes.Int64Value, was: %T`, maxThroughInMbAttribute))
fmt.Sprintf(`max_through_in_mb expected to be basetypes.Int32Value, was: %T`, maxThroughInMbAttribute))
}
if diags.HasError() {
@ -1112,12 +1112,12 @@ func NewStorageClassesValue(attributeTypes map[string]attr.Type, attributes map[
return NewStorageClassesValueUnknown(), diags
}
maxIoPerSecVal, ok := maxIoPerSecAttribute.(basetypes.Int64Value)
maxIoPerSecVal, ok := maxIoPerSecAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_io_per_sec expected to be basetypes.Int64Value, was: %T`, maxIoPerSecAttribute))
fmt.Sprintf(`max_io_per_sec expected to be basetypes.Int32Value, was: %T`, maxIoPerSecAttribute))
}
maxThroughInMbAttribute, ok := attributes["max_through_in_mb"]
@ -1130,12 +1130,12 @@ func NewStorageClassesValue(attributeTypes map[string]attr.Type, attributes map[
return NewStorageClassesValueUnknown(), diags
}
maxThroughInMbVal, ok := maxThroughInMbAttribute.(basetypes.Int64Value)
maxThroughInMbVal, ok := maxThroughInMbAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`max_through_in_mb expected to be basetypes.Int64Value, was: %T`, maxThroughInMbAttribute))
fmt.Sprintf(`max_through_in_mb expected to be basetypes.Int32Value, was: %T`, maxThroughInMbAttribute))
}
if diags.HasError() {
@ -1219,8 +1219,8 @@ var _ basetypes.ObjectValuable = StorageClassesValue{}
type StorageClassesValue struct {
Class basetypes.StringValue `tfsdk:"class"`
MaxIoPerSec basetypes.Int64Value `tfsdk:"max_io_per_sec"`
MaxThroughInMb basetypes.Int64Value `tfsdk:"max_through_in_mb"`
MaxIoPerSec basetypes.Int32Value `tfsdk:"max_io_per_sec"`
MaxThroughInMb basetypes.Int32Value `tfsdk:"max_through_in_mb"`
state attr.ValueState
}
@ -1231,8 +1231,8 @@ func (v StorageClassesValue) ToTerraformValue(ctx context.Context) (tftypes.Valu
var err error
attrTypes["class"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["max_io_per_sec"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["max_through_in_mb"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["max_io_per_sec"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["max_through_in_mb"] = basetypes.Int32Type{}.TerraformType(ctx)
objectType := tftypes.Object{AttributeTypes: attrTypes}
@ -1295,8 +1295,8 @@ func (v StorageClassesValue) ToObjectValue(ctx context.Context) (basetypes.Objec
attributeTypes := map[string]attr.Type{
"class": basetypes.StringType{},
"max_io_per_sec": basetypes.Int64Type{},
"max_through_in_mb": basetypes.Int64Type{},
"max_io_per_sec": basetypes.Int32Type{},
"max_through_in_mb": basetypes.Int32Type{},
}
if v.IsNull() {
@ -1359,8 +1359,8 @@ func (v StorageClassesValue) Type(ctx context.Context) attr.Type {
func (v StorageClassesValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"class": basetypes.StringType{},
"max_io_per_sec": basetypes.Int64Type{},
"max_through_in_mb": basetypes.Int64Type{},
"max_io_per_sec": basetypes.Int32Type{},
"max_through_in_mb": basetypes.Int32Type{},
}
}
@ -1399,12 +1399,12 @@ func (t PaginationType) ValueFromObject(ctx context.Context, in basetypes.Object
return nil, diags
}
pageVal, ok := pageAttribute.(basetypes.Int64Value)
pageVal, ok := pageAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`page expected to be basetypes.Int64Value, was: %T`, pageAttribute))
fmt.Sprintf(`page expected to be basetypes.Int32Value, was: %T`, pageAttribute))
}
sizeAttribute, ok := attributes["size"]
@ -1417,12 +1417,12 @@ func (t PaginationType) ValueFromObject(ctx context.Context, in basetypes.Object
return nil, diags
}
sizeVal, ok := sizeAttribute.(basetypes.Int64Value)
sizeVal, ok := sizeAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`size expected to be basetypes.Int64Value, was: %T`, sizeAttribute))
fmt.Sprintf(`size expected to be basetypes.Int32Value, was: %T`, sizeAttribute))
}
sortAttribute, ok := attributes["sort"]
@ -1453,12 +1453,12 @@ func (t PaginationType) ValueFromObject(ctx context.Context, in basetypes.Object
return nil, diags
}
totalPagesVal, ok := totalPagesAttribute.(basetypes.Int64Value)
totalPagesVal, ok := totalPagesAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`total_pages expected to be basetypes.Int64Value, was: %T`, totalPagesAttribute))
fmt.Sprintf(`total_pages expected to be basetypes.Int32Value, was: %T`, totalPagesAttribute))
}
totalRowsAttribute, ok := attributes["total_rows"]
@ -1471,12 +1471,12 @@ func (t PaginationType) ValueFromObject(ctx context.Context, in basetypes.Object
return nil, diags
}
totalRowsVal, ok := totalRowsAttribute.(basetypes.Int64Value)
totalRowsVal, ok := totalRowsAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`total_rows expected to be basetypes.Int64Value, was: %T`, totalRowsAttribute))
fmt.Sprintf(`total_rows expected to be basetypes.Int32Value, was: %T`, totalRowsAttribute))
}
if diags.HasError() {
@ -1566,12 +1566,12 @@ func NewPaginationValue(attributeTypes map[string]attr.Type, attributes map[stri
return NewPaginationValueUnknown(), diags
}
pageVal, ok := pageAttribute.(basetypes.Int64Value)
pageVal, ok := pageAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`page expected to be basetypes.Int64Value, was: %T`, pageAttribute))
fmt.Sprintf(`page expected to be basetypes.Int32Value, was: %T`, pageAttribute))
}
sizeAttribute, ok := attributes["size"]
@ -1584,12 +1584,12 @@ func NewPaginationValue(attributeTypes map[string]attr.Type, attributes map[stri
return NewPaginationValueUnknown(), diags
}
sizeVal, ok := sizeAttribute.(basetypes.Int64Value)
sizeVal, ok := sizeAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`size expected to be basetypes.Int64Value, was: %T`, sizeAttribute))
fmt.Sprintf(`size expected to be basetypes.Int32Value, was: %T`, sizeAttribute))
}
sortAttribute, ok := attributes["sort"]
@ -1620,12 +1620,12 @@ func NewPaginationValue(attributeTypes map[string]attr.Type, attributes map[stri
return NewPaginationValueUnknown(), diags
}
totalPagesVal, ok := totalPagesAttribute.(basetypes.Int64Value)
totalPagesVal, ok := totalPagesAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`total_pages expected to be basetypes.Int64Value, was: %T`, totalPagesAttribute))
fmt.Sprintf(`total_pages expected to be basetypes.Int32Value, was: %T`, totalPagesAttribute))
}
totalRowsAttribute, ok := attributes["total_rows"]
@ -1638,12 +1638,12 @@ func NewPaginationValue(attributeTypes map[string]attr.Type, attributes map[stri
return NewPaginationValueUnknown(), diags
}
totalRowsVal, ok := totalRowsAttribute.(basetypes.Int64Value)
totalRowsVal, ok := totalRowsAttribute.(basetypes.Int32Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`total_rows expected to be basetypes.Int64Value, was: %T`, totalRowsAttribute))
fmt.Sprintf(`total_rows expected to be basetypes.Int32Value, was: %T`, totalRowsAttribute))
}
if diags.HasError() {
@ -1728,11 +1728,11 @@ func (t PaginationType) ValueType(ctx context.Context) attr.Value {
var _ basetypes.ObjectValuable = PaginationValue{}
type PaginationValue struct {
Page basetypes.Int64Value `tfsdk:"page"`
Size basetypes.Int64Value `tfsdk:"size"`
Page basetypes.Int32Value `tfsdk:"page"`
Size basetypes.Int32Value `tfsdk:"size"`
Sort basetypes.StringValue `tfsdk:"sort"`
TotalPages basetypes.Int64Value `tfsdk:"total_pages"`
TotalRows basetypes.Int64Value `tfsdk:"total_rows"`
TotalPages basetypes.Int32Value `tfsdk:"total_pages"`
TotalRows basetypes.Int32Value `tfsdk:"total_rows"`
state attr.ValueState
}
@ -1742,11 +1742,11 @@ func (v PaginationValue) ToTerraformValue(ctx context.Context) (tftypes.Value, e
var val tftypes.Value
var err error
attrTypes["page"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["size"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["page"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["size"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["sort"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["total_pages"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["total_rows"] = basetypes.Int64Type{}.TerraformType(ctx)
attrTypes["total_pages"] = basetypes.Int32Type{}.TerraformType(ctx)
attrTypes["total_rows"] = basetypes.Int32Type{}.TerraformType(ctx)
objectType := tftypes.Object{AttributeTypes: attrTypes}
@ -1824,11 +1824,11 @@ func (v PaginationValue) ToObjectValue(ctx context.Context) (basetypes.ObjectVal
var diags diag.Diagnostics
attributeTypes := map[string]attr.Type{
"page": basetypes.Int64Type{},
"size": basetypes.Int64Type{},
"page": basetypes.Int32Type{},
"size": basetypes.Int32Type{},
"sort": basetypes.StringType{},
"total_pages": basetypes.Int64Type{},
"total_rows": basetypes.Int64Type{},
"total_pages": basetypes.Int32Type{},
"total_rows": basetypes.Int32Type{},
}
if v.IsNull() {
@ -1900,10 +1900,10 @@ func (v PaginationValue) Type(ctx context.Context) attr.Type {
func (v PaginationValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"page": basetypes.Int64Type{},
"size": basetypes.Int64Type{},
"page": basetypes.Int32Type{},
"size": basetypes.Int32Type{},
"sort": basetypes.StringType{},
"total_pages": basetypes.Int64Type{},
"total_rows": basetypes.Int64Type{},
"total_pages": basetypes.Int32Type{},
"total_rows": basetypes.Int32Type{},
}
}

View file

@ -1,24 +1,24 @@
package postgresFlexAlphaFlavor
package postgresflexalphaflavor
import (
"context"
"fmt"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
type flavorsClientReader interface {
GetFlavorsRequest(
ctx context.Context,
projectId, region string,
) postgresflex.ApiGetFlavorsRequestRequest
) v3alpha1api.ApiGetFlavorsRequestRequest
}
func getAllFlavors(ctx context.Context, client flavorsClientReader, projectId, region string) (
[]postgresflex.ListFlavors,
[]v3alpha1api.ListFlavors,
error,
) {
getAllFilter := func(_ postgresflex.ListFlavors) bool { return true }
getAllFilter := func(_ v3alpha1api.ListFlavors) bool { return true }
flavorList, err := getFlavorsByFilter(ctx, client, projectId, region, getAllFilter)
if err != nil {
return nil, err
@ -32,29 +32,29 @@ func getFlavorsByFilter(
ctx context.Context,
client flavorsClientReader,
projectId, region string,
filter func(db postgresflex.ListFlavors) bool,
) ([]postgresflex.ListFlavors, error) {
filter func(db v3alpha1api.ListFlavors) bool,
) ([]v3alpha1api.ListFlavors, error) {
if projectId == "" || region == "" {
return nil, fmt.Errorf("listing postgresflex flavors: projectId and region are required")
}
const pageSize = 25
var result = make([]postgresflex.ListFlavors, 0)
var result = make([]v3alpha1api.ListFlavors, 0)
for page := int32(1); ; page++ {
res, err := client.GetFlavorsRequest(ctx, projectId, region).
Page(page).Size(pageSize).Sort(postgresflex.FLAVORSORT_ID_ASC).Execute()
Page(page).Size(pageSize).Sort(v3alpha1api.FLAVORSORT_ID_ASC).Execute()
if err != nil {
return nil, fmt.Errorf("requesting flavors list (page %d): %w", page, err)
}
// If the API returns no flavors, we have reached the end of the list.
if res.Flavors == nil || len(*res.Flavors) == 0 {
if len(res.Flavors) == 0 {
break
}
for _, flavor := range *res.Flavors {
for _, flavor := range res.Flavors {
if filter(flavor) {
result = append(result, flavor)
}

View file

@ -1,12 +1,11 @@
package postgresFlexAlphaFlavor
package postgresflexalphaflavor
/*
import (
"context"
"testing"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
type mockRequest struct {
@ -30,25 +29,25 @@ func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) po
return m.executeRequest()
}
var mockResp = func(page int64) (*postgresflex.GetFlavorsResponse, error) {
var mockResp = func(page int32) (*postgresflex.GetFlavorsResponse, error) {
if page == 1 {
return &postgresflex.GetFlavorsResponse{
Flavors: &[]postgresflex.ListFlavors{
{Id: utils.Ptr("flavor-1"), Description: utils.Ptr("first")},
{Id: utils.Ptr("flavor-2"), Description: utils.Ptr("second")},
Flavors: []postgresflex.ListFlavors{
{Id: "flavor-1", Description: "first"},
{Id: "flavor-2", Description: "second"},
},
}, nil
}
if page == 2 {
return &postgresflex.GetFlavorsResponse{
Flavors: &[]postgresflex.ListFlavors{
{Id: utils.Ptr("flavor-3"), Description: utils.Ptr("three")},
Flavors: []postgresflex.ListFlavors{
{Id: "flavor-3", Description: "three"},
},
}, nil
}
return &postgresflex.GetFlavorsResponse{
Flavors: &[]postgresflex.ListFlavors{},
Flavors: []postgresflex.ListFlavors{},
}, nil
}
@ -72,7 +71,7 @@ func TestGetFlavorsByFilter(t *testing.T) {
{
description: "Success - Filter flavors by description",
projectId: "pid", region: "reg",
filter: func(f postgresflex.ListFlavors) bool { return *f.Description == "first" },
filter: func(f postgresflex.ListFlavors) bool { return f.Description == "first" },
wantCount: 1,
wantErr: false,
},
@ -86,10 +85,10 @@ func TestGetFlavorsByFilter(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.description, func(t *testing.T) {
var currentPage int64
var currentPage int32
client := &mockFlavorsClient{
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
return &mockRequest{
return mockRequest{
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
@ -113,10 +112,10 @@ func TestGetFlavorsByFilter(t *testing.T) {
}
func TestGetAllFlavors(t *testing.T) {
var currentPage int64
var currentPage int32
client := &mockFlavorsClient{
executeRequest: func() postgresflex.ApiGetFlavorsRequestRequest {
return &mockRequest{
return mockRequest{
executeFunc: func() (*postgresflex.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
@ -133,3 +132,4 @@ func TestGetAllFlavors(t *testing.T) {
t.Errorf("getAllFlavors() expected 3 flavor, got %d", len(res))
}
}
*/

View file

@ -5,8 +5,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavors/datasources_gen"
@ -26,7 +26,7 @@ func NewFlavorsDataSource() datasource.DataSource {
type dataSourceModel = postgresflexalphaGen.FlavorsModel
type flavorsDataSource struct {
client *postgresflexalpha.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}

View file

@ -6,8 +6,8 @@ import (
"net/http"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
postgresflexalpha2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/datasources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
@ -37,7 +37,7 @@ type dataSourceModel struct {
// instanceDataSource is the data source implementation.
type instanceDataSource struct {
client *postgresflexalpha.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -96,7 +96,7 @@ func (r *instanceDataSource) Read(
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "region", region)
instanceResp, err := r.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := r.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -28,8 +28,8 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
},
"backup_schedule": schema.StringAttribute{
Computed: true,
Description: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
Description: "The schedule for when the database backup will be created. Currently, ONLY daily schedules are supported (every 24 hours). The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for when the database backup will be created. Currently, ONLY daily schedules are supported (every 24 hours). The schedule is written as a cron schedule.",
},
"connection_info": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{

View file

@ -7,8 +7,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflexalphadatasource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/datasources_gen"
postgresflexalpharesource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
@ -33,9 +33,7 @@ func mapGetInstanceResponseToModel(
)
}
isConnectionInfoIncomplete := resp.ConnectionInfo == nil || resp.ConnectionInfo.Write == nil ||
resp.ConnectionInfo.Write.Host == nil || *resp.ConnectionInfo.Write.Host == "" ||
resp.ConnectionInfo.Write.Port == nil || *resp.ConnectionInfo.Write.Port == 0
isConnectionInfoIncomplete := resp.ConnectionInfo.Write.Host == "" || resp.ConnectionInfo.Write.Port == 0
if isConnectionInfoIncomplete {
m.ConnectionInfo = postgresflexalpharesource.NewConnectionInfoValueNull()
@ -43,11 +41,13 @@ func mapGetInstanceResponseToModel(
m.ConnectionInfo = postgresflexalpharesource.NewConnectionInfoValueMust(
postgresflexalpharesource.ConnectionInfoValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"write": postgresflexalpharesource.NewWriteValueMust(
// careful - we can not use NewWriteValueMust here
"write": basetypes.NewObjectValueMust(
postgresflexalpharesource.WriteValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"host": types.StringPointerValue(resp.ConnectionInfo.Write.Host),
"port": types.Int64PointerValue(resp.ConnectionInfo.Write.Port),
"host": types.StringValue(resp.ConnectionInfo.Write.Host),
// note: IDE does not show that port is actually an int64 in the Schema
"port": types.Int64Value(int64(resp.ConnectionInfo.Write.Port)),
},
),
},
@ -62,7 +62,7 @@ func mapGetInstanceResponseToModel(
m.InstanceId.ValueString(),
)
}
m.InstanceId = types.StringPointerValue(resp.Id)
m.InstanceId = types.StringValue(resp.Id)
m.IsDeletable = types.BoolValue(resp.GetIsDeletable())
@ -75,12 +75,12 @@ func mapGetInstanceResponseToModel(
netInstAdd := types.StringValue("")
if instAdd, ok := resp.Network.GetInstanceAddressOk(); ok {
netInstAdd = types.StringValue(instAdd)
netInstAdd = types.StringValue(*instAdd)
}
netRtrAdd := types.StringValue("")
if rtrAdd, ok := resp.Network.GetRouterAddressOk(); ok {
netRtrAdd = types.StringValue(rtrAdd)
netRtrAdd = types.StringValue(*rtrAdd)
}
net, diags := postgresflexalpharesource.NewNetworkValue(
@ -98,7 +98,7 @@ func mapGetInstanceResponseToModel(
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Name = types.StringValue(resp.GetName())
@ -108,7 +108,7 @@ func mapGetInstanceResponseToModel(
postgresflexalpharesource.StorageValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"performance_class": types.StringValue(resp.Storage.GetPerformanceClass()),
"size": types.Int64Value(resp.Storage.GetSize()),
"size": types.Int64Value(int64(resp.Storage.GetSize())),
},
)
if diags.HasError() {
@ -131,7 +131,7 @@ func mapGetDataInstanceResponseToModel(
m.FlavorId = types.StringValue(resp.GetFlavorId())
m.Id = utils.BuildInternalTerraformId(m.ProjectId.ValueString(), m.Region.ValueString(), m.InstanceId.ValueString())
m.InstanceId = types.StringPointerValue(resp.Id)
m.InstanceId = types.StringValue(resp.Id)
m.IsDeletable = types.BoolValue(resp.GetIsDeletable())
m.Name = types.StringValue(resp.GetName())
@ -141,13 +141,13 @@ func mapGetDataInstanceResponseToModel(
}
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Status = types.StringValue(string(resp.GetStatus()))
storage, diags := postgresflexalphadatasource.NewStorageValue(
postgresflexalphadatasource.StorageValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"performance_class": types.StringValue(resp.Storage.GetPerformanceClass()),
"size": types.Int64Value(resp.Storage.GetSize()),
"size": types.Int64Value(int64(resp.Storage.GetSize())),
},
)
if diags.HasError() {
@ -159,9 +159,7 @@ func mapGetDataInstanceResponseToModel(
}
func handleConnectionInfo(ctx context.Context, m *dataSourceModel, resp *postgresflex.GetInstanceResponse) {
isConnectionInfoIncomplete := resp.ConnectionInfo == nil || resp.ConnectionInfo.Write == nil ||
resp.ConnectionInfo.Write.Host == nil || *resp.ConnectionInfo.Write.Host == "" ||
resp.ConnectionInfo.Write.Port == nil || *resp.ConnectionInfo.Write.Port == 0
isConnectionInfoIncomplete := resp.ConnectionInfo.Write.Host == "" || resp.ConnectionInfo.Write.Port == 0
if isConnectionInfoIncomplete {
m.ConnectionInfo = postgresflexalphadatasource.NewConnectionInfoValueNull()
@ -169,11 +167,11 @@ func handleConnectionInfo(ctx context.Context, m *dataSourceModel, resp *postgre
m.ConnectionInfo = postgresflexalphadatasource.NewConnectionInfoValueMust(
postgresflexalphadatasource.ConnectionInfoValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"write": postgresflexalphadatasource.NewWriteValueMust(
"write": types.ObjectValueMust(
postgresflexalphadatasource.WriteValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"host": types.StringPointerValue(resp.ConnectionInfo.Write.Host),
"port": types.Int64PointerValue(resp.ConnectionInfo.Write.Port),
"host": types.StringValue(resp.ConnectionInfo.Write.Host),
"port": types.Int64Value(int64(resp.ConnectionInfo.Write.Port)),
},
),
},
@ -182,26 +180,26 @@ func handleConnectionInfo(ctx context.Context, m *dataSourceModel, resp *postgre
}
func handleNetwork(ctx context.Context, m *dataSourceModel, resp *postgresflex.GetInstanceResponse) error {
netAcl, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
netACL, diags := types.ListValueFrom(ctx, types.StringType, resp.Network.GetAcl())
if diags.HasError() {
return fmt.Errorf("failed converting network acl from response")
}
instAddr := ""
if iA, ok := resp.Network.GetInstanceAddressOk(); ok {
instAddr = iA
instAddr = *iA
}
rtrAddr := ""
if rA, ok := resp.Network.GetRouterAddressOk(); ok {
rtrAddr = rA
rtrAddr = *rA
}
net, diags := postgresflexalphadatasource.NewNetworkValue(
postgresflexalphadatasource.NetworkValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"access_scope": types.StringValue(string(resp.Network.GetAccessScope())),
"acl": netAcl,
"acl": netACL,
"instance_address": types.StringValue(instAddr),
"router_address": types.StringValue(rtrAddr),
},
@ -216,22 +214,22 @@ func handleNetwork(ctx context.Context, m *dataSourceModel, resp *postgresflex.G
func handleEncryption(m *dataSourceModel, resp *postgresflex.GetInstanceResponse) {
keyId := ""
if keyIdVal, ok := resp.Encryption.GetKekKeyIdOk(); ok {
keyId = keyIdVal
keyId = *keyIdVal
}
keyRingId := ""
if keyRingIdVal, ok := resp.Encryption.GetKekKeyRingIdOk(); ok {
keyRingId = keyRingIdVal
keyRingId = *keyRingIdVal
}
keyVersion := ""
if keyVersionVal, ok := resp.Encryption.GetKekKeyVersionOk(); ok {
keyVersion = keyVersionVal
keyVersion = *keyVersionVal
}
svcAcc := ""
if svcAccVal, ok := resp.Encryption.GetServiceAccountOk(); ok {
svcAcc = svcAccVal
svcAcc = *svcAccVal
}
m.Encryption = postgresflexalphadatasource.EncryptionValue{

View file

@ -1,746 +1,191 @@
package postgresflexalpha
import (
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"context"
"testing"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/hashicorp/terraform-plugin-framework/types"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflexalpharesource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
utils2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
//nolint:unused // TODO: remove when used
type testFlavor struct {
Cpu int64
Description string
Id string
MaxGB int64
Memory int64
MinGB int64
NodeType string
StorageClasses []testFlavorStorageClass
}
//nolint:unused // TODO: remove when used
type testFlavorStorageClass struct {
Class string
MaxIoPerSec int64
MaxThroughInMb int64
}
//nolint:unused // TODO: remove when used
var responseList = []testFlavor{
{
Cpu: 1,
Description: "flavor 1.1",
Id: "flv1.1",
MaxGB: 500,
Memory: 1,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.2",
Id: "flv1.2",
MaxGB: 500,
Memory: 2,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.3",
Id: "flv1.3",
MaxGB: 500,
Memory: 3,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.4",
Id: "flv1.4",
MaxGB: 500,
Memory: 4,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.5",
Id: "flv1.5",
MaxGB: 500,
Memory: 5,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.6",
Id: "flv1.6",
MaxGB: 500,
Memory: 6,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.7",
Id: "flv1.7",
MaxGB: 500,
Memory: 7,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.8",
Id: "flv1.8",
MaxGB: 500,
Memory: 8,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.9",
Id: "flv1.9",
MaxGB: 500,
Memory: 9,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
/* ......................................................... */
{
Cpu: 2,
Description: "flavor 2.1",
Id: "flv2.1",
MaxGB: 500,
Memory: 1,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.2",
Id: "flv2.2",
MaxGB: 500,
Memory: 2,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.3",
Id: "flv2.3",
MaxGB: 500,
Memory: 3,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.4",
Id: "flv2.4",
MaxGB: 500,
Memory: 4,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.5",
Id: "flv2.5",
MaxGB: 500,
Memory: 5,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.6",
Id: "flv2.6",
MaxGB: 500,
Memory: 6,
MinGB: 5,
NodeType: "single",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
/* ......................................................... */
{
Cpu: 1,
Description: "flavor 1.1 replica",
Id: "flv1.1r",
MaxGB: 500,
Memory: 1,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.2 replica",
Id: "flv1.2r",
MaxGB: 500,
Memory: 2,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.3 replica",
Id: "flv1.3r",
MaxGB: 500,
Memory: 3,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.4 replica",
Id: "flv1.4r",
MaxGB: 500,
Memory: 4,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.5 replica",
Id: "flv1.5r",
MaxGB: 500,
Memory: 5,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 1,
Description: "flavor 1.6 replica",
Id: "flv1.6r",
MaxGB: 500,
Memory: 6,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
/* ......................................................... */
{
Cpu: 2,
Description: "flavor 2.1 replica",
Id: "flv2.1r",
MaxGB: 500,
Memory: 1,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.2 replica",
Id: "flv2.2r",
MaxGB: 500,
Memory: 2,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.3 replica",
Id: "flv2.3r",
MaxGB: 500,
Memory: 3,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.4 replica",
Id: "flv2.4r",
MaxGB: 500,
Memory: 4,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.5 replica",
Id: "flv2.5r",
MaxGB: 500,
Memory: 5,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
{
Cpu: 2,
Description: "flavor 2.6 replica",
Id: "flv2.6r",
MaxGB: 500,
Memory: 6,
MinGB: 5,
NodeType: "Replica",
StorageClasses: []testFlavorStorageClass{
{Class: "sc1", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc2", MaxIoPerSec: 0, MaxThroughInMb: 0},
{Class: "sc3", MaxIoPerSec: 0, MaxThroughInMb: 0},
},
},
/* ......................................................... */
}
//nolint:unused // TODO: remove when used
func testFlavorListToResponseFlavorList(f []testFlavor) []postgresflex.ListFlavors {
result := make([]postgresflex.ListFlavors, len(f))
for i, flavor := range f {
result[i] = testFlavorToResponseFlavor(flavor)
func Test_handleConnectionInfo(t *testing.T) {
type args struct {
ctx context.Context
m *dataSourceModel
hostName string
port int32
}
return result
}
//nolint:unused // TODO: remove when used
func testFlavorToResponseFlavor(f testFlavor) postgresflex.ListFlavors {
var scList []postgresflex.FlavorStorageClassesStorageClass
for _, fl := range f.StorageClasses {
scList = append(
scList, postgresflex.FlavorStorageClassesStorageClass{
Class: utils.Ptr(fl.Class),
MaxIoPerSec: utils.Ptr(fl.MaxIoPerSec),
MaxThroughInMb: utils.Ptr(fl.MaxThroughInMb),
tests := []struct {
name string
args args
}{
{
name: "empty connection info",
args: args{
ctx: context.TODO(),
m: &dataSourceModel{},
hostName: "",
port: 0,
},
)
},
{
name: "empty connection info host",
args: args{
ctx: context.TODO(),
m: &dataSourceModel{},
hostName: "",
port: 1234,
},
},
{
name: "empty connection info port",
args: args{
ctx: context.TODO(),
m: &dataSourceModel{},
hostName: "hostname",
port: 0,
},
},
{
name: "valid connection info",
args: args{
ctx: context.TODO(),
m: &dataSourceModel{},
hostName: "host",
port: 1000,
},
},
}
return postgresflex.ListFlavors{
Cpu: utils.Ptr(f.Cpu),
Description: utils.Ptr(f.Description),
Id: utils.Ptr(f.Id),
MaxGB: utils.Ptr(f.MaxGB),
Memory: utils.Ptr(f.Memory),
MinGB: utils.Ptr(f.MinGB),
NodeType: utils.Ptr(f.NodeType),
StorageClasses: &scList,
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resp := &postgresflex.GetInstanceResponse{
ConnectionInfo: postgresflex.InstanceConnectionInfo{
Write: postgresflex.InstanceConnectionInfoWrite{
Host: tt.args.hostName,
Port: int32(tt.args.port),
},
},
}
handleConnectionInfo(tt.args.ctx, tt.args.m, resp)
if tt.args.hostName == "" || tt.args.port == 0 {
if !tt.args.m.ConnectionInfo.IsNull() {
t.Errorf("expected connection info to be null")
}
}
if tt.args.hostName != "" && tt.args.port != 0 {
res := tt.args.m.ConnectionInfo.Write.Attributes()
gotHost := ""
if r, ok := res["host"]; ok {
gotHost = utils2.RemoveQuotes(r.String())
}
if gotHost != tt.args.hostName {
t.Errorf("host value incorrect: want: %s - got: %s", tt.args.hostName, gotHost)
}
gotPort, ok := res["port"]
if !ok {
t.Errorf("could not find a value for port in connection_info.write")
}
if !gotPort.Equal(types.Int64Value(int64(tt.args.port))) {
t.Errorf("port value incorrect: want: %d - got: %s", tt.args.port, gotPort.String())
}
}
})
}
}
// func Test_getAllFlavors(t *testing.T) {
// type args struct {
// projectId string
// region string
// }
// tests := []struct {
// name string
// args args
// firstItem int
// lastItem int
// want []postgresflex.ListFlavors
// wantErr bool
// }{
// {
// name: "find exactly one flavor",
// args: args{
// projectId: "project",
// region: "region",
// },
// firstItem: 0,
// lastItem: 0,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[0]),
// },
// wantErr: false,
// },
// {
// name: "get exactly 1 page flavors",
// args: args{
// projectId: "project",
// region: "region",
// },
// firstItem: 0,
// lastItem: 9,
// want: testFlavorListToResponseFlavorList(responseList[0:10]),
// wantErr: false,
// },
// {
// name: "get exactly 20 flavors",
// args: args{
// projectId: "project",
// region: "region",
// },
// firstItem: 0,
// lastItem: 20,
// // 0 indexed therefore we want :21
// want: testFlavorListToResponseFlavorList(responseList[0:21]),
// wantErr: false,
// },
// {
// name: "get all flavors",
// args: args{
// projectId: "project",
// region: "region",
// },
// firstItem: 0,
// lastItem: len(responseList),
// want: testFlavorListToResponseFlavorList(responseList),
// wantErr: false,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// first := tt.firstItem
// if first > len(responseList)-1 {
// first = len(responseList) - 1
// }
// last := tt.lastItem
// if last > len(responseList)-1 {
// last = len(responseList) - 1
// }
// mockClient := postgresFlexClientMocked{
// returnError: tt.wantErr,
// firstItem: first,
// lastItem: last,
// }
// got, err := getAllFlavors(context.TODO(), mockClient, tt.args.projectId, tt.args.region)
// if (err != nil) != tt.wantErr {
// t.Errorf("getAllFlavors() error = %v, wantErr %v", err, tt.wantErr)
// return
// }
//
// if diff := cmp.Diff(tt.want, got); diff != "" {
// t.Errorf("mismatch (-want +got):\n%s", diff)
// }
//
// if !reflect.DeepEqual(got, tt.want) {
// t.Errorf("getAllFlavors() got = %v, want %v", got, tt.want)
// }
// })
// }
//}
func Test_handleEncryption(t *testing.T) {
t.Skipf("please implement")
type args struct {
m *dataSourceModel
resp *postgresflex.GetInstanceResponse
}
tests := []struct {
name string
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
handleEncryption(tt.args.m, tt.args.resp)
t.Logf("need to implement more")
})
}
}
// func Test_loadFlavorId(t *testing.T) {
// type args struct {
// ctx context.Context
// model *Model
// storage *storageModel
// }
// tests := []struct {
// name string
// args args
// firstItem int
// lastItem int
// want []postgresflex.ListFlavors
// wantErr bool
// }{
// {
// name: "find a single flavor",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: 3,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[0]),
// },
// wantErr: false,
// },
// {
// name: "find a single flavor by replicas option",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// Replicas: basetypes.NewInt64Value(1),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: 3,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[0]),
// },
// wantErr: false,
// },
// {
// name: "fail finding find a single flavor by replicas option",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// Replicas: basetypes.NewInt64Value(1),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 13,
// lastItem: 23,
// want: []postgresflex.ListFlavors{},
// wantErr: true,
// },
// {
// name: "find a replicas flavor lower case",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: len(responseList) - 1,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[16]),
// },
// wantErr: false,
// },
// {
// name: "find a replicas flavor CamelCase",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: len(responseList) - 1,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[16]),
// },
// wantErr: false,
// },
// {
// name: "find a replicas flavor by replicas option",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// Replicas: basetypes.NewInt64Value(3),
// },
// flavor: &flavorModel{
// CPU: basetypes.NewInt64Value(1),
// RAM: basetypes.NewInt64Value(1),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: len(responseList) - 1,
// want: []postgresflex.ListFlavors{
// testFlavorToResponseFlavor(responseList[16]),
// },
// wantErr: false,
// },
// {
// name: "fail finding a replica flavor",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// Replicas: basetypes.NewInt64Value(3),
// },
// flavor: &flavorModel{
// CPU: basetypes.NewInt64Value(1),
// RAM: basetypes.NewInt64Value(1),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: 10,
// want: []postgresflex.ListFlavors{},
// wantErr: true,
// },
// {
// name: "no flavor found error",
// args: args{
// ctx: context.Background(),
// model: &Model{
// ProjectId: basetypes.NewStringValue("project"),
// Region: basetypes.NewStringValue("region"),
// },
// flavor: &flavorModel{
// CPU: basetypes.NewInt64Value(10),
// RAM: basetypes.NewInt64Value(1000),
// NodeType: basetypes.NewStringValue("Single"),
// },
// storage: &storageModel{
// Class: basetypes.NewStringValue("sc1"),
// Size: basetypes.NewInt64Value(100),
// },
// },
// firstItem: 0,
// lastItem: 3,
// want: []postgresflex.ListFlavors{},
// wantErr: true,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// first := tt.firstItem
// if first > len(responseList)-1 {
// first = len(responseList) - 1
// }
// last := tt.lastItem
// if last > len(responseList)-1 {
// last = len(responseList) - 1
// }
// mockClient := postgresFlexClientMocked{
// returnError: tt.wantErr,
// firstItem: first,
// lastItem: last,
// }
// if err := loadFlavorId(tt.args.ctx, mockClient, tt.args.model, tt.args.flavor, tt.args.storage); (err != nil) != tt.wantErr {
// t.Errorf("loadFlavorId() error = %v, wantErr %v", err, tt.wantErr)
// }
// })
// }
//}
func Test_handleNetwork(t *testing.T) {
t.Skipf("please implement")
type args struct {
ctx context.Context
m *dataSourceModel
resp *postgresflex.GetInstanceResponse
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := handleNetwork(tt.args.ctx, tt.args.m, tt.args.resp); (err != nil) != tt.wantErr {
t.Errorf("handleNetwork() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func Test_mapGetDataInstanceResponseToModel(t *testing.T) {
t.Skipf("please implement")
type args struct {
ctx context.Context
m *dataSourceModel
resp *postgresflex.GetInstanceResponse
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := mapGetDataInstanceResponseToModel(tt.args.ctx, tt.args.m, tt.args.resp); (err != nil) != tt.wantErr {
t.Errorf("mapGetDataInstanceResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func Test_mapGetInstanceResponseToModel(t *testing.T) {
t.Skipf("please implement")
type args struct {
ctx context.Context
m *postgresflexalpharesource.InstanceModel
resp *postgresflex.GetInstanceResponse
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := mapGetInstanceResponseToModel(tt.args.ctx, tt.args.m, tt.args.resp); (err != nil) != tt.wantErr {
t.Errorf("mapGetInstanceResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

View file

@ -14,8 +14,9 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
coreUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
@ -50,7 +51,7 @@ type InstanceResourceIdentityModel struct {
// instanceResource is the resource implementation.
type instanceResource struct {
client *postgresflex.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -195,9 +196,9 @@ func (r *instanceResource) Create(
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
projectID := model.ProjectId.ValueString()
region := model.Region.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "project_id", projectID)
ctx = tflog.SetField(ctx, "region", region)
var netAcl []string
@ -207,17 +208,13 @@ func (r *instanceResource) Create(
return
}
if model.Replicas.ValueInt64() > math.MaxInt32 {
resp.Diagnostics.AddError("invalid int32 value", "provided int64 value does not fit into int32")
return
}
replVal := int32(model.Replicas.ValueInt64()) // nolint:gosec // check is performed above
replVal := model.Replicas.ValueInt64() // nolint:gosec // check is performed above
payload := modelToCreateInstancePayload(netAcl, model, replVal)
// Create new instance
createResp, err := r.client.CreateInstanceRequest(
createResp, err := r.client.DefaultAPI.CreateInstanceRequest(
ctx,
projectId,
projectID,
region,
).CreateInstanceRequestPayload(payload).Execute()
if err != nil {
@ -226,7 +223,7 @@ func (r *instanceResource) Create(
}
ctx = core.LogResponse(ctx)
instanceId, ok := createResp.GetIdOk()
instanceID, ok := createResp.GetIdOk()
if !ok {
core.LogAndAddError(ctx, &resp.Diagnostics, "error creating instance", "could not find instance id in response")
return
@ -234,16 +231,16 @@ func (r *instanceResource) Create(
// Set data returned by API in identity
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
ProjectID: types.StringValue(projectID),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
InstanceID: types.StringPointerValue(instanceID),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
return
}
waitResp, err := wait.CreateInstanceWaitHandler(ctx, r.client, projectId, region, instanceId).
waitResp, err := wait.CreateInstanceWaitHandler(ctx, r.client.DefaultAPI, projectID, region, *instanceID).
WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(
@ -276,37 +273,35 @@ func (r *instanceResource) Create(
}
func modelToCreateInstancePayload(
netAcl []string,
netACL []string,
model postgresflexalpha.InstanceModel,
replVal int32,
) postgresflex.CreateInstanceRequestPayload {
var enc *postgresflex.InstanceEncryption
replVal int64,
) v3alpha1api.CreateInstanceRequestPayload {
var enc *v3alpha1api.InstanceEncryption
if !model.Encryption.IsNull() && !model.Encryption.IsUnknown() {
enc = &postgresflex.InstanceEncryption{
KekKeyId: model.Encryption.KekKeyId.ValueStringPointer(),
KekKeyRingId: model.Encryption.KekKeyRingId.ValueStringPointer(),
KekKeyVersion: model.Encryption.KekKeyVersion.ValueStringPointer(),
ServiceAccount: model.Encryption.ServiceAccount.ValueStringPointer(),
enc = &v3alpha1api.InstanceEncryption{
KekKeyId: model.Encryption.KekKeyId.ValueString(),
KekKeyRingId: model.Encryption.KekKeyRingId.ValueString(),
KekKeyVersion: model.Encryption.KekKeyVersion.ValueString(),
ServiceAccount: model.Encryption.ServiceAccount.ValueString(),
}
}
payload := postgresflex.CreateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueStringPointer(),
payload := v3alpha1api.CreateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueString(),
Encryption: enc,
FlavorId: model.FlavorId.ValueStringPointer(),
Name: model.Name.ValueStringPointer(),
Network: &postgresflex.InstanceNetworkCreate{
AccessScope: postgresflex.InstanceNetworkGetAccessScopeAttributeType(
model.Network.AccessScope.ValueStringPointer(),
),
Acl: &netAcl,
FlavorId: model.FlavorId.ValueString(),
Name: model.Name.ValueString(),
Network: v3alpha1api.InstanceNetworkCreate{
AccessScope: (*v3alpha1api.InstanceNetworkAccessScope)(model.Network.AccessScope.ValueStringPointer()),
Acl: netACL,
},
Replicas: postgresflex.CreateInstanceRequestPayloadGetReplicasAttributeType(&replVal),
RetentionDays: model.RetentionDays.ValueInt64Pointer(),
Storage: &postgresflex.StorageCreate{
PerformanceClass: model.Storage.PerformanceClass.ValueStringPointer(),
Size: model.Storage.Size.ValueInt64Pointer(),
Replicas: v3alpha1api.Replicas(replVal), //nolint:gosec // TODO
RetentionDays: int32(model.RetentionDays.ValueInt64()), //nolint:gosec // TODO
Storage: v3alpha1api.StorageCreate{
PerformanceClass: model.Storage.PerformanceClass.ValueString(),
Size: int32(model.Storage.Size.ValueInt64()), //nolint:gosec // TODO
},
Version: model.Version.ValueStringPointer(),
Version: model.Version.ValueString(),
}
return payload
}
@ -347,7 +342,7 @@ func (r *instanceResource) Read(
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "region", region)
instanceResp, err := r.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := r.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if ok && oapiErr.StatusCode == http.StatusNotFound {
@ -366,7 +361,7 @@ func (r *instanceResource) Read(
return
}
if !model.InstanceId.IsUnknown() && !model.InstanceId.IsNull() {
if respInstanceID != instanceId {
if *respInstanceID != instanceId {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -431,47 +426,56 @@ func (r *instanceResource) Update(
return
}
projectId := identityData.ProjectID.ValueString()
instanceId := identityData.InstanceID.ValueString()
projectID := identityData.ProjectID.ValueString()
instanceID := identityData.InstanceID.ValueString()
region := model.Region.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "project_id", projectID)
ctx = tflog.SetField(ctx, "instance_id", instanceID)
ctx = tflog.SetField(ctx, "region", region)
var netAcl []string
diag := model.Network.Acl.ElementsAs(ctx, &netAcl, false)
var netACL []string
diag := model.Network.Acl.ElementsAs(ctx, &netACL, false)
resp.Diagnostics.Append(diags...)
if diag.HasError() {
return
}
if model.Replicas.ValueInt64() > math.MaxInt32 {
resp.Diagnostics.AddError("invalid int32 value", "provided int64 value does not fit into int32")
core.LogAndAddError(ctx, &resp.Diagnostics, "UPDATE", "replicas value too large for int32")
return
}
replInt32 := int32(model.Replicas.ValueInt64()) // nolint:gosec // check is performed above
payload := postgresflex.UpdateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueStringPointer(),
FlavorId: model.FlavorId.ValueStringPointer(),
Name: model.Name.ValueStringPointer(),
Network: &postgresflex.InstanceNetworkUpdate{
Acl: &netAcl,
if model.RetentionDays.ValueInt64() > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "UPDATE", "retention_days value too large for int32")
return
}
if model.Storage.Size.ValueInt64() > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "UPDATE", "storage.size value too large for int32")
return
}
payload := v3alpha1api.UpdateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueString(),
FlavorId: model.FlavorId.ValueString(),
Name: model.Name.ValueString(),
Network: v3alpha1api.InstanceNetworkUpdate{
Acl: netACL,
},
Replicas: postgresflex.UpdateInstanceRequestPayloadGetReplicasAttributeType(&replInt32),
RetentionDays: model.RetentionDays.ValueInt64Pointer(),
Storage: &postgresflex.StorageUpdate{
Size: model.Storage.Size.ValueInt64Pointer(),
Replicas: v3alpha1api.Replicas(model.Replicas.ValueInt64()), //nolint:gosec // checked above
RetentionDays: int32(model.RetentionDays.ValueInt64()), //nolint:gosec // checked above
Storage: v3alpha1api.StorageUpdate{
Size: coreUtils.Ptr(int32(model.Storage.Size.ValueInt64())), //nolint:gosec // checked above
},
Version: model.Version.ValueStringPointer(),
Version: model.Version.ValueString(),
}
// Update existing instance
err := r.client.UpdateInstanceRequest(
err := r.client.DefaultAPI.UpdateInstanceRequest(
ctx,
projectId,
projectID,
region,
instanceId,
instanceID,
).UpdateInstanceRequestPayload(payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", err.Error())
@ -482,10 +486,10 @@ func (r *instanceResource) Update(
waitResp, err := wait.PartialUpdateInstanceWaitHandler(
ctx,
r.client,
projectId,
r.client.DefaultAPI,
projectID,
region,
instanceId,
instanceID,
).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(
@ -540,7 +544,7 @@ func (r *instanceResource) Delete(
ctx = tflog.SetField(ctx, "region", region)
// Delete existing instance
err := r.client.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
err := r.client.DefaultAPI.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting instance", fmt.Sprintf("Calling API: %v", err))
return
@ -548,7 +552,7 @@ func (r *instanceResource) Delete(
ctx = core.LogResponse(ctx)
_, err = r.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
_, err = r.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if ok && oapiErr.StatusCode != http.StatusNotFound {

View file

@ -30,8 +30,8 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
},
"backup_schedule": schema.StringAttribute{
Required: true,
Description: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
Description: "The schedule for when the database backup will be created. Currently, ONLY daily schedules are supported (every 24 hours). The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for when the database backup will be created. Currently, ONLY daily schedules are supported (every 24 hours). The schedule is written as a cron schedule.",
},
"connection_info": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{

View file

@ -5,17 +5,23 @@ import (
_ "embed"
"fmt"
"log"
"math"
"os"
"strconv"
"strings"
"testing"
"time"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflexalpha2 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils"
// The fwresource import alias is so there is no collision
@ -26,61 +32,15 @@ import (
const pfx = "stackitprivatepreview_postgresflexalpha"
var testInstances []string
func init() {
sweeperName := fmt.Sprintf("%s_%s", pfx, "sweeper")
resource.AddTestSweepers(
sweeperName, &resource.Sweeper{
Name: sweeperName,
F: func(_ string) error { // region is passed by the testing framework
ctx := context.Background()
apiClientConfigOptions := []config.ConfigurationOption{}
apiClient, err := postgresflexalpha2.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instances, err := apiClient.ListInstancesRequest(ctx, testutils.ProjectId, testutils.Region).
Size(100).
Execute()
if err != nil {
log.Fatalln(err)
}
for _, inst := range instances.GetInstances() {
if strings.HasPrefix(inst.GetName(), "tf-acc-") {
for _, item := range testInstances {
if inst.GetName() == item {
delErr := apiClient.DeleteInstanceRequestExecute(
ctx,
testutils.ProjectId,
testutils.Region,
inst.GetId(),
)
if delErr != nil {
// TODO: maybe just warn?
log.Fatalln(delErr)
}
}
}
}
}
return nil
},
},
)
}
func TestInstanceResourceSchema(t *testing.T) {
t.Parallel()
// t.Parallel()
ctx := context.Background()
schemaRequest := fwresource.SchemaRequest{}
schemaResponse := &fwresource.SchemaResponse{}
// Instantiate the resource.Resource and call its Schema method
postgresflexalpha.NewInstanceResource().Schema(ctx, schemaRequest, schemaResponse)
postgresflexalphaInstance.NewInstanceResource().Schema(ctx, schemaRequest, schemaResponse)
if schemaResponse.Diagnostics.HasError() {
t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
@ -94,14 +54,6 @@ func TestInstanceResourceSchema(t *testing.T) {
}
}
var (
//go:embed testdata/resource-no-enc.tf
resourceConfigNoEnc string //nolint:unused // needs implementation
//go:embed testdata/resource-enc.tf
resourceConfigEnc string //nolint:unused // needs implementation
)
func TestMain(m *testing.M) {
testutils.Setup()
code := m.Run()
@ -115,44 +67,23 @@ func testAccPreCheck(t *testing.T) {
}
}
// func TestAccResourceExample_parallel(t *testing.T) {
// t.Parallel()
//
// exData := resData{
// Region: "eu01",
// ServiceAccountFilePath: sa_file,
// ProjectID: project_id,
// Name: acctest.RandomWithPrefix("tf-acc"),
// }
//
// resource.Test(t, resource.TestCase{
// ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
// Steps: []resource.TestStep{
// {
// Config: testAccResourceEncryptionExampleConfig(exData),
// Check: resource.TestCheckResourceAttrSet("example_resource.test", "id"),
// },
// },
// })
//}
type resData struct {
ServiceAccountFilePath string
ProjectId string
ProjectID string
Region string
Name string
TfName string
FlavorId string
FlavorID string
BackupSchedule string
UseEncryption bool
KekKeyId string
KekKeyRingId string
KekKeyID string
KekKeyRingID string
KekKeyVersion uint8
KekServiceAccount string
PerformanceClass string
Replicas uint32
Size uint32
AclString string
ACLString string
AccessScope string
RetentionDays uint32
Version string
@ -162,13 +93,13 @@ type resData struct {
type User struct {
Name string
ProjectId string
ProjectID string
Roles []string
}
type Database struct {
Name string
ProjectId string
ProjectID string
Owner string
}
@ -177,17 +108,17 @@ func getExample() resData {
return resData{
Region: os.Getenv("TF_ACC_REGION"),
ServiceAccountFilePath: os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Name: name,
TfName: name,
FlavorId: "2.4",
FlavorID: "2.4",
BackupSchedule: "0 0 * * *",
UseEncryption: false,
RetentionDays: 33,
Replicas: 1,
PerformanceClass: "premium-perf2-stackit",
Size: 10,
AclString: "0.0.0.0/0",
ACLString: "0.0.0.0/0",
AccessScope: "PUBLIC",
Version: "17",
}
@ -202,28 +133,103 @@ func TestAccInstance(t *testing.T) {
updSizeData := exData
updSizeData.Size = 25
updBackupSched := updSizeData
// api should complain about more than one daily backup
updBackupSched.BackupSchedule = "30 3 * * *"
/*
{
"backupSchedule": "6 6 * * *",
"flavorId": "1.2",
"name": "postgres-instance",
"network": {
"acl": [
"198.51.100.0/24"
]
},
"replicas": 1,
"retentionDays": 35,
"storage": {
"size": 10
},
"version": "string"
}
*/
testItemID := testutils.ResStr(pfx, "instance", exData.TfName)
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", exData.TfName)
testInstances = append(testInstances, exData.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
//PreConfig: func() {
// //
// },
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
exData,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"name",
exData.Name,
),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", exData.TfName), "id"),
// check params acl count
resource.TestCheckResourceAttr(testItemID, "acl.#", "1"),
// check params are set
resource.TestCheckResourceAttrSet(testItemID, "backup_schedule"),
//// connection_info should contain 1 sub entry
// resource.TestCheckResourceAttr(testItemID, "connection_info.%", "1"),
//
//// connection_info.write should contain 2 sub entries
// resource.TestCheckResourceAttr(testItemID, "connection_info.write", "2"),
//
// resource.TestCheckResourceAttrSet(testItemID, "connection_info.write.host"),
// resource.TestCheckResourceAttrSet(testItemID, "connection_info.write.port"),
resource.TestCheckResourceAttrSet(testItemID, "flavor_id"),
resource.TestCheckResourceAttrSet(testItemID, "id"),
resource.TestCheckResourceAttrSet(testItemID, "instance_id"),
resource.TestCheckResourceAttrSet(testItemID, "is_deletable"),
resource.TestCheckResourceAttrSet(testItemID, "name"),
// network should contain 4 sub entries
resource.TestCheckResourceAttr(testItemID, "network.%", "4"),
resource.TestCheckResourceAttrSet(testItemID, "network.access_scope"),
// on unencrypted instances we expect this to be empty
resource.TestCheckResourceAttr(testItemID, "network.instance_address", ""),
resource.TestCheckResourceAttr(testItemID, "network.router_address", ""),
// only one acl entry should be set
resource.TestCheckResourceAttr(testItemID, "network.acl.#", "1"),
resource.TestCheckResourceAttrSet(testItemID, "replicas"),
resource.TestCheckResourceAttrSet(testItemID, "retention_days"),
resource.TestCheckResourceAttrSet(testItemID, "status"),
// storage should contain 2 sub entries
resource.TestCheckResourceAttr(testItemID, "storage.%", "2"),
resource.TestCheckResourceAttrSet(testItemID, "storage.performance_class"),
resource.TestCheckResourceAttrSet(testItemID, "storage.size"),
resource.TestCheckResourceAttrSet(testItemID, "version"),
// check absent attr
resource.TestCheckNoResourceAttr(testItemID, "encryption"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_id"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_ring_id"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_version"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.service_account"),
// check param values
resource.TestCheckResourceAttr(testItemID, "name", exData.Name),
),
},
// Update name and verify
@ -254,6 +260,20 @@ func TestAccInstance(t *testing.T) {
),
),
},
// Update backup schedule
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updBackupSched,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"backup_schedule",
updBackupSched.BackupSchedule,
),
),
},
//// Import test
//{
// ResourceName: "example_resource.test",
@ -272,7 +292,7 @@ func TestAccInstanceWithUsers(t *testing.T) {
data.Users = []User{
{
Name: userName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
@ -282,8 +302,8 @@ func TestAccInstanceWithUsers(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
@ -316,7 +336,7 @@ func TestAccInstanceWithDatabases(t *testing.T) {
data.Users = []User{
{
Name: userName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
@ -324,7 +344,7 @@ func TestAccInstanceWithDatabases(t *testing.T) {
data.Databases = []Database{
{
Name: dbName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
@ -334,8 +354,95 @@ func TestAccInstanceWithDatabases(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", data.TfName),
"name",
data.Name,
),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", data.TfName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "name", dbName),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "owner", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "database", dbName), "id"),
),
},
},
},
)
}
func TestAccEncryptedInstanceWithDatabases(t *testing.T) {
encKekKeyID, ok := os.LookupEnv("TF_ACC_KEK_KEY_ID")
if !ok || encKekKeyID == "" {
t.Skip("env var TF_ACC_KEK_KEY_ID needed for encryption test")
}
encKekKeyRingID, ok := os.LookupEnv("TF_ACC_KEK_KEY_RING_ID")
if !ok || encKekKeyRingID == "" {
t.Skip("env var TF_ACC_KEK_KEY_RING_ID needed for encryption test")
}
encKekKeyVersion, ok := os.LookupEnv("TF_ACC_KEK_KEY_VERSION")
if !ok || encKekKeyVersion == "" {
t.Skip("env var TF_ACC_KEK_KEY_VERSION needed for encryption test")
}
encSvcAcc, ok := os.LookupEnv("TF_ACC_KEK_SERVICE_ACCOUNT")
if !ok || encSvcAcc == "" {
t.Skip("env var TF_ACC_KEK_SERVICE_ACCOUNT needed for encryption test")
}
data := getExample()
data.UseEncryption = true
data.KekKeyID = encKekKeyID
data.KekKeyRingID = encKekKeyRingID
data.KekServiceAccount = encSvcAcc
encKekKeyVersionInt, err := strconv.Atoi(encKekKeyVersion)
if err != nil {
t.Errorf("error converting string to int")
}
if encKekKeyVersionInt > math.MaxUint8 {
t.Errorf("value too large to convert to uint8")
}
data.KekKeyVersion = uint8(encKekKeyVersionInt) //nolint:gosec // handled above
dbName := "testdb"
userName := "testUser"
data.Users = []User{
{
Name: userName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
data.Databases = []Database{
{
Name: dbName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
@ -402,19 +509,6 @@ func TestAccInstanceWithDatabases(t *testing.T) {
// // Run unit tests against mock
//}
// type postgresFlexClientMocked struct {
// returnError bool
// getFlavorsResp *postgresflex.GetFlavorsResponse
// }
//
// func (c *postgresFlexClientMocked) ListFlavorsExecute(_ context.Context, _, _ string) (*postgresflex.GetFlavorsResponse, error) {
// if c.returnError {
// return nil, fmt.Errorf("get flavors failed")
// }
//
// return c.getFlavorsResp, nil
// }
// func TestNewInstanceResource(t *testing.T) {
// exData := resData{
// Region: "eu01",
@ -1028,3 +1122,87 @@ func TestAccInstanceWithDatabases(t *testing.T) {
// }
// return nil
//}
func testAccCheckPostgresFlexDestroy(s *terraform.State) error {
testutils.Setup()
pID, ok := os.LookupEnv("TF_ACC_PROJECT_ID")
if !ok {
log.Fatalln("unable to read TF_ACC_PROJECT_ID")
}
ctx := context.Background()
var client *v3alpha1api.APIClient
var err error
var region, projectID string
region = testutils.Region
if region == "" {
region = "eu01"
}
projectID = pID
if projectID == "" {
return fmt.Errorf("projectID could not be determined in destroy function")
}
apiClientConfigOptions := []config.ConfigurationOption{
config.WithServiceAccountKeyPath(os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE")),
config.WithRegion(region),
}
if testutils.PostgresFlexCustomEndpoint != "" {
apiClientConfigOptions = append(
apiClientConfigOptions,
config.WithEndpoint(testutils.PostgresFlexCustomEndpoint),
)
}
client, err = v3alpha1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instancesToDestroy := []string{}
for _, rs := range s.RootModule().Resources {
if rs.Type != "stackitprivatepreview_postgresflexalpha_instance" &&
rs.Type != "stackitprivatepreview_postgresflexbeta_instance" {
continue
}
// instance terraform ID: = "[project_id],[region],[instance_id]"
instanceID := strings.Split(rs.Primary.ID, core.Separator)[2]
instancesToDestroy = append(instancesToDestroy, instanceID)
}
instancesResp, err := client.DefaultAPI.ListInstancesRequest(ctx, projectID, region).
Size(100).
Execute()
if err != nil {
return fmt.Errorf("getting instancesResp: %w", err)
}
items := instancesResp.GetInstances()
for i := range items {
if items[i].Id == "" {
continue
}
if utils.Contains(instancesToDestroy, items[i].Id) {
err := client.DefaultAPI.DeleteInstanceRequest(ctx, testutils.ProjectId, region, items[i].Id).Execute()
if err != nil {
return fmt.Errorf("deleting instance %s during CheckDestroy: %w", items[i].Id, err)
}
err = postgresflexalpha.DeleteInstanceWaitHandler(
ctx,
client.DefaultAPI,
testutils.ProjectId,
testutils.Region,
items[i].Id,
15*time.Minute,
10*time.Second,
)
if err != nil {
return fmt.Errorf("deleting instance %s during CheckDestroy: waiting for deletion %w", items[i].Id, err)
}
}
}
return nil
}

View file

@ -4,11 +4,11 @@ provider "stackitprivatepreview" {
}
resource "stackitprivatepreview_postgresflexalpha_instance" "{{ .TfName }}" {
project_id = "{{ .ProjectId }}"
project_id = "{{ .ProjectID }}"
name = "{{ .Name }}"
backup_schedule = "{{ .BackupSchedule }}"
retention_days = {{ .RetentionDays }}
flavor_id = "{{ .FlavorId }}"
flavor_id = "{{ .FlavorID }}"
replicas = {{ .Replicas }}
storage = {
performance_class = "{{ .PerformanceClass }}"
@ -16,14 +16,14 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "{{ .TfName }}" {
}
{{ if .UseEncryption }}
encryption = {
kek_key_id = {{ .KekKeyId }}
kek_key_ring_id = {{ .KekKeyRingId }}
kek_key_id = "{{ .KekKeyID }}"
kek_key_ring_id = "{{ .KekKeyRingID }}"
kek_key_version = {{ .KekKeyVersion }}
service_account = "{{ .KekServiceAccount }}"
}
{{ end }}
network = {
acl = ["{{ .AclString }}"]
acl = ["{{ .ACLString }}"]
access_scope = "{{ .AccessScope }}"
}
version = {{ .Version }}
@ -33,7 +33,7 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "{{ .TfName }}" {
{{ $tfName := .TfName }}
{{ range $user := .Users }}
resource "stackitprivatepreview_postgresflexalpha_user" "{{ $user.Name }}" {
project_id = "{{ $user.ProjectId }}"
project_id = "{{ $user.ProjectID }}"
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
name = "{{ $user.Name }}"
roles = [{{ range $i, $v := $user.Roles }}{{if $i}},{{end}}"{{$v}}"{{end}}]
@ -45,7 +45,7 @@ resource "stackitprivatepreview_postgresflexalpha_user" "{{ $user.Name }}" {
{{ $tfName := .TfName }}
{{ range $db := .Databases }}
resource "stackitprivatepreview_postgresflexalpha_database" "{{ $db.Name }}" {
project_id = "{{ $db.ProjectId }}"
project_id = "{{ $db.ProjectID }}"
instance_id = stackitprivatepreview_postgresflexalpha_instance.{{ $tfName }}.instance_id
name = "{{ $db.Name }}"
owner = stackitprivatepreview_postgresflexalpha_user.{{ $db.Owner }}.name

View file

@ -1,27 +0,0 @@
variable "project_id" {}
variable "kek_key_id" {}
variable "kek_key_ring_id" {}
resource "stackitprivatepreview_postgresflexalpha_instance" "msh-instance-only" {
project_id = var.project_id
name = "example-instance"
backup_schedule = "0 0 * * *"
retention_days = 30
flavor_id = "2.4"
replicas = 1
storage = {
performance_class = "premium-perf2-stackit"
size = 10
}
encryption = {
kek_key_id = var.kek_key_id
kek_key_ring_id = var.kek_key_ring_id
kek_key_version = 1
service_account = "service@account.email"
}
network = {
acl = ["0.0.0.0/0"]
access_scope = "PUBLIC"
}
version = 17
}

View file

@ -1,19 +0,0 @@
variable "project_id" {}
resource "stackitprivatepreview_postgresflexalpha_instance" "msh-instance-only" {
project_id = var.project_id
name = "example-instance"
backup_schedule = "0 0 * * *"
retention_days = 30
flavor_id = "2.4"
replicas = 1
storage = {
performance_class = "premium-perf2-stackit"
size = 10
}
network = {
acl = ["0.0.0.0/0"]
access_scope = "PUBLIC"
}
version = 17
}

View file

@ -8,8 +8,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
postgresflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user/datasources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
@ -40,7 +40,7 @@ type dataSourceModel struct {
// userDataSource is the data source implementation.
type userDataSource struct {
client *postgresflex.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -101,24 +101,24 @@ func (r *userDataSource) Read(
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
userId64 := model.UserId.ValueInt64()
if userId64 > math.MaxInt32 {
projectID := model.ProjectId.ValueString()
instanceID := model.InstanceId.ValueString()
userID64 := model.UserId.ValueInt64()
if userID64 > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error in type conversion", "int value too large (userId)")
return
}
userId := int32(userId64) // nolint:gosec // check is performed above
userID := int32(userID64) // nolint:gosec // check is performed above
region := r.providerData.GetRegionWithOverride(model.Region)
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "project_id", projectID)
ctx = tflog.SetField(ctx, "instance_id", instanceID)
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "user_id", userId)
ctx = tflog.SetField(ctx, "user_id", userID)
recordSetResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
recordSetResp, err := r.client.DefaultAPI.GetUserRequest(ctx, projectID, region, instanceID, userID).Execute()
if err != nil {
handleReadError(ctx, &diags, err, projectId, instanceId, userId)
handleReadError(ctx, &diags, err, projectID, instanceID, userID)
resp.State.RemoveResource(ctx)
return
}
@ -151,8 +151,8 @@ func handleReadError(
ctx context.Context,
diags *diag.Diagnostics,
err error,
projectId, instanceId string,
userId int32,
projectID, instanceID string,
userID int32,
) {
utils.LogError(
ctx,
@ -161,23 +161,23 @@ func handleReadError(
"Reading user",
fmt.Sprintf(
"User with ID %q or instance with ID %q does not exist in project %q.",
userId,
instanceId,
projectId,
userID,
instanceID,
projectID,
),
map[int]string{
http.StatusBadRequest: fmt.Sprintf(
"Invalid user request parameters for project %q and instance %q.",
projectId,
instanceId,
projectID,
instanceID,
),
http.StatusNotFound: fmt.Sprintf(
"User, instance %q, or project %q or user %q not found.",
instanceId,
projectId,
userId,
instanceID,
projectID,
userID,
),
http.StatusForbidden: fmt.Sprintf("Forbidden access to project %q.", projectId),
http.StatusForbidden: fmt.Sprintf("Forbidden access to project %q.", projectID),
},
)
}

View file

@ -6,14 +6,14 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
// mapDataSourceFields maps API response to data source model, preserving existing ID.
func mapDataSourceFields(userResp *postgresflex.GetUserResponse, model *dataSourceModel, region string) error {
func mapDataSourceFields(userResp *v3alpha1api.GetUserResponse, model *dataSourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -22,27 +22,24 @@ func mapDataSourceFields(userResp *postgresflex.GetUserResponse, model *dataSour
}
user := userResp
var userId int64
if model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
} else {
var userID int64
if model.UserId.ValueInt64() == 0 {
return fmt.Errorf("user id not present")
}
userID = model.UserId.ValueInt64()
model.TerraformID = utils.BuildInternalTerraformId(
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userID, 10),
)
model.UserId = types.Int64Value(userId)
model.UserId = types.Int64Value(userID)
model.Name = types.StringValue(user.GetName())
if user.Roles == nil {
model.Roles = types.List(types.SetNull(types.StringType))
} else {
var roles []attr.Value
for _, role := range *user.Roles {
for _, role := range user.Roles {
roles = append(roles, types.StringValue(string(role)))
}
rolesSet, diags := types.SetValue(types.StringType, roles)
@ -52,24 +49,24 @@ func mapDataSourceFields(userResp *postgresflex.GetUserResponse, model *dataSour
model.Roles = types.List(rolesSet)
}
model.Id = types.Int64Value(userId)
model.Id = types.Int64Value(userID)
model.Region = types.StringValue(region)
model.Status = types.StringValue(user.GetStatus())
return nil
}
// toPayloadRoles converts a string slice to the API's role type.
func toPayloadRoles(roles *[]string) *[]postgresflex.UserRole {
var userRoles = make([]postgresflex.UserRole, 0, len(*roles))
for _, role := range *roles {
userRoles = append(userRoles, postgresflex.UserRole(role))
func toPayloadRoles(roles []string) []v3alpha1api.UserRole {
var userRoles = make([]v3alpha1api.UserRole, 0, len(roles))
for _, role := range roles {
userRoles = append(userRoles, v3alpha1api.UserRole(role))
}
return &userRoles
return userRoles
}
// toUpdatePayload creates an API update payload from the resource model.
func toUpdatePayload(model *resourceModel, roles *[]string) (
*postgresflex.UpdateUserRequestPayload,
func toUpdatePayload(model *resourceModel, roles []string) (
*v3alpha1api.UpdateUserRequestPayload,
error,
) {
if model == nil {
@ -79,14 +76,14 @@ func toUpdatePayload(model *resourceModel, roles *[]string) (
return nil, fmt.Errorf("nil roles")
}
return &postgresflex.UpdateUserRequestPayload{
return &v3alpha1api.UpdateUserRequestPayload{
Name: model.Name.ValueStringPointer(),
Roles: toPayloadRoles(roles),
}, nil
}
// toCreatePayload creates an API create payload from the resource model.
func toCreatePayload(model *resourceModel, roles *[]string) (*postgresflex.CreateUserRequestPayload, error) {
func toCreatePayload(model *resourceModel, roles []string) (*v3alpha1api.CreateUserRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
@ -94,14 +91,14 @@ func toCreatePayload(model *resourceModel, roles *[]string) (*postgresflex.Creat
return nil, fmt.Errorf("nil roles")
}
return &postgresflex.CreateUserRequestPayload{
return &v3alpha1api.CreateUserRequestPayload{
Roles: toPayloadRoles(roles),
Name: model.Name.ValueStringPointer(),
Name: model.Name.ValueString(),
}, nil
}
// mapResourceFields maps API response to the resource model, preserving existing ID.
func mapResourceFields(userResp *postgresflex.GetUserResponse, model *resourceModel, region string) error {
func mapResourceFields(userResp *v3alpha1api.GetUserResponse, model *resourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -110,24 +107,24 @@ func mapResourceFields(userResp *postgresflex.GetUserResponse, model *resourceMo
}
user := userResp
var userId int64
var userID int64
if !model.UserId.IsNull() && !model.UserId.IsUnknown() && model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
userID = model.UserId.ValueInt64()
} else if user.Id != 0 {
userID = int64(user.Id)
} else {
return fmt.Errorf("user id not present")
}
model.Id = types.Int64Value(userId)
model.UserId = types.Int64Value(userId)
model.Name = types.StringPointerValue(user.Name)
model.Id = types.Int64Value(userID)
model.UserId = types.Int64Value(userID)
model.Name = types.StringValue(user.Name)
if user.Roles == nil {
model.Roles = types.List(types.SetNull(types.StringType))
} else {
var roles []attr.Value
for _, role := range *user.Roles {
for _, role := range user.Roles {
roles = append(roles, types.StringValue(string(role)))
}
rolesSet, diags := types.SetValue(types.StringType, roles)
@ -137,6 +134,6 @@ func mapResourceFields(userResp *postgresflex.GetUserResponse, model *resourceMo
model.Roles = types.List(rolesSet)
}
model.Region = types.StringValue(region)
model.Status = types.StringPointerValue(user.Status)
model.Status = types.StringValue(user.Status)
return nil
}

View file

@ -8,7 +8,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
data "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user/datasources_gen"
)
@ -43,12 +44,12 @@ func TestMapDataSourceFields(t *testing.T) {
{
"simple_values",
&postgresflex.GetUserResponse{
Roles: &[]postgresflex.UserRole{
Roles: []postgresflex.UserRole{
"role_1",
"role_2",
"",
},
Name: utils.Ptr("username"),
Name: "username",
},
testRegion,
dataSourceModel{
@ -77,10 +78,10 @@ func TestMapDataSourceFields(t *testing.T) {
{
"null_fields_and_int_conversions",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]postgresflex.UserRole{},
Name: nil,
Status: utils.Ptr("status"),
Id: int32(1),
Roles: []postgresflex.UserRole{},
Name: "",
Status: "status",
},
testRegion,
dataSourceModel{
@ -160,7 +161,7 @@ func TestMapFieldsCreate(t *testing.T) {
{
"default_values",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Id: int32(1),
},
testRegion,
resourceModel{
@ -168,11 +169,11 @@ func TestMapFieldsCreate(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Name: types.StringNull(),
Name: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringNull(),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
Status: types.StringValue(""),
//ConnectionString: types.StringNull(),
},
true,
@ -180,9 +181,9 @@ func TestMapFieldsCreate(t *testing.T) {
{
"simple_values",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("username"),
Status: utils.Ptr("status"),
Id: int32(1),
Name: "username",
Status: "status",
},
testRegion,
resourceModel{
@ -202,9 +203,9 @@ func TestMapFieldsCreate(t *testing.T) {
{
"null_fields_and_int_conversions",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Name: nil,
Status: nil,
Id: int32(1),
Name: "",
Status: "",
},
testRegion,
resourceModel{
@ -212,11 +213,11 @@ func TestMapFieldsCreate(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Name: types.StringNull(),
Name: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringNull(),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
Status: types.StringValue(""),
//ConnectionString: types.StringNull(),
},
true,
@ -259,7 +260,7 @@ func TestMapFieldsCreate(t *testing.T) {
t.Fatalf("Should not have failed: %v", err)
}
if tt.isValid {
diff := cmp.Diff(state, &tt.expected)
diff := cmp.Diff(&tt.expected, state)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
@ -281,7 +282,7 @@ func TestMapFields(t *testing.T) {
{
"default_values",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Id: int32(1),
},
testRegion,
resourceModel{
@ -289,10 +290,10 @@ func TestMapFields(t *testing.T) {
UserId: types.Int64Value(int64(1)),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Name: types.StringNull(),
Name: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
Status: types.StringValue(""),
//ConnectionString: types.StringNull(),
},
true,
@ -300,13 +301,13 @@ func TestMapFields(t *testing.T) {
{
"simple_values",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]postgresflex.UserRole{
Id: int32(1),
Roles: []postgresflex.UserRole{
"role_1",
"role_2",
"",
},
Name: utils.Ptr("username"),
Name: "username",
},
testRegion,
resourceModel{
@ -325,7 +326,7 @@ func TestMapFields(t *testing.T) {
),
),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
Status: types.StringValue(""),
//ConnectionString: types.StringNull(),
},
true,
@ -333,8 +334,8 @@ func TestMapFields(t *testing.T) {
{
"null_fields_and_int_conversions",
&postgresflex.GetUserResponse{
Id: utils.Ptr(int64(1)),
Name: nil,
Id: int32(1),
Name: "",
},
testRegion,
resourceModel{
@ -342,10 +343,10 @@ func TestMapFields(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Name: types.StringNull(),
Name: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
Status: types.StringValue(""),
//ConnectionString: types.StringNull(),
},
true,
@ -401,17 +402,17 @@ func TestToCreatePayload(t *testing.T) {
tests := []struct {
description string
input *resourceModel
inputRoles *[]string
inputRoles []string
expected *postgresflex.CreateUserRequestPayload
isValid bool
}{
{
"default_values",
&resourceModel{},
&[]string{},
[]string{},
&postgresflex.CreateUserRequestPayload{
Name: nil,
Roles: &[]postgresflex.UserRole{},
Name: "",
Roles: []postgresflex.UserRole{},
},
true,
},
@ -420,13 +421,13 @@ func TestToCreatePayload(t *testing.T) {
&resourceModel{
Name: types.StringValue("username"),
},
&[]string{
[]string{
"role_1",
"role_2",
},
&postgresflex.CreateUserRequestPayload{
Name: utils.Ptr("username"),
Roles: &[]postgresflex.UserRole{
Name: "username",
Roles: []postgresflex.UserRole{
"role_1",
"role_2",
},
@ -438,21 +439,21 @@ func TestToCreatePayload(t *testing.T) {
&resourceModel{
Name: types.StringNull(),
},
&[]string{
[]string{
"",
},
&postgresflex.CreateUserRequestPayload{
Roles: &[]postgresflex.UserRole{
Roles: []postgresflex.UserRole{
"",
},
Name: nil,
Name: "",
},
true,
},
{
"nil_model",
nil,
&[]string{},
[]string{},
nil,
false,
},
@ -489,16 +490,16 @@ func TestToUpdatePayload(t *testing.T) {
tests := []struct {
description string
input *resourceModel
inputRoles *[]string
inputRoles []string
expected *postgresflex.UpdateUserRequestPayload
isValid bool
}{
{
"default_values",
&resourceModel{},
&[]string{},
[]string{},
&postgresflex.UpdateUserRequestPayload{
Roles: &[]postgresflex.UserRole{},
Roles: []postgresflex.UserRole{},
},
true,
},
@ -507,13 +508,13 @@ func TestToUpdatePayload(t *testing.T) {
&resourceModel{
Name: types.StringValue("username"),
},
&[]string{
[]string{
"role_1",
"role_2",
},
&postgresflex.UpdateUserRequestPayload{
Name: utils.Ptr("username"),
Roles: &[]postgresflex.UserRole{
Roles: []postgresflex.UserRole{
"role_1",
"role_2",
},
@ -525,11 +526,11 @@ func TestToUpdatePayload(t *testing.T) {
&resourceModel{
Name: types.StringNull(),
},
&[]string{
[]string{
"",
},
&postgresflex.UpdateUserRequestPayload{
Roles: &[]postgresflex.UserRole{
Roles: []postgresflex.UserRole{
"",
},
},
@ -538,7 +539,7 @@ func TestToUpdatePayload(t *testing.T) {
{
"nil_model",
nil,
&[]string{},
[]string{},
nil,
false,
},

View file

@ -12,8 +12,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user/resources_gen"
postgresflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
postgresflexalphaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
@ -60,7 +60,7 @@ type UserResourceIdentityModel struct {
// userResource implements the resource handling for a PostgreSQL Flex user.
type userResource struct {
client *postgresflex.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -189,8 +189,8 @@ func (r *userResource) Create(
ctx = core.InitProviderContext(ctx)
arg := &clientArg{
projectId: model.ProjectId.ValueString(),
instanceId: model.InstanceId.ValueString(),
projectID: model.ProjectId.ValueString(),
instanceID: model.InstanceId.ValueString(),
region: r.providerData.GetRegionWithOverride(model.Region),
}
@ -202,18 +202,18 @@ func (r *userResource) Create(
}
// Generate API request body from model
payload, err := toCreatePayload(&model, &roles)
payload, err := toCreatePayload(&model, roles)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Creating API payload: %v", err))
return
}
// Create new user
userResp, err := r.client.CreateUserRequest(
userResp, err := r.client.DefaultAPI.CreateUserRequest(
ctx,
arg.projectId,
arg.projectID,
arg.region,
arg.instanceId,
arg.instanceID,
).CreateUserRequestPayload(*payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err))
@ -221,7 +221,7 @@ func (r *userResource) Create(
}
id, ok := userResp.GetIdOk()
if !ok || id == 0 {
if !ok || *id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -230,7 +230,7 @@ func (r *userResource) Create(
)
return
}
arg.userId = id
arg.userID = int64(*id)
ctx = tflog.SetField(ctx, "user_id", id)
@ -238,28 +238,28 @@ func (r *userResource) Create(
// Set data returned by API in identity
identity := UserResourceIdentityModel{
ProjectID: types.StringValue(arg.projectId),
ProjectID: types.StringValue(arg.projectID),
Region: types.StringValue(arg.region),
InstanceID: types.StringValue(arg.instanceId),
UserID: types.Int64Value(id),
InstanceID: types.StringValue(arg.instanceID),
UserID: types.Int64Value(int64(*id)),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
return
}
model.Id = types.Int64Value(id)
model.UserId = types.Int64Value(id)
model.Id = types.Int64Value(int64(*id))
model.UserId = types.Int64Value(int64(*id))
model.Password = types.StringValue(userResp.GetPassword())
model.Status = types.StringValue(userResp.GetStatus())
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
ctx,
r.client,
arg.projectId,
arg.instanceId,
r.client.DefaultAPI,
arg.projectID,
arg.instanceID,
arg.region,
id,
int64(*id),
).SetSleepBeforeWait(
10 * time.Second,
).SetTimeout(
@ -276,7 +276,7 @@ func (r *userResource) Create(
return
}
if waitResp.Id == nil {
if waitResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -285,7 +285,7 @@ func (r *userResource) Create(
)
return
}
if waitResp.Id == nil || *waitResp.Id != id {
if waitResp.Id != *id {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -324,8 +324,8 @@ func (r *userResource) Read(
ctx = core.InitProviderContext(ctx)
arg := &clientArg{
projectId: model.ProjectId.ValueString(),
instanceId: model.InstanceId.ValueString(),
projectID: model.ProjectId.ValueString(),
instanceID: model.InstanceId.ValueString(),
region: r.providerData.GetRegionWithOverride(model.Region),
}
@ -336,9 +336,9 @@ func (r *userResource) Read(
// Read resource state
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
ctx,
r.client,
arg.projectId,
arg.instanceId,
r.client.DefaultAPI,
arg.projectID,
arg.instanceID,
arg.region,
model.UserId.ValueInt64(),
).SetSleepBeforeWait(
@ -357,7 +357,7 @@ func (r *userResource) Read(
return
}
if waitResp.Id == nil || *waitResp.Id != model.UserId.ValueInt64() {
if int64(waitResp.Id) != model.UserId.ValueInt64() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -366,16 +366,16 @@ func (r *userResource) Read(
)
return
}
arg.userId = *waitResp.Id
arg.userID = int64(waitResp.Id)
ctx = core.LogResponse(ctx)
// Set data returned by API in identity
identity := UserResourceIdentityModel{
ProjectID: types.StringValue(arg.projectId),
ProjectID: types.StringValue(arg.projectID),
Region: types.StringValue(arg.region),
InstanceID: types.StringValue(arg.instanceId),
UserID: types.Int64Value(arg.userId),
InstanceID: types.StringValue(arg.instanceID),
UserID: types.Int64Value(arg.userID),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -407,8 +407,8 @@ func (r *userResource) Update(
ctx = core.InitProviderContext(ctx)
arg := &clientArg{
projectId: model.ProjectId.ValueString(),
instanceId: model.InstanceId.ValueString(),
projectID: model.ProjectId.ValueString(),
instanceID: model.InstanceId.ValueString(),
region: r.providerData.GetRegionWithOverride(model.Region),
}
@ -429,26 +429,26 @@ func (r *userResource) Update(
}
// Generate API request body from model
payload, err := toUpdatePayload(&model, &roles)
payload, err := toUpdatePayload(&model, roles)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", fmt.Sprintf("Updating API payload: %v", err))
return
}
userId64 := arg.userId
if userId64 > math.MaxInt32 {
userID64 := arg.userID
if userID64 > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error in type conversion", "int value too large (userId)")
return
}
userId := int32(userId64) // nolint:gosec // check is performed above
userID := int32(userID64) // nolint:gosec // check is performed above
// Update existing instance
err = r.client.UpdateUserRequest(
err = r.client.DefaultAPI.UpdateUserRequest(
ctx,
arg.projectId,
arg.projectID,
arg.region,
arg.instanceId,
userId,
arg.instanceID,
userID,
).UpdateUserRequestPayload(*payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", err.Error())
@ -459,10 +459,10 @@ func (r *userResource) Update(
// Set data returned by API in identity
identity := UserResourceIdentityModel{
ProjectID: types.StringValue(arg.projectId),
ProjectID: types.StringValue(arg.projectID),
Region: types.StringValue(arg.region),
InstanceID: types.StringValue(arg.instanceId),
UserID: types.Int64Value(userId64),
InstanceID: types.StringValue(arg.instanceID),
UserID: types.Int64Value(userID64),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -472,9 +472,9 @@ func (r *userResource) Update(
// Verify update
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
ctx,
r.client,
arg.projectId,
arg.instanceId,
r.client.DefaultAPI,
arg.projectID,
arg.instanceID,
arg.region,
model.UserId.ValueInt64(),
).SetSleepBeforeWait(
@ -493,7 +493,7 @@ func (r *userResource) Update(
return
}
if waitResp.Id == nil || *waitResp.Id != model.UserId.ValueInt64() {
if int64(waitResp.Id) != model.UserId.ValueInt64() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -502,7 +502,7 @@ func (r *userResource) Update(
)
return
}
arg.userId = *waitResp.Id
arg.userID = int64(waitResp.Id)
// Set state to fully populated data
diags = resp.State.Set(ctx, stateModel)
@ -547,15 +547,15 @@ func (r *userResource) Delete(
ctx = r.setTFLogFields(ctx, arg)
ctx = core.InitProviderContext(ctx)
userId64 := arg.userId
if userId64 > math.MaxInt32 {
userID64 := arg.userID
if userID64 > math.MaxInt32 {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error in type conversion", "int value too large (userId)")
return
}
userId := int32(userId64) // nolint:gosec // check is performed above
userID := int32(userID64) // nolint:gosec // check is performed above
// Delete existing record set
err := r.client.DeleteUserRequest(ctx, arg.projectId, arg.region, arg.instanceId, userId).Execute()
err := r.client.DefaultAPI.DeleteUserRequest(ctx, arg.projectID, arg.region, arg.instanceID, userID).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting user", fmt.Sprintf("Calling API: %v", err))
}
@ -571,7 +571,7 @@ func (r *userResource) Delete(
// if exists {
// core.LogAndAddError(
// ctx, &resp.Diagnostics, "Error deleting user",
// fmt.Sprintf("User ID '%v' resource still exists after deletion", model.UserId.ValueInt64()),
// fmt.Sprintf("User ID '%v' resource still exists after deletion", model.UserId.ValueInt32()),
// )
// return
//}
@ -607,10 +607,10 @@ func (r *userResource) IdentitySchema(
// clientArg holds the arguments for API calls.
type clientArg struct {
projectId string
instanceId string
projectID string
instanceID string
region string
userId int64
userID int64
}
// ImportState imports a resource into the Terraform state on success.
@ -637,7 +637,7 @@ func (r *userResource) ImportState(
return
}
userId, err := strconv.ParseInt(idParts[3], 10, 64)
userID, err := strconv.ParseInt(idParts[3], 10, 64)
if err != nil {
core.LogAndAddError(
ctx,
@ -651,7 +651,7 @@ func (r *userResource) ImportState(
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("region"), idParts[1])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("instance_id"), idParts[2])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("user_id"), userId)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("user_id"), userID)...)
tflog.Info(ctx, "Postgres Flex user state imported")
@ -665,15 +665,15 @@ func (r *userResource) ImportState(
return
}
projectId := identityData.ProjectID.ValueString()
projectID := identityData.ProjectID.ValueString()
region := identityData.Region.ValueString()
instanceId := identityData.InstanceID.ValueString()
userId := identityData.UserID.ValueInt64()
instanceID := identityData.InstanceID.ValueString()
userID := identityData.UserID.ValueInt64()
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), projectId)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), projectID)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("region"), region)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("instance_id"), instanceId)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("user_id"), userId)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("instance_id"), instanceID)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("user_id"), userID)...)
tflog.Info(ctx, "Postgres Flex user state imported")
}
@ -683,25 +683,24 @@ func (r *userResource) extractIdentityData(
model resourceModel,
identity UserResourceIdentityModel,
) (*clientArg, error) {
var projectId, region, instanceId string
var userId int64
var projectID, region, instanceID string
var userID int64
if !model.UserId.IsNull() && !model.UserId.IsUnknown() {
userId = model.UserId.ValueInt64()
userID = model.UserId.ValueInt64()
} else {
if identity.UserID.IsNull() || identity.UserID.IsUnknown() {
return nil, fmt.Errorf("user_id not found in config")
}
userId = identity.UserID.ValueInt64()
userID = identity.UserID.ValueInt64()
}
if !model.ProjectId.IsNull() && !model.ProjectId.IsUnknown() {
projectId = model.ProjectId.ValueString()
projectID = model.ProjectId.ValueString()
} else {
if identity.ProjectID.IsNull() || identity.ProjectID.IsUnknown() {
return nil, fmt.Errorf("project_id not found in config")
}
projectId = identity.ProjectID.ValueString()
projectID = identity.ProjectID.ValueString()
}
if !model.Region.IsNull() && !model.Region.IsUnknown() {
@ -714,27 +713,27 @@ func (r *userResource) extractIdentityData(
}
if !model.InstanceId.IsNull() && !model.InstanceId.IsUnknown() {
instanceId = model.InstanceId.ValueString()
instanceID = model.InstanceId.ValueString()
} else {
if identity.InstanceID.IsNull() || identity.InstanceID.IsUnknown() {
return nil, fmt.Errorf("instance_id not found in config")
}
instanceId = identity.InstanceID.ValueString()
instanceID = identity.InstanceID.ValueString()
}
return &clientArg{
projectId: projectId,
instanceId: instanceId,
projectID: projectID,
instanceID: instanceID,
region: region,
userId: userId,
userID: userID,
}, nil
}
// setTFLogFields adds relevant fields to the context for terraform logging purposes.
func (r *userResource) setTFLogFields(ctx context.Context, arg *clientArg) context.Context {
ctx = tflog.SetField(ctx, "project_id", arg.projectId)
ctx = tflog.SetField(ctx, "instance_id", arg.instanceId)
ctx = tflog.SetField(ctx, "project_id", arg.projectID)
ctx = tflog.SetField(ctx, "instance_id", arg.instanceID)
ctx = tflog.SetField(ctx, "region", arg.region)
ctx = tflog.SetField(ctx, "user_id", arg.userId)
ctx = tflog.SetField(ctx, "user_id", arg.userID)
return ctx
}

View file

@ -9,7 +9,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/stackitcloud/stackit-sdk-go/core/config"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"

View file

@ -15,7 +15,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
const (
@ -38,7 +38,7 @@ func TestConfigureClient(t *testing.T) {
name string
args args
wantErr bool
expected *postgresflex.APIClient
expected *v3alpha1api.APIClient
}{
{
name: "default endpoint",
@ -47,8 +47,8 @@ func TestConfigureClient(t *testing.T) {
Version: testVersion,
},
},
expected: func() *postgresflex.APIClient {
apiClient, err := postgresflex.NewAPIClient(
expected: func() *v3alpha1api.APIClient {
apiClient, err := v3alpha1api.NewAPIClient(
config.WithRegion("eu01"),
utils.UserAgentConfigOption(testVersion),
)
@ -67,8 +67,8 @@ func TestConfigureClient(t *testing.T) {
PostgresFlexCustomEndpoint: testCustomEndpoint,
},
},
expected: func() *postgresflex.APIClient {
apiClient, err := postgresflex.NewAPIClient(
expected: func() *v3alpha1api.APIClient {
apiClient, err := v3alpha1api.NewAPIClient(
utils.UserAgentConfigOption(testVersion),
config.WithEndpoint(testCustomEndpoint),
)

View file

@ -16,7 +16,8 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalphaPkg "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
)
@ -119,7 +120,7 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
databaseName := data.DatabaseName.ValueString()
databaseResp, err := d.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
databaseResp, err := d.client.DefaultAPI.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
handleReadError(ctx, &resp.Diagnostics, err, projectId, instanceId)
resp.State.RemoveResource(ctx)
@ -142,7 +143,7 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "SQL Server Flex beta database read")
tflog.Info(ctx, "SQL Server Flex Alpha database read")
}
// handleReadError centralizes API error handling for the Read operation.

View file

@ -5,8 +5,10 @@ import (
"strings"
"github.com/hashicorp/terraform-plugin-framework/types"
coreUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
@ -15,7 +17,7 @@ func mapFields(source *sqlserverflexalpha.GetDatabaseResponse, model *dataSource
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -25,8 +27,8 @@ func mapFields(source *sqlserverflexalpha.GetDatabaseResponse, model *dataSource
var databaseId int64
if model.Id.ValueInt64() != 0 {
databaseId = model.Id.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = source.Id
} else {
return fmt.Errorf("database id not present")
}
@ -38,7 +40,7 @@ func mapFields(source *sqlserverflexalpha.GetDatabaseResponse, model *dataSource
model.Region = types.StringValue(region)
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
model.CompatibilityLevel = types.Int64Value(source.GetCompatibilityLevel())
model.CompatibilityLevel = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.CollationName = types.StringValue(source.GetCollationName())
model.TerraformId = utils.BuildInternalTerraformId(
@ -56,7 +58,7 @@ func mapResourceFields(source *sqlserverflexalpha.GetDatabaseResponse, model *re
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -66,8 +68,8 @@ func mapResourceFields(source *sqlserverflexalpha.GetDatabaseResponse, model *re
var databaseId int64
if model.Id.ValueInt64() != 0 {
databaseId = model.Id.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = source.Id
} else {
return fmt.Errorf("database id not present")
}
@ -80,8 +82,8 @@ func mapResourceFields(source *sqlserverflexalpha.GetDatabaseResponse, model *re
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
model.Compatibility = types.Int64Value(source.GetCompatibilityLevel())
model.CompatibilityLevel = types.Int64Value(source.GetCompatibilityLevel())
model.Compatibility = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.CompatibilityLevel = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.Collation = types.StringValue(source.GetCollationName()) // it does not come back from api
model.CollationName = types.StringValue(source.GetCollationName())
@ -96,9 +98,9 @@ func toCreatePayload(model *resourceModel) (*sqlserverflexalpha.CreateDatabaseRe
}
return &sqlserverflexalpha.CreateDatabaseRequestPayload{
Name: model.Name.ValueStringPointer(),
Owner: model.Owner.ValueStringPointer(),
Name: model.Name.ValueString(),
Owner: model.Owner.ValueString(),
Collation: model.Collation.ValueStringPointer(),
Compatibility: model.Compatibility.ValueInt64Pointer(),
Compatibility: coreUtils.Ptr(int32(model.Compatibility.ValueInt64())), //nolint:gosec // TODO
}, nil
}

View file

@ -6,8 +6,8 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
datasource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
)
@ -31,11 +31,11 @@ func TestMapFields(t *testing.T) {
name: "should map fields correctly",
given: given{
source: &sqlserverflexalpha.GetDatabaseResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
CollationName: utils.Ptr("collation"),
CompatibilityLevel: utils.Ptr(int64(150)),
Owner: utils.Ptr("my-owner"),
Id: (int64(1)),
Name: ("my-db"),
CollationName: ("collation"),
CompatibilityLevel: (int32(150)),
Owner: ("my-owner"),
},
model: &dataSourceModel{
DatabaseModel: datasource.DatabaseModel{
@ -73,7 +73,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil source ID",
given: given{
source: &sqlserverflexalpha.GetDatabaseResponse{Id: nil},
source: &sqlserverflexalpha.GetDatabaseResponse{Id: 0},
model: &dataSourceModel{},
},
expected: expected{err: true},
@ -81,7 +81,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil model",
given: given{
source: &sqlserverflexalpha.GetDatabaseResponse{Id: utils.Ptr(int64(1))},
source: &sqlserverflexalpha.GetDatabaseResponse{Id: (int64(1))},
model: nil,
},
expected: expected{err: true},
@ -125,9 +125,9 @@ func TestMapResourceFields(t *testing.T) {
name: "should map fields correctly",
given: given{
source: &sqlserverflexalpha.GetDatabaseResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("my-owner"),
Id: (int64(1)),
Name: ("my-db"),
Owner: ("my-owner"),
},
model: &resourceModel{
ProjectId: types.StringValue("my-project"),
@ -202,8 +202,9 @@ func TestToCreatePayload(t *testing.T) {
},
expected: expected{
payload: &sqlserverflexalpha.CreateDatabaseRequestPayload{
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("my-owner"),
Name: "my-db",
Owner: "my-owner",
Compatibility: utils.Ptr(int32(0)),
},
},
},

View file

@ -16,8 +16,10 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
coreUtils "github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
wait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexalpha"
@ -176,13 +178,13 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
}
if !data.Compatibility.IsNull() && !data.Compatibility.IsUnknown() {
payLoad.Compatibility = data.Compatibility.ValueInt64Pointer()
payLoad.Compatibility = coreUtils.Ptr(int32(data.Compatibility.ValueInt64())) //nolint:gosec // TODO
}
payLoad.Name = data.Name.ValueStringPointer()
payLoad.Owner = data.Owner.ValueStringPointer()
payLoad.Name = data.Name.ValueString()
payLoad.Owner = data.Owner.ValueString()
createResp, err := r.client.CreateDatabaseRequest(ctx, projectId, region, instanceId).
createResp, err := r.client.DefaultAPI.CreateDatabaseRequest(ctx, projectId, region, instanceId).
CreateDatabaseRequestPayload(payLoad).
Execute()
if err != nil {
@ -195,7 +197,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if createResp == nil || createResp.Id == nil {
if createResp == nil || createResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -205,7 +207,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
databaseId := *createResp.Id
databaseId := createResp.Id
ctx = tflog.SetField(ctx, "database_id", databaseId)
@ -226,7 +228,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
// TODO: is this necessary to wait for the database-> API say 200 ?
waitResp, err := wait.CreateDatabaseWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
instanceId,
region,
@ -246,7 +248,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if waitResp.Id == nil {
if waitResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -256,7 +258,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Id != databaseId {
if waitResp.Id != databaseId {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -266,7 +268,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Owner != data.Owner.ValueString() {
if waitResp.Owner != data.Owner.ValueString() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -276,7 +278,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Name != data.Name.ValueString() {
if waitResp.Name != data.Name.ValueString() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -286,7 +288,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
database, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
database, err := r.client.DefaultAPI.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
core.LogAndAddError(
ctx,
@ -340,7 +342,7 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "database_name", databaseName)
databaseResp, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
databaseResp, err := r.client.DefaultAPI.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if (ok && oapiErr.StatusCode == http.StatusNotFound) || errors.Is(err, errDatabaseNotFound) {
@ -420,7 +422,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = tflog.SetField(ctx, "database_name", databaseName)
// Delete existing record set
err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
err := r.client.DefaultAPI.DeleteDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
core.LogAndAddError(
ctx,

View file

@ -16,7 +16,8 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalphaPkg "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavor/datasources_gen"
)
@ -273,7 +274,7 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
flavors, err := getAllFlavors(ctx, r.client, projectId, region)
flavors, err := getAllFlavors(ctx, r.client.DefaultAPI, projectId, region)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
return
@ -281,17 +282,17 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
var foundFlavors []sqlserverflexalphaPkg.ListFlavors
for _, flavor := range flavors {
if model.Cpu.ValueInt64() != *flavor.Cpu {
if model.Cpu.ValueInt64() != flavor.Cpu {
continue
}
if model.Memory.ValueInt64() != *flavor.Memory {
if model.Memory.ValueInt64() != flavor.Memory {
continue
}
if model.NodeType.ValueString() != *flavor.NodeType {
if model.NodeType.ValueString() != flavor.NodeType {
continue
}
for _, sc := range *flavor.StorageClasses {
if model.StorageClass.ValueString() != *sc.Class {
for _, sc := range flavor.StorageClasses {
if model.StorageClass.ValueString() != sc.Class {
continue
}
foundFlavors = append(foundFlavors, flavor)
@ -307,11 +308,11 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
}
f := foundFlavors[0]
model.Description = types.StringValue(*f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, *f.Id)
model.FlavorId = types.StringValue(*f.Id)
model.MaxGb = types.Int64Value(*f.MaxGB)
model.MinGb = types.Int64Value(*f.MinGB)
model.Description = types.StringValue(f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, f.Id)
model.FlavorId = types.StringValue(f.Id)
model.MaxGb = types.Int64Value(int64(f.MaxGB))
model.MinGb = types.Int64Value(int64(f.MinGB))
if f.StorageClasses == nil {
model.StorageClasses = types.ListNull(sqlserverflexalphaGen.StorageClassesType{
@ -321,15 +322,15 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
})
} else {
var scList []attr.Value
for _, sc := range *f.StorageClasses {
for _, sc := range f.StorageClasses {
scList = append(
scList,
sqlserverflexalphaGen.NewStorageClassesValueMust(
sqlserverflexalphaGen.StorageClassesValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"class": types.StringValue(*sc.Class),
"max_io_per_sec": types.Int64Value(*sc.MaxIoPerSec),
"max_through_in_mb": types.Int64Value(*sc.MaxThroughInMb),
"class": types.StringValue(sc.Class),
"max_io_per_sec": types.Int64Value(int64(sc.MaxIoPerSec)),
"max_through_in_mb": types.Int64Value(int64(sc.MaxThroughInMb)),
},
),
)

View file

@ -4,7 +4,7 @@ import (
"context"
"fmt"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
type flavorsClientReader interface {
@ -50,11 +50,11 @@ func getFlavorsByFilter(
}
// If the API returns no flavors, we have reached the end of the list.
if res.Flavors == nil || len(*res.Flavors) == 0 {
if len(res.Flavors) == 0 {
break
}
for _, flavor := range *res.Flavors {
for _, flavor := range res.Flavors {
if filter(flavor) {
result = append(result, flavor)
}

View file

@ -4,81 +4,58 @@ import (
"context"
"testing"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
type mockRequest struct {
executeFunc func() (*sqlserverflexalpha.GetFlavorsResponse, error)
}
func (m *mockRequest) Page(_ int64) sqlserverflexalpha.ApiGetFlavorsRequestRequest { return m }
func (m *mockRequest) Size(_ int64) sqlserverflexalpha.ApiGetFlavorsRequestRequest { return m }
func (m *mockRequest) Sort(_ sqlserverflexalpha.FlavorSort) sqlserverflexalpha.ApiGetFlavorsRequestRequest {
return m
}
func (m *mockRequest) Execute() (*sqlserverflexalpha.GetFlavorsResponse, error) {
return m.executeFunc()
}
type mockFlavorsClient struct {
executeRequest func() sqlserverflexalpha.ApiGetFlavorsRequestRequest
}
func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) sqlserverflexalpha.ApiGetFlavorsRequestRequest {
return m.executeRequest()
}
var mockResp = func(page int64) (*sqlserverflexalpha.GetFlavorsResponse, error) {
var mockResp = func(page int64) (*v3alpha1api.GetFlavorsResponse, error) {
if page == 1 {
return &sqlserverflexalpha.GetFlavorsResponse{
Flavors: &[]sqlserverflexalpha.ListFlavors{
{Id: utils.Ptr("flavor-1"), Description: utils.Ptr("first")},
{Id: utils.Ptr("flavor-2"), Description: utils.Ptr("second")},
return &v3alpha1api.GetFlavorsResponse{
Flavors: []v3alpha1api.ListFlavors{
{Id: "flavor-1", Description: "first"},
{Id: "flavor-2", Description: "second"},
},
}, nil
}
if page == 2 {
return &sqlserverflexalpha.GetFlavorsResponse{
Flavors: &[]sqlserverflexalpha.ListFlavors{
{Id: utils.Ptr("flavor-3"), Description: utils.Ptr("three")},
return &v3alpha1api.GetFlavorsResponse{
Flavors: []v3alpha1api.ListFlavors{
{Id: "flavor-3", Description: "three"},
},
}, nil
}
return &sqlserverflexalpha.GetFlavorsResponse{
Flavors: &[]sqlserverflexalpha.ListFlavors{},
return &v3alpha1api.GetFlavorsResponse{
Flavors: []v3alpha1api.ListFlavors{},
}, nil
}
func TestGetFlavorsByFilter(t *testing.T) {
tests := []struct {
description string
projectId string
projectID string
region string
mockErr error
filter func(sqlserverflexalpha.ListFlavors) bool
filter func(v3alpha1api.ListFlavors) bool
wantCount int
wantErr bool
}{
{
description: "Success - Get all flavors (2 pages)",
projectId: "pid", region: "reg",
filter: func(_ sqlserverflexalpha.ListFlavors) bool { return true },
projectID: "pid", region: "reg",
filter: func(_ v3alpha1api.ListFlavors) bool { return true },
wantCount: 3,
wantErr: false,
},
{
description: "Success - Filter flavors by description",
projectId: "pid", region: "reg",
filter: func(f sqlserverflexalpha.ListFlavors) bool { return *f.Description == "first" },
projectID: "pid", region: "reg",
filter: func(f v3alpha1api.ListFlavors) bool { return f.Description == "first" },
wantCount: 1,
wantErr: false,
},
{
description: "Error - Missing parameters",
projectId: "", region: "reg",
projectID: "", region: "reg",
wantErr: true,
},
}
@ -87,17 +64,15 @@ func TestGetFlavorsByFilter(t *testing.T) {
t.Run(
tt.description, func(t *testing.T) {
var currentPage int64
client := &mockFlavorsClient{
executeRequest: func() sqlserverflexalpha.ApiGetFlavorsRequestRequest {
return &mockRequest{
executeFunc: func() (*sqlserverflexalpha.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
},
}
},
getFlavorsMock := func(_ v3alpha1api.ApiGetFlavorsRequestRequest) (*v3alpha1api.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
}
actual, err := getFlavorsByFilter(context.Background(), client, tt.projectId, tt.region, tt.filter)
client := v3alpha1api.DefaultAPIServiceMock{
GetFlavorsRequestExecuteMock: &getFlavorsMock,
}
actual, err := getFlavorsByFilter(context.Background(), client, tt.projectID, tt.region, tt.filter)
if (err != nil) != tt.wantErr {
t.Errorf("getFlavorsByFilter() error = %v, wantErr %v", err, tt.wantErr)
@ -114,15 +89,14 @@ func TestGetFlavorsByFilter(t *testing.T) {
func TestGetAllFlavors(t *testing.T) {
var currentPage int64
client := &mockFlavorsClient{
executeRequest: func() sqlserverflexalpha.ApiGetFlavorsRequestRequest {
return &mockRequest{
executeFunc: func() (*sqlserverflexalpha.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
},
}
},
getFlavorsMock := func(_ v3alpha1api.ApiGetFlavorsRequestRequest) (*v3alpha1api.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
}
client := v3alpha1api.DefaultAPIServiceMock{
GetFlavorsRequestExecuteMock: &getFlavorsMock,
}
res, err := getAllFlavors(context.Background(), client, "pid", "reg")

View file

@ -15,7 +15,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalphaPkg "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavors/datasources_gen"
)
@ -121,7 +121,7 @@ func (d *flavorsDataSource) Read(ctx context.Context, req datasource.ReadRequest
ctx = tflog.SetField(ctx, "flavors_id", flavorsId)
// TODO: refactor to correct implementation
_, err := d.client.GetFlavorsRequest(ctx, projectId, region).Execute()
_, err := d.client.DefaultAPI.GetFlavorsRequest(ctx, projectId, region).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -14,7 +14,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance/datasources_gen"
)
@ -34,7 +34,7 @@ type dataSourceModel struct {
}
type instanceDataSource struct {
client *sqlserverflexalphaPkg.APIClient
client *v3alpha1api.APIClient
providerData core.ProviderData
}
@ -77,7 +77,7 @@ func (d *instanceDataSource) Configure(
config.WithRegion(d.providerData.GetRegion()),
)
}
apiClient, err := sqlserverflexalphaPkg.NewAPIClient(apiClientConfigOptions...)
apiClient, err := v3alpha1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
@ -112,7 +112,7 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
instanceResp, err := d.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := d.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -11,8 +11,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaDataGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance/datasources_gen"
sqlserverflexalphaResGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance/resources_gen"
)
@ -53,7 +53,7 @@ func mapResponseToModel(
}
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Status = types.StringValue(string(resp.GetStatus()))
stor, diags := sqlserverflexalphaResGen.NewStorageValue(
@ -109,7 +109,7 @@ func mapDataResponseToModel(
}
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Status = types.StringValue(string(resp.GetStatus()))
stor, diags := sqlserverflexalphaDataGen.NewStorageValue(
@ -135,10 +135,10 @@ func handleEncryption(
) sqlserverflexalphaResGen.EncryptionValue {
if !resp.HasEncryption() ||
resp.Encryption == nil ||
resp.Encryption.KekKeyId == nil ||
resp.Encryption.KekKeyRingId == nil ||
resp.Encryption.KekKeyVersion == nil ||
resp.Encryption.ServiceAccount == nil {
resp.Encryption.KekKeyId == "" ||
resp.Encryption.KekKeyRingId == "" ||
resp.Encryption.KekKeyVersion == "" ||
resp.Encryption.ServiceAccount == "" {
if m.Encryption.IsNull() || m.Encryption.IsUnknown() {
return sqlserverflexalphaResGen.NewEncryptionValueNull()
}
@ -147,16 +147,16 @@ func handleEncryption(
enc := sqlserverflexalphaResGen.NewEncryptionValueNull()
if kVal, ok := resp.Encryption.GetKekKeyIdOk(); ok {
enc.KekKeyId = types.StringValue(kVal)
enc.KekKeyId = types.StringValue(*kVal)
}
if kkVal, ok := resp.Encryption.GetKekKeyRingIdOk(); ok {
enc.KekKeyRingId = types.StringValue(kkVal)
enc.KekKeyRingId = types.StringValue(*kkVal)
}
if kkvVal, ok := resp.Encryption.GetKekKeyVersionOk(); ok {
enc.KekKeyVersion = types.StringValue(kkvVal)
enc.KekKeyVersion = types.StringValue(*kkvVal)
}
if sa, ok := resp.Encryption.GetServiceAccountOk(); ok {
enc.ServiceAccount = types.StringValue(sa)
enc.ServiceAccount = types.StringValue(*sa)
}
return enc
}
@ -167,10 +167,10 @@ func handleDSEncryption(
) sqlserverflexalphaDataGen.EncryptionValue {
if !resp.HasEncryption() ||
resp.Encryption == nil ||
resp.Encryption.KekKeyId == nil ||
resp.Encryption.KekKeyRingId == nil ||
resp.Encryption.KekKeyVersion == nil ||
resp.Encryption.ServiceAccount == nil {
resp.Encryption.KekKeyId == "" ||
resp.Encryption.KekKeyRingId == "" ||
resp.Encryption.KekKeyVersion == "" ||
resp.Encryption.ServiceAccount == "" {
if m.Encryption.IsNull() || m.Encryption.IsUnknown() {
return sqlserverflexalphaDataGen.NewEncryptionValueNull()
}
@ -179,16 +179,16 @@ func handleDSEncryption(
enc := sqlserverflexalphaDataGen.NewEncryptionValueNull()
if kVal, ok := resp.Encryption.GetKekKeyIdOk(); ok {
enc.KekKeyId = types.StringValue(kVal)
enc.KekKeyId = types.StringValue(*kVal)
}
if kkVal, ok := resp.Encryption.GetKekKeyRingIdOk(); ok {
enc.KekKeyRingId = types.StringValue(kkVal)
enc.KekKeyRingId = types.StringValue(*kkVal)
}
if kkvVal, ok := resp.Encryption.GetKekKeyVersionOk(); ok {
enc.KekKeyVersion = types.StringValue(kkvVal)
enc.KekKeyVersion = types.StringValue(*kkvVal)
}
if sa, ok := resp.Encryption.GetServiceAccountOk(); ok {
enc.ServiceAccount = types.StringValue(sa)
enc.ServiceAccount = types.StringValue(*sa)
}
return enc
}
@ -201,51 +201,47 @@ func toCreatePayload(
return nil, fmt.Errorf("nil model")
}
storagePayload := &sqlserverflexalpha.CreateInstanceRequestPayloadGetStorageArgType{}
storagePayload := sqlserverflexalpha.StorageCreate{}
if !model.Storage.IsNull() && !model.Storage.IsUnknown() {
storagePayload.Class = model.Storage.Class.ValueStringPointer()
storagePayload.Size = model.Storage.Size.ValueInt64Pointer()
storagePayload.Class = model.Storage.Class.ValueString()
storagePayload.Size = model.Storage.Size.ValueInt64()
}
var encryptionPayload *sqlserverflexalpha.CreateInstanceRequestPayloadGetEncryptionArgType = nil
var encryptionPayload *sqlserverflexalpha.InstanceEncryption = nil
if !model.Encryption.IsNull() && !model.Encryption.IsUnknown() &&
!model.Encryption.KekKeyId.IsNull() && model.Encryption.KekKeyId.IsUnknown() && model.Encryption.KekKeyId.ValueString() != "" &&
!model.Encryption.KekKeyRingId.IsNull() && !model.Encryption.KekKeyRingId.IsUnknown() && model.Encryption.KekKeyRingId.ValueString() != "" &&
!model.Encryption.KekKeyVersion.IsNull() && !model.Encryption.KekKeyVersion.IsUnknown() && model.Encryption.KekKeyVersion.ValueString() != "" &&
!model.Encryption.ServiceAccount.IsNull() && !model.Encryption.ServiceAccount.IsUnknown() && model.Encryption.ServiceAccount.ValueString() != "" {
encryptionPayload = &sqlserverflexalpha.CreateInstanceRequestPayloadGetEncryptionArgType{
KekKeyId: model.Encryption.KekKeyId.ValueStringPointer(),
KekKeyRingId: model.Encryption.KekKeyVersion.ValueStringPointer(),
KekKeyVersion: model.Encryption.KekKeyRingId.ValueStringPointer(),
ServiceAccount: model.Encryption.ServiceAccount.ValueStringPointer(),
encryptionPayload = &sqlserverflexalpha.InstanceEncryption{
KekKeyId: model.Encryption.KekKeyId.ValueString(),
KekKeyRingId: model.Encryption.KekKeyVersion.ValueString(),
KekKeyVersion: model.Encryption.KekKeyRingId.ValueString(),
ServiceAccount: model.Encryption.ServiceAccount.ValueString(),
}
}
networkPayload := &sqlserverflexalpha.CreateInstanceRequestPayloadGetNetworkArgType{}
networkPayload := sqlserverflexalpha.CreateInstanceRequestPayloadNetwork{}
if !model.Network.IsNull() && !model.Network.IsUnknown() {
networkPayload.AccessScope = sqlserverflexalpha.CreateInstanceRequestPayloadNetworkGetAccessScopeAttributeType(
model.Network.AccessScope.ValueStringPointer(),
)
networkPayload.AccessScope = (*sqlserverflexalpha.InstanceNetworkAccessScope)(model.Network.AccessScope.ValueStringPointer())
var resList []string
diags := model.Network.Acl.ElementsAs(ctx, &resList, false)
if diags.HasError() {
return nil, fmt.Errorf("error converting network acl list")
}
networkPayload.Acl = &resList
networkPayload.Acl = resList
}
return &sqlserverflexalpha.CreateInstanceRequestPayload{
BackupSchedule: conversion.StringValueToPointer(model.BackupSchedule),
BackupSchedule: model.BackupSchedule.ValueString(),
Encryption: encryptionPayload,
FlavorId: conversion.StringValueToPointer(model.FlavorId),
Name: conversion.StringValueToPointer(model.Name),
FlavorId: model.FlavorId.ValueString(),
Name: model.Name.ValueString(),
Network: networkPayload,
RetentionDays: conversion.Int64ValueToPointer(model.RetentionDays),
RetentionDays: int32(model.RetentionDays.ValueInt64()), //nolint:gosec // TODO
Storage: storagePayload,
Version: sqlserverflexalpha.CreateInstanceRequestPayloadGetVersionAttributeType(
conversion.StringValueToPointer(model.Version),
),
Version: sqlserverflexalpha.InstanceVersion(model.Version.ValueString()),
}, nil
}
@ -269,15 +265,13 @@ func toUpdatePayload(
return nil, fmt.Errorf("error converting model network acl value")
}
return &sqlserverflexalpha.UpdateInstanceRequestPayload{
BackupSchedule: m.BackupSchedule.ValueStringPointer(),
FlavorId: m.FlavorId.ValueStringPointer(),
Name: m.Name.ValueStringPointer(),
Network: sqlserverflexalpha.NewUpdateInstanceRequestPayloadNetwork(netAcl),
Replicas: &replVal,
RetentionDays: m.RetentionDays.ValueInt64Pointer(),
Storage: &sqlserverflexalpha.StorageUpdate{Size: m.Storage.Size.ValueInt64Pointer()},
Version: sqlserverflexalpha.UpdateInstanceRequestPayloadGetVersionAttributeType(
m.Version.ValueStringPointer(),
),
BackupSchedule: m.BackupSchedule.ValueString(),
FlavorId: m.FlavorId.ValueString(),
Name: m.Name.ValueString(),
Network: sqlserverflexalpha.UpdateInstanceRequestPayloadNetwork{Acl: netAcl},
Replicas: replVal,
RetentionDays: int32(m.RetentionDays.ValueInt64()), //nolint:gosec // TODO
Storage: sqlserverflexalpha.StorageUpdate{Size: m.Storage.Size.ValueInt64Pointer()},
Version: sqlserverflexalpha.InstanceVersion(m.Version.ValueString()),
}, nil
}

View file

@ -19,7 +19,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
wait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
@ -179,7 +179,7 @@ func (r *instanceResource) ModifyPlan(
func (r *instanceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data resourceModel
crateErr := "[SQL Server Flex BETA - Create] error"
crateErr := "[SQL Server Flex Alpha - Create] error"
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
@ -207,7 +207,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
return
}
// Create new Instance
createResp, err := r.client.CreateInstanceRequest(
createResp, err := r.client.DefaultAPI.CreateInstanceRequest(
ctx,
projectId,
region,
@ -219,7 +219,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = core.LogResponse(ctx)
InstanceId := *createResp.Id
instanceId := createResp.Id
// Example data value setting
data.InstanceId = types.StringValue("id-from-response")
@ -227,7 +227,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(InstanceId),
InstanceID: types.StringValue(instanceId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -236,9 +236,9 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
waitResp, err := wait.CreateInstanceWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
InstanceId,
instanceId,
region,
).SetSleepBeforeWait(
10 * time.Second,
@ -255,7 +255,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
return
}
if waitResp.Id == nil {
if waitResp.Id == "" {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -309,7 +309,7 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
instanceId := data.InstanceId.ValueString()
ctx = tflog.SetField(ctx, "instance_id", instanceId)
instanceResp, err := r.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := r.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if ok && oapiErr.StatusCode == http.StatusNotFound {
@ -385,7 +385,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
return
}
// Update existing instance
err = r.client.UpdateInstanceRequest(
err = r.client.DefaultAPI.UpdateInstanceRequest(
ctx,
projectId,
region,
@ -399,7 +399,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = core.LogResponse(ctx)
waitResp, err := wait.
UpdateInstanceWaitHandler(ctx, r.client, projectId, instanceId, region).
UpdateInstanceWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region).
SetSleepBeforeWait(15 * time.Second).
SetTimeout(45 * time.Minute).
WaitWithContext(ctx)
@ -471,7 +471,7 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
// Delete existing instance
err := r.client.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
err := r.client.DefaultAPI.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting instance", fmt.Sprintf("Calling API: %v", err))
return
@ -479,7 +479,7 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = core.LogResponse(ctx)
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client, projectId, instanceId, region).WaitWithContext(ctx)
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(
ctx,

View file

@ -4,18 +4,14 @@ import (
"context"
_ "embed"
"fmt"
"log"
"os"
"strconv"
"strings"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils"
sqlserverflexalphaPkgGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalpha "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
// The fwresource import alias is so there is no collision
@ -28,44 +24,6 @@ const providerPrefix = "stackitprivatepreview_sqlserverflexalpha"
var testInstances []string
func init() {
sweeperName := fmt.Sprintf("%s_%s", providerPrefix, "sweeper")
resource.AddTestSweepers(sweeperName, &resource.Sweeper{
Name: sweeperName,
F: func(region string) error {
ctx := context.Background()
apiClientConfigOptions := []config.ConfigurationOption{}
apiClient, err := sqlserverflexalphaPkgGen.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instances, err := apiClient.ListInstancesRequest(ctx, testutils.ProjectId, region).
Size(100).
Execute()
if err != nil {
log.Fatalln(err)
}
for _, inst := range instances.GetInstances() {
if strings.HasPrefix(inst.GetName(), "tf-acc-") {
for _, item := range testInstances {
if inst.GetName() == item {
delErr := apiClient.DeleteInstanceRequestExecute(ctx, testutils.ProjectId, region, inst.GetId())
if delErr != nil {
// TODO: maybe just warn?
log.Fatalln(delErr)
}
}
}
}
}
return nil
},
})
}
func TestInstanceResourceSchema(t *testing.T) {
t.Parallel()
@ -103,20 +61,20 @@ func testAccPreCheck(t *testing.T) {
type resData struct {
ServiceAccountFilePath string
ProjectId string
ProjectID string
Region string
Name string
TfName string
FlavorId string
FlavorID string
BackupSchedule string
UseEncryption bool
KekKeyId string
KekKeyRingId string
KekKeyID string
KekKeyRingID string
KekKeyVersion uint8
KekServiceAccount string
PerformanceClass string
Size uint32
AclString string
ACLString string
AccessScope string
RetentionDays uint32
Version string
@ -126,13 +84,13 @@ type resData struct {
type User struct {
Name string
ProjectId string
ProjectID string
Roles []string
}
type Database struct {
Name string
ProjectId string
ProjectID string
Owner string
Collation string
Compatibility string
@ -147,16 +105,16 @@ func getExample() resData {
return resData{
Region: os.Getenv("TF_ACC_REGION"),
ServiceAccountFilePath: os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Name: name,
TfName: name,
FlavorId: "4.16-Single",
FlavorID: "4.16-Single",
BackupSchedule: "0 0 * * *",
UseEncryption: false,
RetentionDays: 33,
PerformanceClass: "premium-perf2-stackit",
Size: 10,
AclString: "0.0.0.0/0",
ACLString: "0.0.0.0/0",
AccessScope: "PUBLIC",
Version: "2022",
}
@ -236,21 +194,21 @@ func TestAccInstanceNoEncryption(t *testing.T) {
data.Users = []User{
{
Name: userName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{
"##STACKIT_DatabaseManager##",
"##STACKIT_LoginManager##",
"##STACKIT_ProcessManager##",
"##STACKIT_SQLAgentManager##",
"##STACKIT_SQLAgentUser##",
"##STACKIT_ServerManager##",
//"##STACKIT_ProcessManager##",
//"##STACKIT_SQLAgentManager##",
//"##STACKIT_SQLAgentUser##",
//"##STACKIT_ServerManager##",
},
},
}
data.Databases = []Database{
{
Name: dbName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
@ -340,23 +298,28 @@ func TestAccInstanceEncryption(t *testing.T) {
data.Users = []User{
{
Name: userName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"##STACKIT_DatabaseManager##", "##STACKIT_LoginManager##"},
},
}
data.Databases = []Database{
{
Name: dbName,
ProjectId: os.Getenv("TF_ACC_PROJECT_ID"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
data.UseEncryption = true
data.KekKeyId = "fe039bcf-8d7b-431a-801d-9e81371a6b7b"
data.KekKeyRingId = "6a2d95ab-3c4c-4963-a2bb-08d17a320e27"
data.KekKeyVersion = 1
data.KekServiceAccount = "henselinm-u2v3ex1@sa.stackit.cloud"
data.KekKeyID = os.Getenv("TF_ACC_KEK_KEY_ID")
data.KekKeyRingID = os.Getenv("TF_ACC_KEK_KEY_RING_ID")
verString := os.Getenv("TF_ACC_KEK_KEY_VERSION")
version, err := strconv.ParseInt(verString, 0, 32)
if err != nil {
t.Errorf("error coverting value to uint8: %+v", verString)
}
data.KekKeyVersion = uint8(version) //nolint:gosec // not important its a test
data.KekServiceAccount = os.Getenv("TF_ACC_KEK_SERVICE_ACCOUNT")
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {

View file

@ -4,25 +4,25 @@ provider "stackitprivatepreview" {
}
resource "stackitprivatepreview_sqlserverflexalpha_instance" "{{ .TfName }}" {
project_id = "{{ .ProjectId }}"
project_id = "{{ .ProjectID }}"
name = "{{ .Name }}"
backup_schedule = "{{ .BackupSchedule }}"
retention_days = {{ .RetentionDays }}
flavor_id = "{{ .FlavorId }}"
flavor_id = "{{ .FlavorID }}"
storage = {
class = "{{ .PerformanceClass }}"
size = {{ .Size }}
}
{{ if .UseEncryption }}
encryption = {
kek_key_id = "{{ .KekKeyId }}"
kek_key_ring_id = "{{ .KekKeyRingId }}"
kek_key_id = "{{ .KekKeyID }}"
kek_key_ring_id = "{{ .KekKeyRingID }}"
kek_key_version = {{ .KekKeyVersion }}
service_account = "{{ .KekServiceAccount }}"
}
{{ end }}
network = {
acl = ["{{ .AclString }}"]
acl = ["{{ .ACLString }}"]
access_scope = "{{ .AccessScope }}"
}
version = "{{ .Version }}"
@ -32,7 +32,7 @@ resource "stackitprivatepreview_sqlserverflexalpha_instance" "{{ .TfName }}" {
{{ $tfName := .TfName }}
{{ range $user := .Users }}
resource "stackitprivatepreview_sqlserverflexalpha_user" "{{ $user.Name }}" {
project_id = "{{ $user.ProjectId }}"
project_id = "{{ $user.ProjectID }}"
instance_id = stackitprivatepreview_sqlserverflexalpha_instance.{{ $tfName }}.instance_id
username = "{{ $user.Name }}"
roles = [{{ range $i, $v := $user.Roles }}{{if $i}},{{end}}"{{$v}}"{{end}}]
@ -45,7 +45,7 @@ resource "stackitprivatepreview_sqlserverflexalpha_user" "{{ $user.Name }}" {
{{ range $db := .Databases }}
resource "stackitprivatepreview_sqlserverflexalpha_database" "{{ $db.Name }}" {
depends_on = [stackitprivatepreview_sqlserverflexalpha_user.{{ $db.Owner }}]
project_id = "{{ $db.ProjectId }}"
project_id = "{{ $db.ProjectID }}"
instance_id = stackitprivatepreview_sqlserverflexalpha_instance.{{ $tfName }}.instance_id
name = "{{ $db.Name }}"
owner = "{{ $db.Owner }}"

View file

@ -14,7 +14,8 @@ import (
sqlserverflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalphaPkg "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user/datasources_gen"
)
@ -94,7 +95,7 @@ func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
ctx = tflog.SetField(ctx, "user_id", userId)
ctx = tflog.SetField(ctx, "region", region)
recordSetResp, err := d.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
recordSetResp, err := d.client.DefaultAPI.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
utils.LogError(
ctx,
@ -135,5 +136,5 @@ func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "SQLServer Flex beta instance read")
tflog.Info(ctx, "SQLServer Flex Alpha instance read")
}

View file

@ -8,14 +8,14 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
// mapDataSourceFields maps the API response to a dataSourceModel.
func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *dataSourceModel, region string) error {
func mapDataSourceFields(userResp *v3alpha1api.GetUserResponse, model *dataSourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -28,8 +28,8 @@ func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *da
var userId int64
if model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
} else if user.Id != 0 {
userId = user.Id
} else {
return fmt.Errorf("user id not present")
}
@ -39,13 +39,13 @@ func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *da
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
model.Username = types.StringValue(user.Username)
// Map roles
if user.Roles == nil {
model.Roles = types.List(types.SetNull(types.StringType))
} else {
resRoles := *user.Roles
resRoles := user.Roles
slices.Sort(resRoles)
var roles []attr.Value
@ -60,17 +60,17 @@ func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *da
}
// Set remaining attributes
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
model.Status = types.StringPointerValue(user.Status)
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
model.Status = types.StringValue(user.Status)
model.DefaultDatabase = types.StringValue(user.DefaultDatabase)
return nil
}
// mapFields maps the API response to a resourceModel.
func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceModel, region string) error {
func mapFields(userResp *v3alpha1api.GetUserResponse, model *resourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -80,23 +80,23 @@ func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceMode
user := userResp
// Handle user ID
var userId int64
var userID int64
if model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
userID = model.UserId.ValueInt64()
} else if user.Id != 0 {
userID = user.Id
} else {
return fmt.Errorf("user id not present")
}
// Set main attributes
model.Id = types.Int64Value(userId)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
model.Id = types.Int64Value(userID)
model.UserId = types.Int64Value(userID)
model.Username = types.StringValue(user.Username)
// Map roles
if user.Roles != nil {
resRoles := *user.Roles
resRoles := user.Roles
slices.Sort(resRoles)
var roles []attr.Value
@ -116,14 +116,14 @@ func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceMode
}
// Set connection details
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
return nil
}
// mapFieldsCreate maps the API response from creating a user to a resourceModel.
func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *resourceModel, region string) error {
func mapFieldsCreate(userResp *v3alpha1api.CreateUserResponse, model *resourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -132,21 +132,21 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res
}
user := userResp
if user.Id == nil {
if user.Id == 0 {
return fmt.Errorf("user id not present")
}
userId := *user.Id
model.Id = types.Int64Value(userId)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
userID := user.Id
model.Id = types.Int64Value(userID)
model.UserId = types.Int64Value(userID)
model.Username = types.StringValue(user.Username)
if user.Password == nil {
if user.Password == "" {
return fmt.Errorf("user password not present")
}
model.Password = types.StringValue(*user.Password)
model.Password = types.StringValue(user.Password)
if user.Roles != nil {
resRoles := *user.Roles
if len(user.Roles) > 0 {
resRoles := user.Roles
slices.Sort(resRoles)
var roles []attr.Value
@ -164,14 +164,14 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res
model.Roles = types.List(types.SetNull(types.StringType))
}
model.Password = types.StringPointerValue(user.Password)
model.Uri = types.StringPointerValue(user.Uri)
model.Password = types.StringValue(user.Password)
model.Uri = types.StringValue(user.Uri)
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
model.Status = types.StringPointerValue(user.Status)
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
model.Status = types.StringValue(user.Status)
model.DefaultDatabase = types.StringValue(user.DefaultDatabase)
return nil
}
@ -180,14 +180,18 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res
func toCreatePayload(
model *resourceModel,
roles []string,
) (*sqlserverflexalpha.CreateUserRequestPayload, error) {
) (*v3alpha1api.CreateUserRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
return &sqlserverflexalpha.CreateUserRequestPayload{
Username: conversion.StringValueToPointer(model.Username),
DefaultDatabase: conversion.StringValueToPointer(model.DefaultDatabase),
Roles: &roles,
}, nil
res := v3alpha1api.CreateUserRequestPayload{
Username: model.Username.ValueString(),
DefaultDatabase: nil,
Roles: roles,
}
if !model.DefaultDatabase.IsUnknown() && !model.DefaultDatabase.IsNull() {
res.DefaultDatabase = model.DefaultDatabase.ValueStringPointer()
}
return &res, nil
}

View file

@ -6,43 +6,42 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
func TestMapDataSourceFields(t *testing.T) {
const testRegion = "region"
tests := []struct {
description string
input *sqlserverflexalpha.GetUserResponse
input *v3alpha1api.GetUserResponse
region string
expected dataSourceModel
isValid bool
}{
{
"default_values",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
dataSourceModel{
Id: types.StringValue("pid,region,iid,1"),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Host: types.StringNull(),
Port: types.Int64Null(),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
DefaultDatabase: types.StringNull(),
Status: types.StringValue(""),
DefaultDatabase: types.StringValue(""),
},
true,
},
{
"simple_values",
&sqlserverflexalpha.GetUserResponse{
Roles: &[]string{
&v3alpha1api.GetUserResponse{
Roles: []string{
"##STACKIT_SQLAgentUser##",
"##STACKIT_DatabaseManager##",
"##STACKIT_LoginManager##",
@ -50,11 +49,11 @@ func TestMapDataSourceFields(t *testing.T) {
"##STACKIT_ProcessManager##",
"##STACKIT_ServerManager##",
},
Username: utils.Ptr("username"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Status: utils.Ptr("active"),
DefaultDatabase: utils.Ptr("default_db"),
Username: "username",
Host: "host",
Port: int32(1234),
Status: "active",
DefaultDatabase: "default_db",
},
testRegion,
dataSourceModel{
@ -85,24 +84,26 @@ func TestMapDataSourceFields(t *testing.T) {
},
{
"null_fields_and_int_conversions",
&sqlserverflexalpha.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]string{},
Username: nil,
Host: nil,
Port: utils.Ptr(int64(2123456789)),
&v3alpha1api.GetUserResponse{
Id: int64(1),
Roles: []string{},
Username: "",
Host: "",
Port: int32(2123456789),
},
testRegion,
dataSourceModel{
Id: types.StringValue("pid,region,iid,1"),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringNull(),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
Id: types.StringValue("pid,region,iid,1"),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringValue(""),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringValue(""),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
},
true,
},
@ -115,14 +116,14 @@ func TestMapDataSourceFields(t *testing.T) {
},
{
"nil_response_2",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
dataSourceModel{},
false,
},
{
"no_resource_id",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
dataSourceModel{},
false,
@ -158,47 +159,51 @@ func TestMapFieldsCreate(t *testing.T) {
const testRegion = "region"
tests := []struct {
description string
input *sqlserverflexalpha.CreateUserResponse
input *v3alpha1api.CreateUserResponse
region string
expected resourceModel
isValid bool
}{
{
"default_values",
&sqlserverflexalpha.CreateUserResponse{
Id: utils.Ptr(int64(1)),
Password: utils.Ptr(""),
&v3alpha1api.CreateUserResponse{
Id: int64(1),
Password: "xy",
},
testRegion,
resourceModel{
Id: types.Int64Value(1),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringValue(""),
Host: types.StringNull(),
Port: types.Int64Null(),
Region: types.StringValue(testRegion),
Id: types.Int64Value(1),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringValue("xy"),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
Uri: types.StringValue(""),
},
true,
},
{
"simple_values",
&sqlserverflexalpha.CreateUserResponse{
Id: utils.Ptr(int64(2)),
Roles: &[]string{
&v3alpha1api.CreateUserResponse{
Id: int64(2),
Roles: []string{
"role_2",
"role_1",
"",
},
Username: utils.Ptr("username"),
Password: utils.Ptr("password"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Status: utils.Ptr("status"),
DefaultDatabase: utils.Ptr("default_db"),
Username: "username",
Password: "password",
Host: "host",
Port: int32(1234),
Status: "status",
DefaultDatabase: "default_db",
Uri: "myURI",
},
testRegion,
resourceModel{
@ -222,18 +227,19 @@ func TestMapFieldsCreate(t *testing.T) {
Region: types.StringValue(testRegion),
Status: types.StringValue("status"),
DefaultDatabase: types.StringValue("default_db"),
Uri: types.StringValue("myURI"),
},
true,
},
{
"null_fields_and_int_conversions",
&sqlserverflexalpha.CreateUserResponse{
Id: utils.Ptr(int64(3)),
Roles: &[]string{},
Username: nil,
Password: utils.Ptr(""),
Host: nil,
Port: utils.Ptr(int64(2123456789)),
&v3alpha1api.CreateUserResponse{
Id: int64(3),
Roles: []string{},
Username: "",
Password: "xy",
Host: "",
Port: int32(256789),
},
testRegion,
resourceModel{
@ -241,14 +247,15 @@ func TestMapFieldsCreate(t *testing.T) {
UserId: types.Int64Value(3),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Password: types.StringValue(""),
Host: types.StringNull(),
Port: types.Int64Value(2123456789),
Username: types.StringValue(""),
Roles: types.ListNull(types.StringType),
Password: types.StringValue("xy"),
Host: types.StringValue(""),
Port: types.Int64Value(256789),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringNull(),
Status: types.StringNull(),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
Uri: types.StringValue(""),
},
true,
},
@ -261,22 +268,22 @@ func TestMapFieldsCreate(t *testing.T) {
},
{
"nil_response_2",
&sqlserverflexalpha.CreateUserResponse{},
&v3alpha1api.CreateUserResponse{},
testRegion,
resourceModel{},
false,
},
{
"no_resource_id",
&sqlserverflexalpha.CreateUserResponse{},
&v3alpha1api.CreateUserResponse{},
testRegion,
resourceModel{},
false,
},
{
"no_password",
&sqlserverflexalpha.CreateUserResponse{
Id: utils.Ptr(int64(1)),
&v3alpha1api.CreateUserResponse{
Id: int64(1),
},
testRegion,
resourceModel{},
@ -312,39 +319,39 @@ func TestMapFields(t *testing.T) {
const testRegion = "region"
tests := []struct {
description string
input *sqlserverflexalpha.GetUserResponse
input *v3alpha1api.GetUserResponse
region string
expected resourceModel
isValid bool
}{
{
"default_values",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
resourceModel{
Id: types.Int64Value(1),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Host: types.StringNull(),
Port: types.Int64Null(),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
},
true,
},
{
"simple_values",
&sqlserverflexalpha.GetUserResponse{
Roles: &[]string{
&v3alpha1api.GetUserResponse{
Roles: []string{
"role_2",
"role_1",
"",
},
Username: utils.Ptr("username"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Username: ("username"),
Host: ("host"),
Port: (int32(1234)),
},
testRegion,
resourceModel{
@ -370,12 +377,12 @@ func TestMapFields(t *testing.T) {
},
{
"null_fields_and_int_conversions",
&sqlserverflexalpha.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]string{},
Username: nil,
Host: nil,
Port: utils.Ptr(int64(2123456789)),
&v3alpha1api.GetUserResponse{
Id: int64(1),
Roles: []string{},
Username: "",
Host: "",
Port: int32(2123456789),
},
testRegion,
resourceModel{
@ -383,9 +390,9 @@ func TestMapFields(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringNull(),
Host: types.StringValue(""),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
},
@ -400,14 +407,14 @@ func TestMapFields(t *testing.T) {
},
{
"nil_response_2",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
resourceModel{},
false,
},
{
"no_resource_id",
&sqlserverflexalpha.GetUserResponse{},
&v3alpha1api.GetUserResponse{},
testRegion,
resourceModel{},
false,
@ -444,16 +451,16 @@ func TestToCreatePayload(t *testing.T) {
description string
input *resourceModel
inputRoles []string
expected *sqlserverflexalpha.CreateUserRequestPayload
expected *v3alpha1api.CreateUserRequestPayload
isValid bool
}{
{
"default_values",
&resourceModel{},
[]string{},
&sqlserverflexalpha.CreateUserRequestPayload{
Roles: &[]string{},
Username: nil,
&v3alpha1api.CreateUserRequestPayload{
Roles: []string{},
Username: "",
},
true,
},
@ -466,28 +473,28 @@ func TestToCreatePayload(t *testing.T) {
"role_1",
"role_2",
},
&sqlserverflexalpha.CreateUserRequestPayload{
Roles: &[]string{
&v3alpha1api.CreateUserRequestPayload{
Roles: []string{
"role_1",
"role_2",
},
Username: utils.Ptr("username"),
Username: "username",
},
true,
},
{
"null_fields_and_int_conversions",
&resourceModel{
Username: types.StringNull(),
Username: types.StringValue(""),
},
[]string{
"",
},
&sqlserverflexalpha.CreateUserRequestPayload{
Roles: &[]string{
&v3alpha1api.CreateUserRequestPayload{
Roles: []string{
"",
},
Username: nil,
Username: "",
},
true,
},
@ -504,9 +511,9 @@ func TestToCreatePayload(t *testing.T) {
Username: types.StringValue("username"),
},
[]string{},
&sqlserverflexalpha.CreateUserRequestPayload{
Roles: &[]string{},
Username: utils.Ptr("username"),
&v3alpha1api.CreateUserRequestPayload{
Roles: []string{},
Username: "username",
},
true,
},

View file

@ -18,7 +18,8 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflexalpha "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
sqlserverflexalphaUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/utils"
sqlserverflexalphaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexalpha"
@ -75,7 +76,7 @@ func (r *userResource) Configure(ctx context.Context, req resource.ConfigureRequ
return
}
r.client = apiClient
tflog.Info(ctx, "SQLServer Beta Flex user client configured")
tflog.Info(ctx, "SQLServer Alpha Flex user client configured")
}
// ModifyPlan implements resource.ResourceWithModifyPlan.
@ -205,12 +206,12 @@ func (r *userResource) Create(
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
projectID := model.ProjectId.ValueString()
instanceID := model.InstanceId.ValueString()
region := model.Region.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
ctx = tflog.SetField(ctx, "project_id", projectID)
ctx = tflog.SetField(ctx, "instance_id", instanceID)
ctx = tflog.SetField(ctx, "region", region)
var roles []string
@ -231,11 +232,11 @@ func (r *userResource) Create(
return
}
// Create new user
userResp, err := r.client.CreateUserRequest(
userResp, err := r.client.DefaultAPI.CreateUserRequest(
ctx,
projectId,
projectID,
region,
instanceId,
instanceID,
).CreateUserRequestPayload(*payload).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err))
@ -244,7 +245,7 @@ func (r *userResource) Create(
ctx = core.LogResponse(ctx)
if userResp == nil || userResp.Id == nil || *userResp.Id == 0 {
if userResp == nil || userResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -254,14 +255,14 @@ func (r *userResource) Create(
return
}
userId := *userResp.Id
userId := userResp.Id
ctx = tflog.SetField(ctx, "user_id", userId)
// Set data returned by API in identity
identity := UserResourceIdentityModel{
ProjectID: types.StringValue(projectId),
ProjectID: types.StringValue(projectID),
Region: types.StringValue(region),
InstanceID: types.StringValue(instanceId),
InstanceID: types.StringValue(instanceID),
UserID: types.Int64Value(userId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
@ -282,9 +283,9 @@ func (r *userResource) Create(
waitResp, err := sqlserverflexalphaWait.CreateUserWaitHandler(
ctx,
r.client,
projectId,
instanceId,
r.client.DefaultAPI,
projectID,
instanceID,
region,
userId,
).SetSleepBeforeWait(
@ -303,7 +304,7 @@ func (r *userResource) Create(
return
}
if waitResp.Id == nil {
if waitResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -357,7 +358,7 @@ func (r *userResource) Read(
ctx = tflog.SetField(ctx, "user_id", userId)
ctx = tflog.SetField(ctx, "region", region)
recordSetResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
recordSetResp, err := r.client.DefaultAPI.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(
@ -445,7 +446,7 @@ func (r *userResource) Delete(
// Delete existing record set
// err := r.client.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
err := r.client.DeleteUserRequestExecute(ctx, projectId, region, instanceId, userId)
err := r.client.DefaultAPI.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -467,7 +468,7 @@ func (r *userResource) Delete(
}
}
// Delete existing record set
_, err = sqlserverflexalphaWait.DeleteUserWaitHandler(ctx, r.client, projectId, region, instanceId, userId).
_, err = sqlserverflexalphaWait.DeleteUserWaitHandler(ctx, r.client.DefaultAPI, projectId, region, instanceId, userId).
WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("Calling API: %v", err))

View file

@ -4,7 +4,7 @@ import (
"context"
"fmt"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/stackitcloud/stackit-sdk-go/core/config"

View file

@ -10,7 +10,7 @@ import (
sdkClients "github.com/stackitcloud/stackit-sdk-go/core/clients"
"github.com/stackitcloud/stackit-sdk-go/core/config"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"

View file

@ -16,7 +16,8 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbetaPkg "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database/datasources_gen"
)
@ -119,7 +120,7 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
databaseName := data.DatabaseName.ValueString()
databaseResp, err := d.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
databaseResp, err := d.client.DefaultAPI.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
handleReadError(ctx, &resp.Diagnostics, err, projectId, instanceId)
resp.State.RemoveResource(ctx)

View file

@ -4,8 +4,10 @@ import (
"fmt"
"github.com/hashicorp/terraform-plugin-framework/types"
utils2 "github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexbeta "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
@ -14,7 +16,7 @@ func mapFields(source *sqlserverflexbeta.GetDatabaseResponse, model *dataSourceM
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -24,8 +26,8 @@ func mapFields(source *sqlserverflexbeta.GetDatabaseResponse, model *dataSourceM
var databaseId int64
if model.Id.ValueInt64() != 0 {
databaseId = model.Id.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = source.Id
} else {
return fmt.Errorf("database id not present")
}
@ -37,7 +39,7 @@ func mapFields(source *sqlserverflexbeta.GetDatabaseResponse, model *dataSourceM
model.Region = types.StringValue(region)
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
model.CompatibilityLevel = types.Int64Value(source.GetCompatibilityLevel())
model.CompatibilityLevel = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.CollationName = types.StringValue(source.GetCollationName())
model.TerraformId = utils.BuildInternalTerraformId(
@ -55,7 +57,7 @@ func mapResourceFields(source *sqlserverflexbeta.GetDatabaseResponse, model *res
if source == nil {
return fmt.Errorf("response is nil")
}
if source.Id == nil || *source.Id == 0 {
if source.Id == 0 {
return fmt.Errorf("id not present")
}
if model == nil {
@ -65,8 +67,8 @@ func mapResourceFields(source *sqlserverflexbeta.GetDatabaseResponse, model *res
var databaseId int64
if model.Id.ValueInt64() != 0 {
databaseId = model.Id.ValueInt64()
} else if source.Id != nil {
databaseId = *source.Id
} else if source.Id != 0 {
databaseId = source.Id
} else {
return fmt.Errorf("database id not present")
}
@ -79,8 +81,8 @@ func mapResourceFields(source *sqlserverflexbeta.GetDatabaseResponse, model *res
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
model.Compatibility = types.Int64Value(source.GetCompatibilityLevel())
model.CompatibilityLevel = types.Int64Value(source.GetCompatibilityLevel())
model.Compatibility = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.CompatibilityLevel = types.Int64Value(int64(source.GetCompatibilityLevel()))
model.Collation = types.StringValue(source.GetCollationName()) // it does not come back from api
model.CollationName = types.StringValue(source.GetCollationName())
@ -95,9 +97,9 @@ func toCreatePayload(model *resourceModel) (*sqlserverflexbeta.CreateDatabaseReq
}
return &sqlserverflexbeta.CreateDatabaseRequestPayload{
Name: model.Name.ValueStringPointer(),
Owner: model.Owner.ValueStringPointer(),
Name: model.Name.ValueString(),
Owner: model.Owner.ValueString(),
Collation: model.Collation.ValueStringPointer(),
Compatibility: model.Compatibility.ValueInt64Pointer(),
Compatibility: utils2.Ptr(int32(model.Compatibility.ValueInt64())), //nolint:gosec // TODO
}, nil
}

View file

@ -6,14 +6,14 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
datasource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database/datasources_gen"
)
func TestMapFields(t *testing.T) {
type given struct {
source *sqlserverflexbeta.GetDatabaseResponse
source *v3beta1api.GetDatabaseResponse
model *dataSourceModel
region string
}
@ -30,12 +30,12 @@ func TestMapFields(t *testing.T) {
{
name: "should map fields correctly",
given: given{
source: &sqlserverflexbeta.GetDatabaseResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
CollationName: utils.Ptr("collation"),
CompatibilityLevel: utils.Ptr(int64(150)),
Owner: utils.Ptr("my-owner"),
source: &v3beta1api.GetDatabaseResponse{
Id: int64(1),
Name: "my-db",
CollationName: "collation",
CompatibilityLevel: int32(150),
Owner: "my-owner",
},
model: &dataSourceModel{
DatabaseModel: datasource.DatabaseModel{
@ -73,7 +73,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil source ID",
given: given{
source: &sqlserverflexbeta.GetDatabaseResponse{Id: nil},
source: &v3beta1api.GetDatabaseResponse{Id: 0},
model: &dataSourceModel{},
},
expected: expected{err: true},
@ -81,7 +81,7 @@ func TestMapFields(t *testing.T) {
{
name: "should fail on nil model",
given: given{
source: &sqlserverflexbeta.GetDatabaseResponse{Id: utils.Ptr(int64(1))},
source: &v3beta1api.GetDatabaseResponse{Id: int64(1)},
model: nil,
},
expected: expected{err: true},
@ -107,7 +107,7 @@ func TestMapFields(t *testing.T) {
func TestMapResourceFields(t *testing.T) {
type given struct {
source *sqlserverflexbeta.GetDatabaseResponse
source *v3beta1api.GetDatabaseResponse
model *resourceModel
region string
}
@ -124,10 +124,10 @@ func TestMapResourceFields(t *testing.T) {
{
name: "should map fields correctly",
given: given{
source: &sqlserverflexbeta.GetDatabaseResponse{
Id: utils.Ptr(int64(1)),
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("my-owner"),
source: &v3beta1api.GetDatabaseResponse{
Id: (int64(1)),
Name: ("my-db"),
Owner: ("my-owner"),
},
model: &resourceModel{
ProjectId: types.StringValue("my-project"),
@ -183,7 +183,7 @@ func TestToCreatePayload(t *testing.T) {
model *resourceModel
}
type expected struct {
payload *sqlserverflexbeta.CreateDatabaseRequestPayload
payload *v3beta1api.CreateDatabaseRequestPayload
err bool
}
@ -201,9 +201,10 @@ func TestToCreatePayload(t *testing.T) {
},
},
expected: expected{
payload: &sqlserverflexbeta.CreateDatabaseRequestPayload{
Name: utils.Ptr("my-db"),
Owner: utils.Ptr("my-owner"),
payload: &v3beta1api.CreateDatabaseRequestPayload{
Name: "my-db",
Owner: "my-owner",
Compatibility: utils.Ptr(int32(0)),
},
},
},

View file

@ -16,8 +16,10 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
utils2 "github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexbeta "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
wait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexbeta"
@ -176,15 +178,15 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
}
if !data.Compatibility.IsNull() && !data.Compatibility.IsUnknown() {
payLoad.Compatibility = data.Compatibility.ValueInt64Pointer()
payLoad.Compatibility = utils2.Ptr(int32(data.Compatibility.ValueInt64())) //nolint:gosec // TODO
}
payLoad.Name = data.Name.ValueStringPointer()
payLoad.Owner = data.Owner.ValueStringPointer()
payLoad.Name = data.Name.ValueString()
payLoad.Owner = data.Owner.ValueString()
_, err := wait.WaitForUserWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
instanceId,
region,
@ -202,7 +204,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
createResp, err := r.client.CreateDatabaseRequest(ctx, projectId, region, instanceId).
createResp, err := r.client.DefaultAPI.CreateDatabaseRequest(ctx, projectId, region, instanceId).
CreateDatabaseRequestPayload(payLoad).
Execute()
if err != nil {
@ -215,7 +217,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if createResp == nil || createResp.Id == nil {
if createResp == nil || createResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -225,7 +227,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
databaseId := *createResp.Id
databaseId := createResp.Id
ctx = tflog.SetField(ctx, "database_id", databaseId)
@ -245,7 +247,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
waitResp, err := wait.CreateDatabaseWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
instanceId,
region,
@ -265,7 +267,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if waitResp.Id == nil {
if waitResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -275,7 +277,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Id != databaseId {
if waitResp.Id != databaseId {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -285,7 +287,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Owner != data.Owner.ValueString() {
if waitResp.Owner != data.Owner.ValueString() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -295,7 +297,7 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
return
}
if *waitResp.Name != data.Name.ValueString() {
if waitResp.Name != data.Name.ValueString() {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -348,7 +350,7 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "database_name", databaseName)
databaseResp, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
databaseResp, err := r.client.DefaultAPI.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if (ok && oapiErr.StatusCode == http.StatusNotFound) || errors.Is(err, errDatabaseNotFound) {
@ -419,7 +421,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = tflog.SetField(ctx, "database_name", databaseName)
// Delete existing record set
err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
err := r.client.DefaultAPI.DeleteDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
core.LogAndAddError(
ctx,
@ -555,5 +557,3 @@ func (r *databaseResource) ImportState(
tflog.Info(ctx, "Sqlserverflexbeta database state imported")
}
// extractIdentityData extracts essential identifiers from the resource model, falling back to the identity mode

View file

@ -16,7 +16,8 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavor/datasources_gen"
)
@ -48,7 +49,7 @@ func NewFlavorDataSource() datasource.DataSource {
// flavorDataSource is the data source implementation.
type flavorDataSource struct {
client *sqlserverflexbetaPkg.APIClient
client *v3beta1api.APIClient
providerData core.ProviderData
}
@ -80,7 +81,7 @@ func (r *flavorDataSource) Configure(ctx context.Context, req datasource.Configu
config.WithRegion(r.providerData.GetRegion()),
)
}
apiClient, err := sqlserverflexbetaPkg.NewAPIClient(apiClientConfigOptions...)
apiClient, err := v3beta1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
@ -273,25 +274,25 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
flavors, err := getAllFlavors(ctx, r.client, projectId, region)
flavors, err := getAllFlavors(ctx, r.client.DefaultAPI, projectId, region)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
return
}
var foundFlavors []sqlserverflexbetaPkg.ListFlavors
var foundFlavors []v3beta1api.ListFlavors
for _, flavor := range flavors {
if model.Cpu.ValueInt64() != *flavor.Cpu {
if model.Cpu.ValueInt64() != flavor.Cpu {
continue
}
if model.Memory.ValueInt64() != *flavor.Memory {
if model.Memory.ValueInt64() != flavor.Memory {
continue
}
if model.NodeType.ValueString() != *flavor.NodeType {
if model.NodeType.ValueString() != flavor.NodeType {
continue
}
for _, sc := range *flavor.StorageClasses {
if model.StorageClass.ValueString() != *sc.Class {
for _, sc := range flavor.StorageClasses {
if model.StorageClass.ValueString() != sc.Class {
continue
}
foundFlavors = append(foundFlavors, flavor)
@ -307,11 +308,11 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
}
f := foundFlavors[0]
model.Description = types.StringValue(*f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, *f.Id)
model.FlavorId = types.StringValue(*f.Id)
model.MaxGb = types.Int64Value(*f.MaxGB)
model.MinGb = types.Int64Value(*f.MinGB)
model.Description = types.StringValue(f.Description)
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, f.Id)
model.FlavorId = types.StringValue(f.Id)
model.MaxGb = types.Int64Value(int64(f.MaxGB))
model.MinGb = types.Int64Value(int64(f.MinGB))
if f.StorageClasses == nil {
model.StorageClasses = types.ListNull(sqlserverflexbetaGen.StorageClassesType{
@ -321,15 +322,15 @@ func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest,
})
} else {
var scList []attr.Value
for _, sc := range *f.StorageClasses {
for _, sc := range f.StorageClasses {
scList = append(
scList,
sqlserverflexbetaGen.NewStorageClassesValueMust(
sqlserverflexbetaGen.StorageClassesValue{}.AttributeTypes(ctx),
map[string]attr.Value{
"class": types.StringValue(*sc.Class),
"max_io_per_sec": types.Int64Value(*sc.MaxIoPerSec),
"max_through_in_mb": types.Int64Value(*sc.MaxThroughInMb),
"class": types.StringValue(sc.Class),
"max_io_per_sec": types.Int64Value(int64(sc.MaxIoPerSec)),
"max_through_in_mb": types.Int64Value(int64(sc.MaxThroughInMb)),
},
),
)

View file

@ -4,21 +4,21 @@ import (
"context"
"fmt"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
type flavorsClientReader interface {
GetFlavorsRequest(
ctx context.Context,
projectId, region string,
) sqlserverflexbeta.ApiGetFlavorsRequestRequest
) v3beta1api.ApiGetFlavorsRequestRequest
}
func getAllFlavors(ctx context.Context, client flavorsClientReader, projectId, region string) (
[]sqlserverflexbeta.ListFlavors,
[]v3beta1api.ListFlavors,
error,
) {
getAllFilter := func(_ sqlserverflexbeta.ListFlavors) bool { return true }
getAllFilter := func(_ v3beta1api.ListFlavors) bool { return true }
flavorList, err := getFlavorsByFilter(ctx, client, projectId, region, getAllFilter)
if err != nil {
return nil, err
@ -32,29 +32,29 @@ func getFlavorsByFilter(
ctx context.Context,
client flavorsClientReader,
projectId, region string,
filter func(db sqlserverflexbeta.ListFlavors) bool,
) ([]sqlserverflexbeta.ListFlavors, error) {
filter func(db v3beta1api.ListFlavors) bool,
) ([]v3beta1api.ListFlavors, error) {
if projectId == "" || region == "" {
return nil, fmt.Errorf("listing sqlserverflexbeta flavors: projectId and region are required")
return nil, fmt.Errorf("listing v3beta1api flavors: projectId and region are required")
}
const pageSize = 25
var result = make([]sqlserverflexbeta.ListFlavors, 0)
var result = make([]v3beta1api.ListFlavors, 0)
for page := int64(1); ; page++ {
res, err := client.GetFlavorsRequest(ctx, projectId, region).
Page(page).Size(pageSize).Sort(sqlserverflexbeta.FLAVORSORT_INDEX_ASC).Execute()
Page(page).Size(pageSize).Sort(v3beta1api.FLAVORSORT_INDEX_ASC).Execute()
if err != nil {
return nil, fmt.Errorf("requesting flavors list (page %d): %w", page, err)
}
// If the API returns no flavors, we have reached the end of the list.
if res.Flavors == nil || len(*res.Flavors) == 0 {
if len(res.Flavors) == 0 {
break
}
for _, flavor := range *res.Flavors {
for _, flavor := range res.Flavors {
if filter(flavor) {
result = append(result, flavor)
}

View file

@ -1,135 +1,135 @@
package sqlserverFlexBetaFlavor
import (
"context"
"testing"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
)
type mockRequest struct {
executeFunc func() (*sqlserverflexbeta.GetFlavorsResponse, error)
}
func (m *mockRequest) Page(_ int64) sqlserverflexbeta.ApiGetFlavorsRequestRequest { return m }
func (m *mockRequest) Size(_ int64) sqlserverflexbeta.ApiGetFlavorsRequestRequest { return m }
func (m *mockRequest) Sort(_ sqlserverflexbeta.FlavorSort) sqlserverflexbeta.ApiGetFlavorsRequestRequest {
return m
}
func (m *mockRequest) Execute() (*sqlserverflexbeta.GetFlavorsResponse, error) {
return m.executeFunc()
}
type mockFlavorsClient struct {
executeRequest func() sqlserverflexbeta.ApiGetFlavorsRequestRequest
}
func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) sqlserverflexbeta.ApiGetFlavorsRequestRequest {
return m.executeRequest()
}
var mockResp = func(page int64) (*sqlserverflexbeta.GetFlavorsResponse, error) {
if page == 1 {
return &sqlserverflexbeta.GetFlavorsResponse{
Flavors: &[]sqlserverflexbeta.ListFlavors{
{Id: utils.Ptr("flavor-1"), Description: utils.Ptr("first")},
{Id: utils.Ptr("flavor-2"), Description: utils.Ptr("second")},
},
}, nil
}
if page == 2 {
return &sqlserverflexbeta.GetFlavorsResponse{
Flavors: &[]sqlserverflexbeta.ListFlavors{
{Id: utils.Ptr("flavor-3"), Description: utils.Ptr("three")},
},
}, nil
}
return &sqlserverflexbeta.GetFlavorsResponse{
Flavors: &[]sqlserverflexbeta.ListFlavors{},
}, nil
}
func TestGetFlavorsByFilter(t *testing.T) {
tests := []struct {
description string
projectId string
region string
mockErr error
filter func(sqlserverflexbeta.ListFlavors) bool
wantCount int
wantErr bool
}{
{
description: "Success - Get all flavors (2 pages)",
projectId: "pid", region: "reg",
filter: func(_ sqlserverflexbeta.ListFlavors) bool { return true },
wantCount: 3,
wantErr: false,
},
{
description: "Success - Filter flavors by description",
projectId: "pid", region: "reg",
filter: func(f sqlserverflexbeta.ListFlavors) bool { return *f.Description == "first" },
wantCount: 1,
wantErr: false,
},
{
description: "Error - Missing parameters",
projectId: "", region: "reg",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(
tt.description, func(t *testing.T) {
var currentPage int64
client := &mockFlavorsClient{
executeRequest: func() sqlserverflexbeta.ApiGetFlavorsRequestRequest {
return &mockRequest{
executeFunc: func() (*sqlserverflexbeta.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
},
}
},
}
actual, err := getFlavorsByFilter(context.Background(), client, tt.projectId, tt.region, tt.filter)
if (err != nil) != tt.wantErr {
t.Errorf("getFlavorsByFilter() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && len(actual) != tt.wantCount {
t.Errorf("getFlavorsByFilter() got %d flavors, want %d", len(actual), tt.wantCount)
}
},
)
}
}
func TestGetAllFlavors(t *testing.T) {
var currentPage int64
client := &mockFlavorsClient{
executeRequest: func() sqlserverflexbeta.ApiGetFlavorsRequestRequest {
return &mockRequest{
executeFunc: func() (*sqlserverflexbeta.GetFlavorsResponse, error) {
currentPage++
return mockResp(currentPage)
},
}
},
}
res, err := getAllFlavors(context.Background(), client, "pid", "reg")
if err != nil {
t.Errorf("getAllFlavors() unexpected error: %v", err)
}
if len(res) != 3 {
t.Errorf("getAllFlavors() expected 3 flavor, got %d", len(res))
}
}
// import (
// "context"
// "testing"
//
// "github.com/stackitcloud/stackit-sdk-go/core/utils"
//
// "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
//)
//
// type mockRequest struct {
// executeFunc func() (*v3beta1api.GetFlavorsResponse, error)
//}
//
// func (m *mockRequest) Page(_ int64) v3beta1api.ApiGetFlavorsRequestRequest { return m }
// func (m *mockRequest) Size(_ int64) v3beta1api.ApiGetFlavorsRequestRequest { return m }
// func (m *mockRequest) Sort(_ v3beta1api.FlavorSort) v3beta1api.ApiGetFlavorsRequestRequest {
// return m
//}
// func (m *mockRequest) Execute() (*v3beta1api.GetFlavorsResponse, error) {
// return m.executeFunc()
//}
//
// type mockFlavorsClient struct {
// executeRequest func() v3beta1api.ApiGetFlavorsRequestRequest
//}
//
// func (m *mockFlavorsClient) GetFlavorsRequest(_ context.Context, _, _ string) v3beta1api.ApiGetFlavorsRequestRequest {
// return m.executeRequest()
//}
//
// var mockResp = func(page int64) (*v3beta1api.GetFlavorsResponse, error) {
// if page == 1 {
// return &v3beta1api.GetFlavorsResponse{
// Flavors: &[]v3beta1api.ListFlavors{
// {Id: utils.Ptr("flavor-1"), Description: utils.Ptr("first")},
// {Id: utils.Ptr("flavor-2"), Description: utils.Ptr("second")},
// },
// }, nil
// }
// if page == 2 {
// return &v3beta1api.GetFlavorsResponse{
// Flavors: &[]v3beta1api.ListFlavors{
// {Id: utils.Ptr("flavor-3"), Description: utils.Ptr("three")},
// },
// }, nil
// }
//
// return &v3beta1api.GetFlavorsResponse{
// Flavors: &[]v3beta1api.ListFlavors{},
// }, nil
//}
//
// func TestGetFlavorsByFilter(t *testing.T) {
// tests := []struct {
// description string
// projectId string
// region string
// mockErr error
// filter func(v3beta1api.ListFlavors) bool
// wantCount int
// wantErr bool
// }{
// {
// description: "Success - Get all flavors (2 pages)",
// projectId: "pid", region: "reg",
// filter: func(_ v3beta1api.ListFlavors) bool { return true },
// wantCount: 3,
// wantErr: false,
// },
// {
// description: "Success - Filter flavors by description",
// projectId: "pid", region: "reg",
// filter: func(f v3beta1api.ListFlavors) bool { return *f.Description == "first" },
// wantCount: 1,
// wantErr: false,
// },
// {
// description: "Error - Missing parameters",
// projectId: "", region: "reg",
// wantErr: true,
// },
// }
//
// for _, tt := range tests {
// t.Run(
// tt.description, func(t *testing.T) {
// var currentPage int64
// client := &mockFlavorsClient{
// executeRequest: func() v3beta1api.ApiGetFlavorsRequestRequest {
// return &mockRequest{
// executeFunc: func() (*v3beta1api.GetFlavorsResponse, error) {
// currentPage++
// return mockResp(currentPage)
// },
// }
// },
// }
// actual, err := getFlavorsByFilter(context.Background(), client, tt.projectId, tt.region, tt.filter)
//
// if (err != nil) != tt.wantErr {
// t.Errorf("getFlavorsByFilter() error = %v, wantErr %v", err, tt.wantErr)
// return
// }
//
// if !tt.wantErr && len(actual) != tt.wantCount {
// t.Errorf("getFlavorsByFilter() got %d flavors, want %d", len(actual), tt.wantCount)
// }
// },
// )
// }
//}
//
// func TestGetAllFlavors(t *testing.T) {
// var currentPage int64
// client := &mockFlavorsClient{
// executeRequest: func() v3beta1api.ApiGetFlavorsRequestRequest {
// return &mockRequest{
// executeFunc: func() (*v3beta1api.GetFlavorsResponse, error) {
// currentPage++
// return mockResp(currentPage)
// },
// }
// },
// }
//
// res, err := getAllFlavors(context.Background(), client, "pid", "reg")
// if err != nil {
// t.Errorf("getAllFlavors() unexpected error: %v", err)
// }
// if len(res) != 3 {
// t.Errorf("getAllFlavors() expected 3 flavor, got %d", len(res))
// }
//}

View file

@ -15,7 +15,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavors/datasources_gen"
)
@ -34,7 +34,7 @@ type dataSourceModel struct {
}
type flavorsDataSource struct {
client *sqlserverflexbetaPkg.APIClient
client *v3beta1api.APIClient
providerData core.ProviderData
}
@ -82,7 +82,7 @@ func (d *flavorsDataSource) Configure(
config.WithRegion(d.providerData.GetRegion()),
)
}
apiClient, err := sqlserverflexbetaPkg.NewAPIClient(apiClientConfigOptions...)
apiClient, err := v3beta1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
@ -121,7 +121,7 @@ func (d *flavorsDataSource) Read(ctx context.Context, req datasource.ReadRequest
ctx = tflog.SetField(ctx, "flavors_id", flavorsId)
// TODO: refactor to correct implementation
_, err := d.client.GetFlavorsRequest(ctx, projectId, region).Execute()
_, err := d.client.DefaultAPI.GetFlavorsRequest(ctx, projectId, region).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -14,7 +14,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance/datasources_gen"
)
@ -34,7 +34,7 @@ type dataSourceModel struct {
}
type instanceDataSource struct {
client *sqlserverflexbetaPkg.APIClient
client *v3beta1api.APIClient
providerData core.ProviderData
}
@ -77,7 +77,7 @@ func (d *instanceDataSource) Configure(
config.WithRegion(d.providerData.GetRegion()),
)
}
apiClient, err := sqlserverflexbetaPkg.NewAPIClient(apiClientConfigOptions...)
apiClient, err := v3beta1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
@ -112,7 +112,7 @@ func (d *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
instanceResp, err := d.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := d.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -11,15 +11,15 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaDataGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance/datasources_gen"
sqlserverflexbetaResGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance/resources_gen"
)
func mapResponseToModel(
ctx context.Context,
resp *sqlserverflexbeta.GetInstanceResponse,
resp *v3beta1api.GetInstanceResponse,
m *sqlserverflexbetaResGen.InstanceModel,
tfDiags diag.Diagnostics,
) error {
@ -53,7 +53,7 @@ func mapResponseToModel(
}
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Status = types.StringValue(string(resp.GetStatus()))
stor, diags := sqlserverflexbetaResGen.NewStorageValue(
@ -75,7 +75,7 @@ func mapResponseToModel(
func mapDataResponseToModel(
ctx context.Context,
resp *sqlserverflexbeta.GetInstanceResponse,
resp *v3beta1api.GetInstanceResponse,
m *dataSourceModel,
tfDiags diag.Diagnostics,
) error {
@ -109,7 +109,7 @@ func mapDataResponseToModel(
}
m.Network = net
m.Replicas = types.Int64Value(int64(resp.GetReplicas()))
m.RetentionDays = types.Int64Value(resp.GetRetentionDays())
m.RetentionDays = types.Int64Value(int64(resp.GetRetentionDays()))
m.Status = types.StringValue(string(resp.GetStatus()))
stor, diags := sqlserverflexbetaDataGen.NewStorageValue(
@ -132,14 +132,14 @@ func mapDataResponseToModel(
func handleEncryption(
ctx context.Context,
m *sqlserverflexbetaResGen.InstanceModel,
resp *sqlserverflexbeta.GetInstanceResponse,
resp *v3beta1api.GetInstanceResponse,
) sqlserverflexbetaResGen.EncryptionValue {
if !resp.HasEncryption() ||
resp.Encryption == nil ||
resp.Encryption.KekKeyId == nil ||
resp.Encryption.KekKeyRingId == nil ||
resp.Encryption.KekKeyVersion == nil ||
resp.Encryption.ServiceAccount == nil {
resp.Encryption.KekKeyId == "" ||
resp.Encryption.KekKeyRingId == "" ||
resp.Encryption.KekKeyVersion == "" ||
resp.Encryption.ServiceAccount == "" {
if m.Encryption.IsNull() || m.Encryption.IsUnknown() {
return sqlserverflexbetaResGen.NewEncryptionValueNull()
}
@ -161,14 +161,14 @@ func handleEncryption(
func handleDSEncryption(
ctx context.Context,
m *dataSourceModel,
resp *sqlserverflexbeta.GetInstanceResponse,
resp *v3beta1api.GetInstanceResponse,
) sqlserverflexbetaDataGen.EncryptionValue {
if !resp.HasEncryption() ||
resp.Encryption == nil ||
resp.Encryption.KekKeyId == nil ||
resp.Encryption.KekKeyRingId == nil ||
resp.Encryption.KekKeyVersion == nil ||
resp.Encryption.ServiceAccount == nil {
resp.Encryption.KekKeyId == "" ||
resp.Encryption.KekKeyRingId == "" ||
resp.Encryption.KekKeyVersion == "" ||
resp.Encryption.ServiceAccount == "" {
if m.Encryption.IsNull() || m.Encryption.IsUnknown() {
return sqlserverflexbetaDataGen.NewEncryptionValueNull()
}
@ -190,51 +190,50 @@ func handleDSEncryption(
func toCreatePayload(
ctx context.Context,
model *sqlserverflexbetaResGen.InstanceModel,
) (*sqlserverflexbeta.CreateInstanceRequestPayload, error) {
) (*v3beta1api.CreateInstanceRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
storagePayload := &sqlserverflexbeta.CreateInstanceRequestPayloadGetStorageArgType{}
storagePayload := v3beta1api.StorageCreate{}
if !model.Storage.IsNull() && !model.Storage.IsUnknown() {
storagePayload.Class = model.Storage.Class.ValueStringPointer()
storagePayload.Size = model.Storage.Size.ValueInt64Pointer()
storagePayload.Class = model.Storage.Class.ValueString()
storagePayload.Size = model.Storage.Size.ValueInt64()
}
var encryptionPayload *sqlserverflexbeta.CreateInstanceRequestPayloadGetEncryptionArgType = nil
var encryptionPayload *v3beta1api.InstanceEncryption = nil
if !model.Encryption.IsNull() && !model.Encryption.IsUnknown() {
encryptionPayload = &sqlserverflexbeta.CreateInstanceRequestPayloadGetEncryptionArgType{}
encryptionPayload.KekKeyId = model.Encryption.KekKeyId.ValueStringPointer()
encryptionPayload.KekKeyRingId = model.Encryption.KekKeyRingId.ValueStringPointer()
encryptionPayload.KekKeyVersion = model.Encryption.KekKeyVersion.ValueStringPointer()
encryptionPayload.ServiceAccount = model.Encryption.ServiceAccount.ValueStringPointer()
encryptionPayload = &v3beta1api.InstanceEncryption{}
encryptionPayload.KekKeyId = model.Encryption.KekKeyId.ValueString()
encryptionPayload.KekKeyRingId = model.Encryption.KekKeyRingId.ValueString()
encryptionPayload.KekKeyVersion = model.Encryption.KekKeyVersion.ValueString()
encryptionPayload.ServiceAccount = model.Encryption.ServiceAccount.ValueString()
}
networkPayload := &sqlserverflexbeta.CreateInstanceRequestPayloadGetNetworkArgType{}
networkPayload := v3beta1api.CreateInstanceRequestPayloadNetwork{}
if !model.Network.IsNull() && !model.Network.IsUnknown() {
networkPayload.AccessScope = sqlserverflexbeta.CreateInstanceRequestPayloadNetworkGetAccessScopeAttributeType(
model.Network.AccessScope.ValueStringPointer(),
accScope := v3beta1api.InstanceNetworkAccessScope(
model.Network.AccessScope.ValueString(),
)
networkPayload.AccessScope = &accScope
var resList []string
diags := model.Network.Acl.ElementsAs(ctx, &resList, false)
if diags.HasError() {
return nil, fmt.Errorf("error converting network acl list")
}
networkPayload.Acl = &resList
networkPayload.Acl = resList
}
return &sqlserverflexbeta.CreateInstanceRequestPayload{
BackupSchedule: conversion.StringValueToPointer(model.BackupSchedule),
return &v3beta1api.CreateInstanceRequestPayload{
BackupSchedule: model.BackupSchedule.ValueString(),
Encryption: encryptionPayload,
FlavorId: conversion.StringValueToPointer(model.FlavorId),
Name: conversion.StringValueToPointer(model.Name),
FlavorId: model.FlavorId.ValueString(),
Name: model.Name.ValueString(),
Network: networkPayload,
RetentionDays: conversion.Int64ValueToPointer(model.RetentionDays),
RetentionDays: int32(model.RetentionDays.ValueInt64()), //nolint:gosec // TODO
Storage: storagePayload,
Version: sqlserverflexbeta.CreateInstanceRequestPayloadGetVersionAttributeType(
conversion.StringValueToPointer(model.Version),
),
Version: v3beta1api.InstanceVersion(model.Version.ValueString()),
}, nil
}
@ -242,31 +241,34 @@ func toUpdatePayload(
ctx context.Context,
m *sqlserverflexbetaResGen.InstanceModel,
resp *resource.UpdateResponse,
) (*sqlserverflexbeta.UpdateInstanceRequestPayload, error) {
) (*v3beta1api.UpdateInstanceRequestPayload, error) {
if m == nil {
return nil, fmt.Errorf("nil model")
}
if m.Replicas.ValueInt64() > math.MaxUint32 {
return nil, fmt.Errorf("replicas value is too big for uint32")
}
replVal := sqlserverflexbeta.Replicas(uint32(m.Replicas.ValueInt64())) // nolint:gosec // check is performed above
replVal := v3beta1api.Replicas(uint32(m.Replicas.ValueInt64())) // nolint:gosec // check is performed above
var netAcl []string
diags := m.Network.Acl.ElementsAs(ctx, &netAcl, false)
var netACL []string
diags := m.Network.Acl.ElementsAs(ctx, &netACL, false)
resp.Diagnostics.Append(diags...)
if diags.HasError() {
return nil, fmt.Errorf("error converting model network acl value")
}
return &sqlserverflexbeta.UpdateInstanceRequestPayload{
BackupSchedule: m.BackupSchedule.ValueStringPointer(),
FlavorId: m.FlavorId.ValueStringPointer(),
Name: m.Name.ValueStringPointer(),
Network: sqlserverflexbeta.NewUpdateInstanceRequestPayloadNetwork(netAcl),
Replicas: &replVal,
RetentionDays: m.RetentionDays.ValueInt64Pointer(),
Storage: &sqlserverflexbeta.StorageUpdate{Size: m.Storage.Size.ValueInt64Pointer()},
Version: sqlserverflexbeta.UpdateInstanceRequestPayloadGetVersionAttributeType(
m.Version.ValueStringPointer(),
),
if m.RetentionDays.ValueInt64() > math.MaxInt32 {
return nil, fmt.Errorf("value is too large for int32")
}
return &v3beta1api.UpdateInstanceRequestPayload{
BackupSchedule: m.BackupSchedule.ValueString(),
FlavorId: m.FlavorId.ValueString(),
Name: m.Name.ValueString(),
Network: v3beta1api.UpdateInstanceRequestPayloadNetwork{
Acl: netACL,
},
Replicas: replVal,
RetentionDays: int32(m.RetentionDays.ValueInt64()), //nolint:gosec // checked above
Storage: v3beta1api.StorageUpdate{Size: m.Storage.Size.ValueInt64Pointer()},
Version: v3beta1api.InstanceVersion(m.Version.ValueString()),
}, nil
}

View file

@ -10,9 +10,8 @@ import (
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexbetaPkgGen "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaPkgGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbetaRs "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance/resources_gen"
)
@ -73,26 +72,32 @@ func Test_handleEncryption(t *testing.T) {
m: &sqlserverflexbetaRs.InstanceModel{},
resp: &sqlserverflexbetaPkgGen.GetInstanceResponse{
Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{
KekKeyId: utils.Ptr("kek_key_id"),
KekKeyRingId: utils.Ptr("kek_key_ring_id"),
KekKeyVersion: utils.Ptr("kek_key_version"),
ServiceAccount: utils.Ptr("kek_svc_acc"),
KekKeyId: ("kek_key_id"),
KekKeyRingId: ("kek_key_ring_id"),
KekKeyVersion: ("kek_key_version"),
ServiceAccount: ("kek_svc_acc"),
},
},
},
want: sqlserverflexbetaRs.EncryptionValue{
KekKeyId: types.StringValue("kek_key_id"),
KekKeyRingId: types.StringValue("kek_key_ring_id"),
KekKeyVersion: types.StringValue("kek_key_version"),
ServiceAccount: types.StringValue("kek_svc_acc"),
},
want: sqlserverflexbetaRs.NewEncryptionValueMust(
sqlserverflexbetaRs.EncryptionValue{}.AttributeTypes(context.TODO()),
map[string]attr.Value{
"kek_key_id": types.StringValue("kek_key_id"),
"kek_key_ring_id": types.StringValue("kek_key_ring_id"),
"kek_key_version": types.StringValue("kek_key_version"),
"service_account": types.StringValue("kek_svc_acc"),
},
),
},
}
for _, tt := range tests {
t.Run(
tt.name, func(t *testing.T) {
if got := handleEncryption(t.Context(), tt.args.m, tt.args.resp); !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleEncryption() = %v, want %v", got, tt.want)
got := handleEncryption(t.Context(), tt.args.m, tt.args.resp)
diff := cmp.Diff(tt.want, got)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
},
)
@ -188,19 +193,19 @@ func Test_toCreatePayload(t *testing.T) {
},
},
want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
BackupSchedule: nil,
BackupSchedule: "",
Encryption: &sqlserverflexbetaPkgGen.InstanceEncryption{
KekKeyId: utils.Ptr("kek_key_id"),
KekKeyRingId: utils.Ptr("kek_key_ring_id"),
KekKeyVersion: utils.Ptr("kek_key_version"),
ServiceAccount: utils.Ptr("sacc"),
KekKeyId: ("kek_key_id"),
KekKeyRingId: ("kek_key_ring_id"),
KekKeyVersion: ("kek_key_version"),
ServiceAccount: ("sacc"),
},
FlavorId: nil,
Name: nil,
Network: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
RetentionDays: nil,
Storage: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadGetStorageArgType{},
Version: nil,
FlavorId: "",
Name: "",
Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
RetentionDays: 0,
Storage: sqlserverflexbetaPkgGen.StorageCreate{},
Version: "",
},
wantErr: false,
},
@ -214,14 +219,14 @@ func Test_toCreatePayload(t *testing.T) {
},
},
want: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayload{
BackupSchedule: nil,
BackupSchedule: "",
Encryption: nil,
FlavorId: nil,
Name: nil,
Network: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
RetentionDays: nil,
Storage: &sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadGetStorageArgType{},
Version: nil,
FlavorId: "",
Name: "",
Network: sqlserverflexbetaPkgGen.CreateInstanceRequestPayloadNetwork{},
RetentionDays: 0,
Storage: sqlserverflexbetaPkgGen.StorageCreate{},
Version: "",
},
wantErr: false,
},

View file

@ -19,7 +19,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
wait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexbeta"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
@ -40,7 +40,7 @@ func NewInstanceResource() resource.Resource {
}
type instanceResource struct {
client *sqlserverflexbeta.APIClient
client *v3beta1api.APIClient
providerData core.ProviderData
}
@ -125,7 +125,7 @@ func (r *instanceResource) Configure(
} else {
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(r.providerData.GetRegion()))
}
apiClient, err := sqlserverflexbeta.NewAPIClient(apiClientConfigOptions...)
apiClient, err := v3beta1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
@ -208,7 +208,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
}
// Create new Instance
createResp, err := r.client.CreateInstanceRequest(
createResp, err := r.client.DefaultAPI.CreateInstanceRequest(
ctx,
projectId,
region,
@ -220,15 +220,13 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = core.LogResponse(ctx)
InstanceId := *createResp.Id
// Example data value setting
data.InstanceId = types.StringValue("id-from-response")
instanceId := createResp.Id
data.InstanceId = types.StringValue(instanceId)
identity := InstanceResourceIdentityModel{
ProjectID: types.StringValue(projectId),
Region: types.StringValue(region),
InstanceID: types.StringValue(InstanceId),
InstanceID: types.StringValue(instanceId),
}
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
if resp.Diagnostics.HasError() {
@ -237,9 +235,9 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
waitResp, err := wait.CreateInstanceWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
InstanceId,
instanceId,
region,
).SetSleepBeforeWait(
10 * time.Second,
@ -256,7 +254,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
return
}
if waitResp.Id == nil {
if waitResp.Id == "" {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -303,7 +301,7 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
instanceId := data.InstanceId.ValueString()
ctx = tflog.SetField(ctx, "instance_id", instanceId)
instanceResp, err := r.client.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
instanceResp, err := r.client.DefaultAPI.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if ok && oapiErr.StatusCode == http.StatusNotFound {
@ -379,7 +377,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
return
}
// Update existing instance
err = r.client.UpdateInstanceRequest(
err = r.client.DefaultAPI.UpdateInstanceRequest(
ctx,
projectId,
region,
@ -393,7 +391,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = core.LogResponse(ctx)
waitResp, err := wait.
UpdateInstanceWaitHandler(ctx, r.client, projectId, instanceId, region).
UpdateInstanceWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region).
SetSleepBeforeWait(15 * time.Second).
SetTimeout(45 * time.Minute).
WaitWithContext(ctx)
@ -465,7 +463,7 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
// Delete existing instance
err := r.client.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
err := r.client.DefaultAPI.DeleteInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting instance", fmt.Sprintf("Calling API: %v", err))
return
@ -473,7 +471,7 @@ func (r *instanceResource) Delete(ctx context.Context, req resource.DeleteReques
ctx = core.LogResponse(ctx)
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client, projectId, instanceId, region).WaitWithContext(ctx)
delResp, err := wait.DeleteInstanceWaitHandler(ctx, r.client.DefaultAPI, projectId, instanceId, region).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(
ctx,

View file

@ -4,18 +4,14 @@ import (
"context"
_ "embed"
"fmt"
"log"
"os"
"strconv"
"strings"
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils"
sqlserverflexbetaResGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbeta "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance"
// The fwresource import alias is so there is no collision
@ -26,46 +22,6 @@ import (
const providerPrefix = "stackitprivatepreview_sqlserverflexbeta"
var testInstances []string
func init() {
sweeperName := fmt.Sprintf("%s_%s", providerPrefix, "sweeper")
resource.AddTestSweepers(sweeperName, &resource.Sweeper{
Name: sweeperName,
F: func(region string) error {
ctx := context.Background()
apiClientConfigOptions := []config.ConfigurationOption{}
apiClient, err := sqlserverflexbetaResGen.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instances, err := apiClient.ListInstancesRequest(ctx, testutils.ProjectId, region).
Size(100).
Execute()
if err != nil {
log.Fatalln(err)
}
for _, inst := range instances.GetInstances() {
if strings.HasPrefix(inst.GetName(), "tf-acc-") {
for _, item := range testInstances {
if inst.GetName() == item {
delErr := apiClient.DeleteInstanceRequestExecute(ctx, testutils.ProjectId, region, inst.GetId())
if delErr != nil {
// TODO: maybe just warn?
log.Fatalln(delErr)
}
}
}
}
}
return nil
},
})
}
func TestInstanceResourceSchema(t *testing.T) {
t.Parallel()
@ -175,7 +131,6 @@ func TestAccInstance(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", exData.TfName)
testInstances = append(testInstances, exData.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
@ -234,7 +189,6 @@ func TestAccInstanceReApply(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", exData.TfName)
testInstances = append(testInstances, exData.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
@ -320,7 +274,6 @@ func TestAccInstanceNoEncryption(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
@ -423,7 +376,6 @@ func TestAccInstanceEncryption(t *testing.T) {
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{

View file

@ -14,7 +14,8 @@ import (
sqlserverflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user/datasources_gen"
)
@ -39,7 +40,7 @@ type dataSourceModel struct {
}
type userDataSource struct {
client *sqlserverflexbetaPkg.APIClient
client *v3beta1api.APIClient
providerData core.ProviderData
}
@ -94,7 +95,7 @@ func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
ctx = tflog.SetField(ctx, "user_id", userId)
ctx = tflog.SetField(ctx, "region", region)
recordSetResp, err := d.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
recordSetResp, err := d.client.DefaultAPI.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
utils.LogError(
ctx,

View file

@ -8,14 +8,15 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
)
// mapDataSourceFields maps the API response to a dataSourceModel.
func mapDataSourceFields(userResp *sqlserverflexbeta.GetUserResponse, model *dataSourceModel, region string) error {
func mapDataSourceFields(userResp *v3beta1api.GetUserResponse, model *dataSourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -28,8 +29,8 @@ func mapDataSourceFields(userResp *sqlserverflexbeta.GetUserResponse, model *dat
var userId int64
if model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
} else if user.Id != 0 {
userId = user.Id
} else {
return fmt.Errorf("user id not present")
}
@ -39,14 +40,14 @@ func mapDataSourceFields(userResp *sqlserverflexbeta.GetUserResponse, model *dat
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
model.Username = types.StringValue(user.Username)
// Map roles
if user.Roles == nil {
model.Roles = types.List(types.SetNull(types.StringType))
} else {
var roles []attr.Value
resRoles := *user.Roles
resRoles := user.Roles
slices.Sort(resRoles)
for _, role := range resRoles {
roles = append(roles, types.StringValue(string(role)))
@ -59,17 +60,17 @@ func mapDataSourceFields(userResp *sqlserverflexbeta.GetUserResponse, model *dat
}
// Set remaining attributes
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
model.Status = types.StringPointerValue(user.Status)
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
model.Status = types.StringValue(user.Status)
model.DefaultDatabase = types.StringValue(user.DefaultDatabase)
return nil
}
// mapFields maps the API response to a resourceModel.
func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel, region string) error {
func mapFields(userResp *v3beta1api.GetUserResponse, model *resourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -82,8 +83,8 @@ func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel
var userId int64
if model.UserId.ValueInt64() != 0 {
userId = model.UserId.ValueInt64()
} else if user.Id != nil {
userId = *user.Id
} else if user.Id != 0 {
userId = user.Id
} else {
return fmt.Errorf("user id not present")
}
@ -91,11 +92,11 @@ func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel
// Set main attributes
model.Id = types.Int64Value(userId)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
model.Username = types.StringValue(user.Username)
// Map roles
if userResp.Roles != nil {
resRoles := *userResp.Roles
resRoles := userResp.Roles
slices.Sort(resRoles)
var roles []attr.Value
@ -116,14 +117,14 @@ func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel
}
// Set connection details
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
return nil
}
// mapFieldsCreate maps the API response from creating a user to a resourceModel.
func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *resourceModel, region string) error {
func mapFieldsCreate(userResp *v3beta1api.CreateUserResponse, model *resourceModel, region string) error {
if userResp == nil {
return fmt.Errorf("response is nil")
}
@ -132,21 +133,15 @@ func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *reso
}
user := userResp
if user.Id == nil {
return fmt.Errorf("user id not present")
}
userId := *user.Id
userId := user.Id
model.Id = types.Int64Value(userId)
model.UserId = types.Int64Value(userId)
model.Username = types.StringPointerValue(user.Username)
model.Username = types.StringValue(user.Username)
if user.Password == nil {
return fmt.Errorf("user password not present")
}
model.Password = types.StringValue(*user.Password)
model.Password = types.StringValue(user.Password)
if user.Roles != nil {
resRoles := *user.Roles
resRoles := user.Roles
slices.Sort(resRoles)
var roles []attr.Value
@ -164,14 +159,15 @@ func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *reso
model.Roles = types.List(types.SetNull(types.StringType))
}
model.Password = types.StringPointerValue(user.Password)
model.Uri = types.StringPointerValue(user.Uri)
model.Password = types.StringValue(user.Password)
model.Uri = types.StringValue(user.Uri)
model.Host = types.StringPointerValue(user.Host)
model.Port = types.Int64PointerValue(user.Port)
model.Host = types.StringValue(user.Host)
model.Port = types.Int64Value(int64(user.Port))
model.Region = types.StringValue(region)
model.Status = types.StringPointerValue(user.Status)
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
model.Status = types.StringValue(user.Status)
model.DefaultDatabase = types.StringValue(user.DefaultDatabase)
model.Uri = types.StringValue(user.Uri)
return nil
}
@ -180,14 +176,14 @@ func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *reso
func toCreatePayload(
model *resourceModel,
roles []string,
) (*sqlserverflexbeta.CreateUserRequestPayload, error) {
) (*v3beta1api.CreateUserRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
pl := sqlserverflexbeta.CreateUserRequestPayload{
Username: conversion.StringValueToPointer(model.Username),
Roles: &roles,
pl := v3beta1api.CreateUserRequestPayload{
Username: model.Username.ValueString(),
Roles: roles,
}
slices.Sort(roles)
if !model.DefaultDatabase.IsNull() || !model.DefaultDatabase.IsUnknown() {

View file

@ -6,9 +6,8 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbeta "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
func TestMapDataSourceFields(t *testing.T) {
@ -29,29 +28,29 @@ func TestMapDataSourceFields(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Host: types.StringNull(),
Port: types.Int64Null(),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
Status: types.StringNull(),
DefaultDatabase: types.StringNull(),
Status: types.StringValue(""),
DefaultDatabase: types.StringValue(""),
},
true,
},
{
"simple_values",
&sqlserverflexbeta.GetUserResponse{
Roles: &[]string{
Roles: []string{
"role_1",
"role_2",
"",
},
Username: utils.Ptr("username"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Status: utils.Ptr("active"),
DefaultDatabase: utils.Ptr("default_db"),
Username: ("username"),
Host: ("host"),
Port: (int32(1234)),
Status: ("active"),
DefaultDatabase: ("default_db"),
},
testRegion,
dataSourceModel{
@ -80,23 +79,25 @@ func TestMapDataSourceFields(t *testing.T) {
{
"null_fields_and_int_conversions",
&sqlserverflexbeta.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]string{},
Username: nil,
Host: nil,
Port: utils.Ptr(int64(2123456789)),
Id: (int64(1)),
Roles: []string{},
Username: "",
Host: "",
Port: (int32(2123456789)),
},
testRegion,
dataSourceModel{
Id: types.StringValue("pid,region,iid,1"),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringNull(),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
Id: types.StringValue("pid,region,iid,1"),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringValue(""),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringValue(""),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
},
true,
},
@ -160,39 +161,43 @@ func TestMapFieldsCreate(t *testing.T) {
{
"default_values",
&sqlserverflexbeta.CreateUserResponse{
Id: utils.Ptr(int64(1)),
Password: utils.Ptr(""),
Id: int64(1),
Password: "",
},
testRegion,
resourceModel{
Id: types.Int64Value(1),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringValue(""),
Host: types.StringNull(),
Port: types.Int64Null(),
Region: types.StringValue(testRegion),
Id: types.Int64Value(1),
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Password: types.StringValue(""),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
Uri: types.StringValue(""),
},
true,
},
{
"simple_values",
&sqlserverflexbeta.CreateUserResponse{
Id: utils.Ptr(int64(2)),
Roles: &[]string{
Id: int64(2),
Roles: []string{
"role_1",
"role_2",
"",
},
Username: utils.Ptr("username"),
Password: utils.Ptr("password"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Status: utils.Ptr("status"),
DefaultDatabase: utils.Ptr("default_db"),
Username: "username",
Password: "password",
Host: "host",
Port: int32(1234),
Status: "status",
DefaultDatabase: "default_db",
Uri: "myURI",
},
testRegion,
resourceModel{
@ -216,18 +221,19 @@ func TestMapFieldsCreate(t *testing.T) {
Region: types.StringValue(testRegion),
Status: types.StringValue("status"),
DefaultDatabase: types.StringValue("default_db"),
Uri: types.StringValue("myURI"),
},
true,
},
{
"null_fields_and_int_conversions",
&sqlserverflexbeta.CreateUserResponse{
Id: utils.Ptr(int64(3)),
Roles: &[]string{},
Username: nil,
Password: utils.Ptr(""),
Host: nil,
Port: utils.Ptr(int64(2123456789)),
Id: (int64(3)),
Roles: []string{},
Username: "",
Password: (""),
Host: "",
Port: (int32(2123456789)),
},
testRegion,
resourceModel{
@ -235,14 +241,15 @@ func TestMapFieldsCreate(t *testing.T) {
UserId: types.Int64Value(3),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Password: types.StringValue(""),
Host: types.StringNull(),
Host: types.StringValue(""),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
DefaultDatabase: types.StringNull(),
Status: types.StringNull(),
DefaultDatabase: types.StringValue(""),
Status: types.StringValue(""),
Uri: types.StringValue(""),
},
true,
},
@ -253,29 +260,20 @@ func TestMapFieldsCreate(t *testing.T) {
resourceModel{},
false,
},
{
"nil_response_2",
&sqlserverflexbeta.CreateUserResponse{},
testRegion,
resourceModel{},
false,
},
{
"no_resource_id",
&sqlserverflexbeta.CreateUserResponse{},
testRegion,
resourceModel{},
false,
},
{
"no_password",
&sqlserverflexbeta.CreateUserResponse{
Id: utils.Ptr(int64(1)),
},
testRegion,
resourceModel{},
false,
},
//{
// "nil_response_2",
// &sqlserverflexbeta.CreateUserResponse{},
// testRegion,
// resourceModel{},
// false,
// },
//{
// "no_resource_id",
// &sqlserverflexbeta.CreateUserResponse{},
// testRegion,
// resourceModel{},
// false,
// },
}
for _, tt := range tests {
t.Run(
@ -320,10 +318,10 @@ func TestMapFields(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetNull(types.StringType)),
Host: types.StringNull(),
Port: types.Int64Null(),
Host: types.StringValue(""),
Port: types.Int64Value(0),
Region: types.StringValue(testRegion),
},
true,
@ -331,14 +329,14 @@ func TestMapFields(t *testing.T) {
{
"simple_values",
&sqlserverflexbeta.GetUserResponse{
Roles: &[]string{
Roles: []string{
"role_2",
"role_1",
"",
},
Username: utils.Ptr("username"),
Host: utils.Ptr("host"),
Port: utils.Ptr(int64(1234)),
Username: ("username"),
Host: ("host"),
Port: (int32(1234)),
},
testRegion,
resourceModel{
@ -365,11 +363,11 @@ func TestMapFields(t *testing.T) {
{
"null_fields_and_int_conversions",
&sqlserverflexbeta.GetUserResponse{
Id: utils.Ptr(int64(1)),
Roles: &[]string{},
Username: nil,
Host: nil,
Port: utils.Ptr(int64(2123456789)),
Id: (int64(1)),
Roles: []string{},
Username: "",
Host: "",
Port: (int32(2123456789)),
},
testRegion,
resourceModel{
@ -377,9 +375,9 @@ func TestMapFields(t *testing.T) {
UserId: types.Int64Value(1),
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
Username: types.StringNull(),
Username: types.StringValue(""),
Roles: types.List(types.SetValueMust(types.StringType, []attr.Value{})),
Host: types.StringNull(),
Host: types.StringValue(""),
Port: types.Int64Value(2123456789),
Region: types.StringValue(testRegion),
},
@ -446,8 +444,8 @@ func TestToCreatePayload(t *testing.T) {
&resourceModel{},
[]string{},
&sqlserverflexbeta.CreateUserRequestPayload{
Roles: &[]string{},
Username: nil,
Roles: []string{},
Username: "",
},
true,
},
@ -461,27 +459,27 @@ func TestToCreatePayload(t *testing.T) {
"role_2",
},
&sqlserverflexbeta.CreateUserRequestPayload{
Roles: &[]string{
Roles: []string{
"role_1",
"role_2",
},
Username: utils.Ptr("username"),
Username: ("username"),
},
true,
},
{
"null_fields_and_int_conversions",
&resourceModel{
Username: types.StringNull(),
Username: types.StringValue(""),
},
[]string{
"",
},
&sqlserverflexbeta.CreateUserRequestPayload{
Roles: &[]string{
Roles: []string{
"",
},
Username: nil,
Username: "",
},
true,
},
@ -499,8 +497,8 @@ func TestToCreatePayload(t *testing.T) {
},
[]string{},
&sqlserverflexbeta.CreateUserRequestPayload{
Roles: &[]string{},
Username: utils.Ptr("username"),
Roles: []string{},
Username: ("username"),
},
true,
},

View file

@ -18,7 +18,8 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbeta "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
sqlserverflexbetaUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/utils"
sqlserverflexbetaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexbeta"
@ -250,7 +251,7 @@ func (r *userResource) Create(
return
}
// Create new user
userResp, err := r.client.CreateUserRequest(
userResp, err := r.client.DefaultAPI.CreateUserRequest(
ctx,
projectId,
region,
@ -263,7 +264,7 @@ func (r *userResource) Create(
ctx = core.LogResponse(ctx)
if userResp == nil || userResp.Id == nil || *userResp.Id == 0 {
if userResp == nil || userResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -273,7 +274,7 @@ func (r *userResource) Create(
return
}
userId := *userResp.Id
userId := userResp.Id
ctx = tflog.SetField(ctx, "user_id", userId)
// Set data returned by API in identity
@ -301,7 +302,7 @@ func (r *userResource) Create(
waitResp, err := sqlserverflexbetaWait.CreateUserWaitHandler(
ctx,
r.client,
r.client.DefaultAPI,
projectId,
instanceId,
region,
@ -322,7 +323,7 @@ func (r *userResource) Create(
return
}
if waitResp.Id == nil {
if waitResp.Id == 0 {
core.LogAndAddError(
ctx,
&resp.Diagnostics,
@ -376,7 +377,7 @@ func (r *userResource) Read(
ctx = tflog.SetField(ctx, "user_id", userId)
ctx = tflog.SetField(ctx, "region", region)
recordSetResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
recordSetResp, err := r.client.DefaultAPI.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(
@ -469,7 +470,7 @@ func (r *userResource) Delete(
// Delete existing record set
// err := r.client.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
err := r.client.DeleteUserRequestExecute(ctx, projectId, region, instanceId, userId)
err := r.client.DefaultAPI.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -491,7 +492,7 @@ func (r *userResource) Delete(
}
}
// Delete existing record set
_, err = sqlserverflexbetaWait.DeleteUserWaitHandler(ctx, r.client, projectId, region, instanceId, userId).
_, err = sqlserverflexbetaWait.DeleteUserWaitHandler(ctx, r.client.DefaultAPI, projectId, region, instanceId, userId).
WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("Calling API: %v", err))

View file

@ -4,7 +4,7 @@ import (
"context"
"fmt"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/stackitcloud/stackit-sdk-go/core/config"

View file

@ -10,7 +10,7 @@ import (
sdkClients "github.com/stackitcloud/stackit-sdk-go/core/clients"
"github.com/stackitcloud/stackit-sdk-go/core/config"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
@ -36,7 +36,7 @@ func TestConfigureClient(t *testing.T) {
name string
args args
wantErr bool
expected *sqlserverflex.APIClient
expected *v3beta1api.APIClient
}{
{
name: "default endpoint",
@ -45,8 +45,8 @@ func TestConfigureClient(t *testing.T) {
Version: testVersion,
},
},
expected: func() *sqlserverflex.APIClient {
apiClient, err := sqlserverflex.NewAPIClient(
expected: func() *v3beta1api.APIClient {
apiClient, err := v3beta1api.NewAPIClient(
config.WithRegion("eu01"),
utils.UserAgentConfigOption(testVersion),
)
@ -65,8 +65,8 @@ func TestConfigureClient(t *testing.T) {
SQLServerFlexCustomEndpoint: testCustomEndpoint,
},
},
expected: func() *sqlserverflex.APIClient {
apiClient, err := sqlserverflex.NewAPIClient(
expected: func() *v3beta1api.APIClient {
apiClient, err := v3beta1api.NewAPIClient(
utils.UserAgentConfigOption(testVersion),
config.WithEndpoint(testCustomEndpoint),
)
@ -89,7 +89,7 @@ func TestConfigureClient(t *testing.T) {
t.Errorf("ConfigureClient() error = %v, want %v", diags.HasError(), tt.wantErr)
}
if !reflect.DeepEqual(actual, tt.expected) {
if !reflect.DeepEqual(actual.GetConfig(), tt.expected.GetConfig()) {
t.Errorf("ConfigureClient() = %v, want %v", actual, tt.expected)
}
},

View file

@ -0,0 +1,12 @@
package utils
func RemoveQuotes(src string) string {
var res string
if src != "" && src[0] == '"' {
res = src[1:]
}
if res != "" && res[len(res)-1] == '"' {
res = res[:len(res)-1]
}
return res
}

View file

@ -9,8 +9,7 @@ import (
"time"
"github.com/hashicorp/terraform-plugin-log/tflog"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/wait"
@ -25,68 +24,60 @@ const (
InstanceStateTerminating = "TERMINATING"
InstanceStateUnknown = "UNKNOWN"
InstanceStatePending = "PENDING"
InstanceStateDeleted = "DELETED"
)
// APIClientInstanceInterface Interface needed for tests
type APIClientInstanceInterface interface {
GetInstanceRequestExecute(ctx context.Context, projectId, region, instanceId string) (
*postgresflex.GetInstanceResponse,
error,
)
GetInstanceRequest(ctx context.Context, projectId, region, instanceId string) v3alpha1api.ApiGetInstanceRequestRequest
ListUsersRequestExecute(
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) (*postgresflex.ListUserResponse, error)
) v3alpha1api.ApiListUsersRequestRequest
}
// APIClientUserInterface Interface needed for tests
type APIClientUserInterface interface {
GetUserRequestExecute(ctx context.Context, projectId, region, instanceId string, userId int32) (
*postgresflex.GetUserResponse,
error,
)
GetUserRequest(ctx context.Context, projectId, region, instanceId string, userId int32) v3alpha1api.ApiGetUserRequestRequest
}
GetDatabaseRequestExecute(
ctx context.Context,
projectId string,
region string,
instanceId string,
databaseId int32,
) (*postgresflex.GetDatabaseResponse, error)
// APIClientDatabaseInterface Interface needed for tests
type APIClientDatabaseInterface interface {
GetDatabaseRequest(ctx context.Context, projectId string, region string, instanceId string, databaseId int32) v3alpha1api.ApiGetDatabaseRequestRequest
}
// CreateInstanceWaitHandler will wait for instance creation
func CreateInstanceWaitHandler(
ctx context.Context, a APIClientInstanceInterface, projectId, region,
instanceId string,
) *wait.AsyncActionHandler[postgresflex.GetInstanceResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
instanceCreated := false
var instanceGetResponse *postgresflex.GetInstanceResponse
var instanceGetResponse *v3alpha1api.GetInstanceResponse
maxWait := time.Minute * 45
startTime := time.Now()
extendedTimeout := 0
handler := wait.New(
func() (waitFinished bool, response *postgresflex.GetInstanceResponse, err error) {
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
if !instanceCreated {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceId {
return false, nil, nil
}
tflog.Debug(
ctx, "waiting for instance ready", map[string]interface{}{
"status": *s.Status,
"status": s.Status,
},
)
switch *s.Status {
switch s.Status {
default:
return true, s, fmt.Errorf("instance with id %s has unexpected status %s", instanceId, *s.Status)
return true, s, fmt.Errorf("instance with id %s has unexpected status %s", instanceId, s.Status)
case InstanceStateEmpty:
return false, nil, nil
case InstanceStatePending:
@ -111,7 +102,7 @@ func CreateInstanceWaitHandler(
extendedTimeout++
if *s.Network.AccessScope == "SNA" {
ready := true
if s.Network == nil || s.Network.InstanceAddress == nil {
if s.Network.InstanceAddress == nil {
tflog.Warn(ctx, "Waiting for instance_address")
ready = false
}
@ -123,16 +114,12 @@ func CreateInstanceWaitHandler(
return false, nil, nil
}
}
if s.IsDeletable == nil {
tflog.Warn(ctx, "Waiting for is_deletable")
return false, nil, nil
}
}
instanceCreated = true
instanceGetResponse = s
case InstanceStateSuccess:
if s.Network != nil && s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.InstanceAddress == nil {
tflog.Warn(ctx, "Waiting for instance_address")
return false, nil, nil
@ -155,7 +142,7 @@ func CreateInstanceWaitHandler(
tflog.Info(ctx, "Waiting for instance (calling list users")
// // User operations aren't available right after an instance is deemed successful
// // To check if they are, perform a users request
_, err = a.ListUsersRequestExecute(ctx, projectId, region, instanceId)
_, err = a.ListUsersRequest(ctx, projectId, region, instanceId).Execute()
if err == nil {
return true, instanceGetResponse, nil
}
@ -180,21 +167,21 @@ func CreateInstanceWaitHandler(
// PartialUpdateInstanceWaitHandler will wait for instance update
func PartialUpdateInstanceWaitHandler(
ctx context.Context, a APIClientInstanceInterface, projectId, region,
instanceId string,
) *wait.AsyncActionHandler[postgresflex.GetInstanceResponse] {
ctx context.Context, a APIClientInstanceInterface, projectID, region,
instanceID string,
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *postgresflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectID, region, instanceID).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceID {
return false, nil, nil
}
switch *s.Status {
switch s.Status {
default:
return true, s, fmt.Errorf("instance with id %s has unexpected status %s", instanceId, *s.Status)
return true, s, fmt.Errorf("instance with id %s has unexpected status %s", instanceID, s.Status)
case InstanceStateEmpty:
return false, nil, nil
case InstanceStatePending:
@ -208,7 +195,7 @@ func PartialUpdateInstanceWaitHandler(
case InstanceStateUnknown:
return false, nil, nil
case InstanceStateFailed:
return true, s, fmt.Errorf("update got status FAILURE for instance with id %s", instanceId)
return true, s, fmt.Errorf("update got status FAILURE for instance with id %s", instanceID)
}
},
)
@ -220,16 +207,16 @@ func PartialUpdateInstanceWaitHandler(
func GetUserByIdWaitHandler(
ctx context.Context,
a APIClientUserInterface,
projectId, instanceId, region string,
userId int64,
) *wait.AsyncActionHandler[postgresflex.GetUserResponse] {
projectID, instanceID, region string,
userID int64,
) *wait.AsyncActionHandler[v3alpha1api.GetUserResponse] {
handler := wait.New(
func() (waitFinished bool, response *postgresflex.GetUserResponse, err error) {
if userId > math.MaxInt32 {
return false, nil, fmt.Errorf("userId value is too big for int32")
func() (waitFinished bool, response *v3alpha1api.GetUserResponse, err error) {
if userID > math.MaxInt32 {
return false, nil, fmt.Errorf("userID too large for int32")
}
userId32 := int32(userId) //nolint:gosec // we need to convert databaseId to int32 because API expects int32
s, err := a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId32)
userID32 := int32(userID) //nolint:gosec // checked above
s, err := a.GetUserRequest(ctx, projectID, region, instanceID, userID32).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -258,14 +245,17 @@ func GetUserByIdWaitHandler(
// GetDatabaseByIdWaitHandler will wait for instance creation
func GetDatabaseByIdWaitHandler(
ctx context.Context,
a APIClientUserInterface,
projectId, instanceId, region string,
databaseId int64,
) *wait.AsyncActionHandler[postgresflex.GetDatabaseResponse] {
a APIClientDatabaseInterface,
projectID, instanceID, region string,
databaseID int64,
) *wait.AsyncActionHandler[v3alpha1api.GetDatabaseResponse] {
handler := wait.New(
func() (waitFinished bool, response *postgresflex.GetDatabaseResponse, err error) {
dbId32 := int32(databaseId) //nolint:gosec // we need to convert databaseId to int32 because API expects int32
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, dbId32)
func() (waitFinished bool, response *v3alpha1api.GetDatabaseResponse, err error) {
if databaseID > math.MaxInt32 {
return false, nil, fmt.Errorf("databaseID too large for int32")
}
dbId32 := int32(databaseID) //nolint:gosec // is checked above
s, err := a.GetDatabaseRequest(ctx, projectID, region, instanceID, dbId32).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -296,3 +286,46 @@ func GetDatabaseByIdWaitHandler(
)
return handler
}
func DeleteInstanceWaitHandler(
ctx context.Context,
a APIClientInstanceInterface,
projectID,
region,
instanceID string,
timeout, sleepBeforeWait time.Duration,
) error {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectID, region, instanceID).Execute()
if err != nil {
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) // nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
if !ok {
return false, nil, fmt.Errorf("received error is no oapierror: %w", err)
}
if oapiErr.StatusCode == 404 {
return true, nil, nil
}
return false, nil, fmt.Errorf("api returned error: %w", err)
}
switch s.Status {
case InstanceStateDeleted:
return true, nil, nil
case InstanceStateEmpty, InstanceStatePending, InstanceStateUnknown, InstanceStateProgressing, InstanceStateSuccess:
return false, nil, nil
case InstanceStateFailed:
return true, nil, fmt.Errorf("wait handler got status FAILURE for instance: %s", instanceID)
default:
return true, s, fmt.Errorf("instance with id %s has unexpected status %s", instanceID, s.Status)
}
},
).
SetTimeout(timeout).
SetSleepBeforeWait(sleepBeforeWait)
_, err := handler.WaitWithContext(ctx)
if err != nil {
return err
}
return nil
}

View file

@ -10,87 +10,34 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
postgresflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
// Used for testing instance operations
type apiClientInstanceMocked struct {
instanceId string
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceIsForceDeleted bool
instanceGetFails bool
usersGetErrorStatus int
}
func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
_ context.Context,
_, _, _ string,
) (*postgresflex.GetInstanceResponse, error) {
if a.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if a.instanceIsForceDeleted {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &postgresflex.GetInstanceResponse{
Id: &a.instanceId,
Status: postgresflex.GetInstanceResponseGetStatusAttributeType(&a.instanceState),
Network: postgresflex.GetInstanceResponseGetNetworkAttributeType(&a.instanceNetwork),
}, nil
}
func (a *apiClientInstanceMocked) ListUsersRequestExecute(
_ context.Context,
_, _, _ string,
) (*postgresflex.ListUserResponse, error) {
if a.usersGetErrorStatus != 0 {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: a.usersGetErrorStatus,
}
}
aux := int64(0)
return &postgresflex.ListUserResponse{
Pagination: &postgresflex.Pagination{
TotalRows: &aux,
},
Users: &[]postgresflex.ListUser{},
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceNetwork v3alpha1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *postgresflex.GetInstanceResponse
wantRes *v3alpha1api.GetInstanceResponse
}{
{
desc: "create_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: false,
wantRes: &postgresflex.GetInstanceResponse{
Id: utils.Ptr("foo-bar"),
Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(InstanceStateSuccess)),
Network: &postgresflex.InstanceNetwork{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: InstanceStateSuccess,
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -102,7 +49,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "create_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -115,7 +62,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "create_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -134,7 +81,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "users_get_fails",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -148,7 +95,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "users_get_fails_2",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -156,10 +103,10 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
usersGetErrorStatus: 400,
wantErr: true,
wantRes: &postgresflex.GetInstanceResponse{
Id: utils.Ptr("foo-bar"),
Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(InstanceStateSuccess)),
Network: &postgresflex.InstanceNetwork{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: InstanceStateSuccess,
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -171,8 +118,8 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "fail when response has no instance address",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
AccessScope: postgresflex.InstanceNetworkGetAccessScopeAttributeType(utils.Ptr("SNA")),
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: (*v3alpha1api.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
Acl: nil,
InstanceAddress: nil,
RouterAddress: utils.Ptr("10.0.0.1"),
@ -184,8 +131,8 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProgressing,
instanceNetwork: postgresflex.InstanceNetwork{
AccessScope: postgresflex.InstanceNetworkGetAccessScopeAttributeType(utils.Ptr("SNA")),
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: (*v3alpha1api.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
@ -197,17 +144,44 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceId: instanceId,
instanceState: tt.instanceState,
instanceNetwork: tt.instanceNetwork,
instanceGetFails: tt.instanceGetFails,
usersGetErrorStatus: tt.usersGetErrorStatus,
listUsersMock := func(_ v3alpha1api.ApiListUsersRequestRequest) (*v3alpha1api.ListUserResponse, error) {
if tt.usersGetErrorStatus != 0 {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: tt.usersGetErrorStatus,
}
}
aux := int32(0)
return &v3alpha1api.ListUserResponse{
Pagination: v3alpha1api.Pagination{
TotalRows: aux,
},
Users: []v3alpha1api.ListUser{},
}, nil
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", "", instanceId)
getInstanceMock := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
apiClientMock := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &getInstanceMock,
ListUsersRequestExecuteMock: &listUsersMock,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClientMock, "", "", instanceID)
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
@ -227,25 +201,25 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc string
instanceGetFails bool
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceNetwork v3alpha1api.InstanceNetwork
wantErr bool
wantRes *postgresflex.GetInstanceResponse
wantRes *v3alpha1api.GetInstanceResponse
}{
{
desc: "update_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: false,
wantRes: &postgresflex.GetInstanceResponse{
Id: utils.Ptr("foo-bar"),
Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(InstanceStateSuccess)),
Network: &postgresflex.InstanceNetwork{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: v3alpha1api.Status(InstanceStateSuccess),
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -257,17 +231,17 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "update_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: true,
wantRes: &postgresflex.GetInstanceResponse{
Id: utils.Ptr("foo-bar"),
Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(InstanceStateFailed)),
Network: &postgresflex.InstanceNetwork{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: v3alpha1api.Status(InstanceStateFailed),
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -279,7 +253,7 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "update_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -298,7 +272,7 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProgressing,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -311,16 +285,38 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceId: instanceId,
instanceState: tt.instanceState,
instanceNetwork: tt.instanceNetwork,
instanceGetFails: tt.instanceGetFails,
listUsersMock := func(_ v3alpha1api.ApiListUsersRequestRequest) (*v3alpha1api.ListUserResponse, error) {
aux := int32(0)
return &v3alpha1api.ListUserResponse{
Pagination: v3alpha1api.Pagination{
TotalRows: aux,
},
Users: []v3alpha1api.ListUser{},
}, nil
}
handler := PartialUpdateInstanceWaitHandler(context.Background(), apiClient, "", "", instanceId)
getInstanceMock := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
apiClientMock := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &getInstanceMock,
ListUsersRequestExecuteMock: &listUsersMock,
}
handler := PartialUpdateInstanceWaitHandler(context.Background(), apiClientMock, "", "", instanceID)
gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {

View file

@ -12,7 +12,7 @@ import (
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/wait"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
// READY, PENDING, PROGRESSING, FAILURE, UNKNOWN,
@ -28,45 +28,40 @@ const (
// APIClientInterface Interface needed for tests
type APIClientInterface interface {
GetInstanceRequestExecute(
GetInstanceRequest(
ctx context.Context,
projectId, region, instanceId string,
) (*sqlserverflex.GetInstanceResponse, error)
GetDatabaseRequestExecute(
) v3alpha1api.ApiGetInstanceRequestRequest
GetDatabaseRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
databaseName string,
) (*sqlserverflex.GetDatabaseResponse, error)
GetUserRequestExecute(
) v3alpha1api.ApiGetDatabaseRequestRequest
GetUserRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) (*sqlserverflex.GetUserResponse, error)
) v3alpha1api.ApiGetUserRequestRequest
ListRolesRequestExecute(
ListRolesRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) (*sqlserverflex.ListRolesResponse, error)
) v3alpha1api.ApiListRolesRequestRequest
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequestExecute(
ctx context.Context,
projectId string,
region string,
instanceId string,
) (*sqlserverflex.ListUserResponse, error)
) v3alpha1api.ApiListUsersRequestRequest
}
// APIClientUserInterface Interface needed for tests
@ -85,19 +80,19 @@ func CreateInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
if s.Network != nil && s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.InstanceAddress == nil {
tflog.Info(ctx, "Waiting for instance_address")
return false, nil, nil
@ -110,7 +105,7 @@ func CreateInstanceWaitHandler(
tflog.Info(ctx, "trying to get roles")
time.Sleep(10 * time.Second)
_, rolesErr := a.ListRolesRequestExecute(ctx, projectId, region, instanceId)
_, rolesErr := a.ListRolesRequest(ctx, projectId, region, instanceId).Execute()
if rolesErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(rolesErr, &oapiErr)
@ -134,7 +129,7 @@ func CreateInstanceWaitHandler(
tflog.Info(ctx, "trying to get users")
time.Sleep(10 * time.Second)
_, usersErr := a.ListUsersRequestExecute(ctx, projectId, region, instanceId)
_, usersErr := a.ListUsersRequest(ctx, projectId, region, instanceId).Execute()
if usersErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(usersErr, &oapiErr)
@ -161,7 +156,7 @@ func CreateInstanceWaitHandler(
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
"status": s.Status,
},
)
time.Sleep(10 * time.Second)
@ -185,17 +180,17 @@ func UpdateInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
return true, s, nil
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
@ -203,7 +198,7 @@ func UpdateInstanceWaitHandler(
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
"status": s.Status,
},
)
return false, s, nil
@ -226,10 +221,10 @@ func DeleteInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err == nil {
return false, s, nil
}
@ -253,10 +248,10 @@ func CreateDatabaseWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region, databaseName string,
) *wait.AsyncActionHandler[sqlserverflex.GetDatabaseResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetDatabaseResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetDatabaseResponse, err error) {
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
func() (waitFinished bool, response *v3alpha1api.GetDatabaseResponse, err error) {
s, err := a.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -271,7 +266,7 @@ func CreateDatabaseWaitHandler(
}
return false, nil, nil
}
if s == nil || s.Name == nil || *s.Name != databaseName {
if s == nil || s.Name != databaseName {
return false, nil, errors.New("response did return different result")
}
return true, s, nil
@ -286,10 +281,10 @@ func CreateUserWaitHandler(
a APIClientInterface,
projectId, instanceId, region string,
userId int64,
) *wait.AsyncActionHandler[sqlserverflex.GetUserResponse] {
) *wait.AsyncActionHandler[v3alpha1api.GetUserResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetUserResponse, err error) {
s, err := a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId)
func() (waitFinished bool, response *v3alpha1api.GetUserResponse, err error) {
s, err := a.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -312,12 +307,12 @@ func WaitForUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region, userName string,
) *wait.AsyncActionHandler[sqlserverflex.ListUserResponse] {
) *wait.AsyncActionHandler[v3alpha1api.ListUserResponse] {
startTime := time.Now()
timeOut := 2 * time.Minute
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.ListUserResponse, err error) {
func() (waitFinished bool, response *v3alpha1api.ListUserResponse, err error) {
if time.Since(startTime) > timeOut {
return false, nil, errors.New("ran into timeout")
}
@ -368,7 +363,7 @@ func DeleteUserWaitHandler(
) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(
func() (waitFinished bool, response *struct{}, err error) {
_, err = a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId)
_, err = a.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err == nil {
return false, nil, nil
}

View file

@ -9,137 +9,35 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexalpha"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
// Used for testing instance operations
type apiClientInstanceMocked struct {
instanceId string
instanceState string
instanceNetwork sqlserverflex.InstanceNetwork
instanceIsDeleted bool
instanceGetFails bool
}
type ListUsersRequestRequest struct{}
func (l ListUsersRequestRequest) Page(_ int64) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Size(_ int64) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Sort(_ sqlserverflex.UserSort) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Execute() (*sqlserverflex.ListUserResponse, error) {
// TODO implement me
panic("implement me")
}
func (a *apiClientInstanceMocked) ListUsersRequest(
_ context.Context,
_ string,
_ string,
_ string,
) sqlserverflex.ApiListUsersRequestRequest {
return ListUsersRequestRequest{}
}
func (a *apiClientInstanceMocked) ListRolesRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
) (*sqlserverflex.ListRolesResponse, error) {
return &sqlserverflex.ListRolesResponse{
Roles: &[]string{},
}, nil
}
func (a *apiClientInstanceMocked) ListUsersRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
) (*sqlserverflex.ListUserResponse, error) {
return &sqlserverflex.ListUserResponse{
Pagination: nil,
Users: nil,
}, nil
}
func (a *apiClientInstanceMocked) GetDatabaseRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
_ string,
) (*sqlserverflex.GetDatabaseResponse, error) {
return nil, nil
}
func (a *apiClientInstanceMocked) GetUserRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
_ int64,
) (*sqlserverflex.GetUserResponse, error) {
return nil, nil
}
func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
_ context.Context,
_, _, _ string,
) (*sqlserverflex.GetInstanceResponse, error) {
if a.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if a.instanceIsDeleted {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &sqlserverflex.GetInstanceResponse{
Id: &a.instanceId,
Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(&a.instanceState),
Network: &a.instanceNetwork,
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
instanceId := utils.Ptr("foo")
instanceID := utils.Ptr("foo")
tests := []struct {
desc string
instanceId string
instanceID string
instanceGetFails bool
instanceState string
instanceNetwork sqlserverflex.InstanceNetwork
instanceNetwork v3alpha1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *sqlserverflex.GetInstanceResponse
wantRes *v3alpha1api.GetInstanceResponse
}{
//{
// desc: "create_succeeded",
// instanceId: *instanceId,
// instanceGetFails: false,
// instanceState: *stateSuccess,
// instanceNetwork: sqlserverflex.InstanceNetwork{
// instanceNetwork: v3alpha1api.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
// RouterAddress: utils.Ptr("10.0.0.2"),
// },
// wantErr: false,
// wantRes: &sqlserverflex.GetInstanceResponse{
// wantRes: &v3alpha1api.GetInstanceResponse{
// BackupSchedule: nil,
// Edition: nil,
// Encryption: nil,
@ -147,7 +45,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
// Id: instanceId,
// IsDeletable: nil,
// Name: nil,
// Network: &sqlserverflex.InstanceNetwork{
// Network: &v3alpha1api.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
@ -155,14 +53,14 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
// },
// Replicas: nil,
// RetentionDays: nil,
// Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(stateSuccess),
// Status: v3alpha1api.GetInstanceResponseGetStatusAttributeType(stateSuccess),
// Storage: nil,
// Version: nil,
// },
// },
{
desc: "create_failed",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
@ -170,7 +68,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
{
desc: "create_failed_2",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
@ -178,14 +76,14 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
{
desc: "instance_get_fails",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: true,
wantErr: true,
wantRes: nil,
},
{
desc: "timeout",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
@ -195,13 +93,25 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
apiClient := &apiClientInstanceMocked{
instanceId: tt.instanceId,
instanceState: tt.instanceState,
instanceGetFails: tt.instanceGetFails,
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: tt.instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceId, "")
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
@ -217,7 +127,6 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
}
func TestUpdateInstanceWaitHandler(t *testing.T) {
t.Skip("skipping - needs refactoring")
tests := []struct {
desc string
instanceGetFails bool
@ -263,23 +172,35 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceId: instanceId,
instanceState: tt.instanceState,
instanceGetFails: tt.instanceGetFails,
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
var wantRes *sqlserverflex.GetInstanceResponse
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
var wantRes *v3alpha1api.GetInstanceResponse
if tt.wantResp {
wantRes = &sqlserverflex.GetInstanceResponse{
Id: &instanceId,
Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(tt.instanceState)),
wantRes = &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
}
}
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceId, "")
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
@ -322,16 +243,33 @@ func TestDeleteInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceGetFails: tt.instanceGetFails,
instanceIsDeleted: tt.instanceState == InstanceStateSuccess,
instanceId: instanceId,
instanceState: tt.instanceState,
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if tt.instanceState == InstanceStateSuccess {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceId, "")
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())

View file

@ -12,7 +12,7 @@ import (
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/wait"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
// READY, PENDING, PROGRESSING, FAILURE, UNKNOWN,
@ -28,31 +28,31 @@ const (
// APIClientInterface Interface needed for tests
type APIClientInterface interface {
GetInstanceRequestExecute(
GetInstanceRequest(
ctx context.Context,
projectId, region, instanceId string,
) (*sqlserverflex.GetInstanceResponse, error)
GetDatabaseRequestExecute(
) sqlserverflex.ApiGetInstanceRequestRequest
GetDatabaseRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
databaseName string,
) (*sqlserverflex.GetDatabaseResponse, error)
GetUserRequestExecute(
) sqlserverflex.ApiGetDatabaseRequestRequest
GetUserRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) (*sqlserverflex.GetUserResponse, error)
) sqlserverflex.ApiGetUserRequestRequest
ListRolesRequestExecute(
ListRolesRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) (*sqlserverflex.ListRolesResponse, error)
) sqlserverflex.ApiListRolesRequestRequest
ListUsersRequest(
ctx context.Context,
@ -60,13 +60,6 @@ type APIClientInterface interface {
region string,
instanceId string,
) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequestExecute(
ctx context.Context,
projectId string,
region string,
instanceId string,
) (*sqlserverflex.ListUserResponse, error)
}
// APIClientUserInterface Interface needed for tests
@ -88,7 +81,7 @@ func CreateInstanceWaitHandler(
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -102,12 +95,12 @@ func CreateInstanceWaitHandler(
return false, nil, fmt.Errorf("api error: %w", err)
}
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
if s.Network != nil && s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.AccessScope != nil && *s.Network.AccessScope == "SNA" {
if s.Network.InstanceAddress == nil {
tflog.Info(ctx, "Waiting for instance_address")
return false, nil, nil
@ -120,7 +113,7 @@ func CreateInstanceWaitHandler(
tflog.Info(ctx, "trying to get roles")
time.Sleep(10 * time.Second)
_, rolesErr := a.ListRolesRequestExecute(ctx, projectId, region, instanceId)
_, rolesErr := a.ListRolesRequest(ctx, projectId, region, instanceId).Execute()
if rolesErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(rolesErr, &oapiErr)
@ -144,7 +137,7 @@ func CreateInstanceWaitHandler(
tflog.Info(ctx, "trying to get users")
time.Sleep(10 * time.Second)
_, usersErr := a.ListUsersRequestExecute(ctx, projectId, region, instanceId)
_, usersErr := a.ListUsersRequest(ctx, projectId, region, instanceId).Execute()
if usersErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(usersErr, &oapiErr)
@ -181,7 +174,7 @@ func CreateInstanceWaitHandler(
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
"status": s.Status,
},
)
time.Sleep(10 * time.Second)
@ -208,14 +201,14 @@ func UpdateInstanceWaitHandler(
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
return true, s, nil
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
@ -223,7 +216,7 @@ func UpdateInstanceWaitHandler(
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
"status": s.Status,
},
)
return false, s, nil
@ -249,7 +242,7 @@ func DeleteInstanceWaitHandler(
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err == nil {
return false, s, nil
}
@ -276,7 +269,7 @@ func CreateDatabaseWaitHandler(
) *wait.AsyncActionHandler[sqlserverflex.GetDatabaseResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetDatabaseResponse, err error) {
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
s, err := a.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -291,7 +284,7 @@ func CreateDatabaseWaitHandler(
}
return false, nil, nil
}
if s == nil || s.Name == nil || *s.Name != databaseName {
if s == nil || s.Name != databaseName {
return false, nil, errors.New("response did return different result")
}
return true, s, nil
@ -309,7 +302,7 @@ func CreateUserWaitHandler(
) *wait.AsyncActionHandler[sqlserverflex.GetUserResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetUserResponse, err error) {
s, err := a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId)
s, err := a.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
@ -388,7 +381,7 @@ func DeleteUserWaitHandler(
) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(
func() (waitFinished bool, response *struct{}, err error) {
_, err = a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId)
_, err = a.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
if err == nil {
return false, nil, nil
}

View file

@ -9,160 +9,57 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
// Used for testing instance operations
type apiClientInstanceMocked struct {
instanceId string
instanceState string
instanceNetwork sqlserverflex.InstanceNetwork
instanceIsDeleted bool
instanceGetFails bool
}
type ListUsersRequestRequest struct{}
func (l ListUsersRequestRequest) Page(_ int64) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Size(_ int64) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Sort(_ sqlserverflex.UserSort) sqlserverflex.ApiListUsersRequestRequest {
return l
}
func (l ListUsersRequestRequest) Execute() (*sqlserverflex.ListUserResponse, error) {
// TODO implement me
panic("implement me")
}
func (a *apiClientInstanceMocked) ListUsersRequest(
_ context.Context,
_ string,
_ string,
_ string,
) sqlserverflex.ApiListUsersRequestRequest {
return ListUsersRequestRequest{}
}
func (a *apiClientInstanceMocked) ListRolesRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
) (*sqlserverflex.ListRolesResponse, error) {
return &sqlserverflex.ListRolesResponse{
Roles: &[]string{},
}, nil
}
func (a *apiClientInstanceMocked) ListUsersRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
) (*sqlserverflex.ListUserResponse, error) {
return &sqlserverflex.ListUserResponse{
Pagination: nil,
Users: nil,
}, nil
}
func (a *apiClientInstanceMocked) GetDatabaseRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
_ string,
) (*sqlserverflex.GetDatabaseResponse, error) {
return nil, nil
}
func (a *apiClientInstanceMocked) GetUserRequestExecute(
_ context.Context,
_ string,
_ string,
_ string,
_ int64,
) (*sqlserverflex.GetUserResponse, error) {
return nil, nil
}
func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
_ context.Context,
_, _, _ string,
) (*sqlserverflex.GetInstanceResponse, error) {
if a.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if a.instanceIsDeleted {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &sqlserverflex.GetInstanceResponse{
Id: &a.instanceId,
Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(&a.instanceState),
Network: &a.instanceNetwork,
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
instanceId := utils.Ptr("foo")
instanceID := utils.Ptr("foo")
tests := []struct {
desc string
instanceId string
instanceID string
instanceGetFails bool
instanceState string
instanceNetwork sqlserverflex.InstanceNetwork
instanceNetwork v3beta1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *sqlserverflex.GetInstanceResponse
wantRes *v3beta1api.GetInstanceResponse
}{
//{
// desc: "create_succeeded",
// instanceId: *instanceId,
// instanceGetFails: false,
// instanceState: *stateSuccess,
// instanceNetwork: sqlserverflex.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
// RouterAddress: utils.Ptr("10.0.0.2"),
// },
// wantErr: false,
// wantRes: &sqlserverflex.GetInstanceResponse{
// BackupSchedule: nil,
// Edition: nil,
// Encryption: nil,
// FlavorId: nil,
// Id: instanceId,
// IsDeletable: nil,
// Name: nil,
// Network: &sqlserverflex.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
// RouterAddress: utils.Ptr("10.0.0.2"),
// },
// Replicas: nil,
// RetentionDays: nil,
// Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(stateSuccess),
// Storage: nil,
// Version: nil,
// },
// },
{
desc: "create_succeeded_default_values",
instanceID: "instance1",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: v3beta1api.InstanceNetwork{
AccessScope: (*v3beta1api.InstanceNetworkAccessScope)(utils.Ptr("PUBLIC")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.2"),
},
wantErr: false,
wantRes: &v3beta1api.GetInstanceResponse{
BackupSchedule: "",
Edition: "",
Encryption: nil,
FlavorId: "",
Id: "instance1",
IsDeletable: false,
Name: "",
Network: v3beta1api.InstanceNetwork{
AccessScope: (*v3beta1api.InstanceNetworkAccessScope)(utils.Ptr("PUBLIC")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.2"),
},
Replicas: 0,
RetentionDays: 0,
Status: v3beta1api.Status(InstanceStateSuccess),
Storage: v3beta1api.Storage{},
Version: "",
},
},
{
desc: "create_failed",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
@ -170,7 +67,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
{
desc: "create_failed_2",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
@ -178,14 +75,14 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
{
desc: "instance_get_fails",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: true,
wantErr: true,
wantRes: nil,
},
{
desc: "timeout",
instanceId: *instanceId,
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
@ -195,19 +92,55 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
apiClient := &apiClientInstanceMocked{
instanceId: tt.instanceId,
instanceState: tt.instanceState,
instanceGetFails: tt.instanceGetFails,
listRolesMock := func(_ v3beta1api.ApiListRolesRequestRequest) (*v3beta1api.ListRolesResponse, error) {
return &v3beta1api.ListRolesResponse{
Roles: []string{},
}, nil
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceId, "")
listUsersMock := func(_ v3beta1api.ApiListUsersRequestRequest) (*v3beta1api.ListUserResponse, error) {
aux := int64(0)
return &v3beta1api.ListUserResponse{
Pagination: v3beta1api.Pagination{
TotalRows: aux,
},
Users: []v3beta1api.ListUser{},
}, nil
}
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3beta1api.GetInstanceResponse{
Id: tt.instanceID,
Status: v3beta1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
Storage: v3beta1api.Storage{},
}, nil
}
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
ListUsersRequestExecuteMock: &listUsersMock,
ListRolesRequestExecuteMock: &listRolesMock,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
if err == nil {
if diff := cmp.Diff(tt.wantRes, gotRes); diff != "" {
t.Errorf("model mismatch (-want +got):\n%s", diff)
}
}
if !reflect.DeepEqual(gotRes, tt.wantRes) {
t.Fatalf("handler gotRes = %v, want %v", gotRes, tt.wantRes)
}
@ -217,7 +150,6 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
}
func TestUpdateInstanceWaitHandler(t *testing.T) {
t.Skip("skipping - needs refactoring")
tests := []struct {
desc string
instanceGetFails bool
@ -263,23 +195,35 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceId: instanceId,
instanceState: tt.instanceState,
instanceGetFails: tt.instanceGetFails,
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
var wantRes *sqlserverflex.GetInstanceResponse
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
var wantRes *v3beta1api.GetInstanceResponse
if tt.wantResp {
wantRes = &sqlserverflex.GetInstanceResponse{
Id: &instanceId,
Status: sqlserverflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr(tt.instanceState)),
wantRes = &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
}
}
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceId, "")
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
@ -322,16 +266,33 @@ func TestDeleteInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceGetFails: tt.instanceGetFails,
instanceIsDeleted: tt.instanceState == InstanceStateSuccess,
instanceId: instanceId,
instanceState: tt.instanceState,
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if tt.instanceState == InstanceStateSuccess {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceId, "")
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())

View file

@ -6,7 +6,6 @@ import (
"context"
"fmt"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
@ -21,6 +20,11 @@ import (
sdkauth "github.com/stackitcloud/stackit-sdk-go/core/auth"
"github.com/stackitcloud/stackit-sdk-go/core/config"
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
sqlserverflexalphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
sqlserverflexalphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
sqlserverflexbetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/features"
@ -30,15 +34,9 @@ import (
postgresFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
postgresFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user"
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
sqlserverFlexAlphaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavor"
sqlServerFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
sqlserverFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
sqlserverflexBetaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database"
sqlserverFlexBetaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavor"
sqlserverFlexBetaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database"
sqlserverflexBetaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance"
sqlserverFlexBetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
// sqlserverFlexBetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbetaUser/user"
)
// Ensure the implementation satisfies the expected interfaces
@ -46,7 +44,10 @@ var (
_ provider.Provider = &Provider{}
)
const providerConfigError = "Error configuring provider"
//nolint:unused // These constants are defined for future use in retry logic for HTTP requests, which is not yet implemented.
/*
const (
// maxRetries is the maximum number of retries for a failed HTTP request.
maxRetries = 3
@ -57,6 +58,7 @@ const (
// perTryTimeout is the timeout for each individual HTTP request attempt.
perTryTimeout = 30 * time.Second
)
*/
// Provider is the provider implementation.
type Provider struct {
@ -92,7 +94,7 @@ type providerModel struct {
// Custom endpoints
AuthorizationCustomEndpoint types.String `tfsdk:"authorization_custom_endpoint"`
CdnCustomEndpoint types.String `tfsdk:"cdn_custom_endpoint"`
DnsCustomEndpoint types.String `tfsdk:"dns_custom_endpoint"`
DNSCustomEndpoint types.String `tfsdk:"dns_custom_endpoint"`
GitCustomEndpoint types.String `tfsdk:"git_custom_endpoint"`
IaaSCustomEndpoint types.String `tfsdk:"iaas_custom_endpoint"`
KmsCustomEndpoint types.String `tfsdk:"kms_custom_endpoint"`
@ -370,7 +372,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"Error configuring provider",
providerConfigError,
fmt.Sprintf("Setting up bool value: %v", diags.Errors()),
)
}
@ -389,7 +391,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
setStringField(providerConfig.DefaultRegion, func(v string) { providerData.DefaultRegion = v })
setStringField(
providerConfig.Region,
providerConfig.Region, // nolint:staticcheck // preliminary handling of deprecated attribute
func(v string) { providerData.Region = v }, // nolint:staticcheck // preliminary handling of deprecated attribute
)
setBoolField(providerConfig.EnableBetaResources, func(v bool) { providerData.EnableBetaResources = v })
@ -399,7 +401,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
func(v string) { providerData.AuthorizationCustomEndpoint = v },
)
setStringField(providerConfig.CdnCustomEndpoint, func(v string) { providerData.CdnCustomEndpoint = v })
setStringField(providerConfig.DnsCustomEndpoint, func(v string) { providerData.DnsCustomEndpoint = v })
setStringField(providerConfig.DNSCustomEndpoint, func(v string) { providerData.DnsCustomEndpoint = v })
setStringField(providerConfig.GitCustomEndpoint, func(v string) { providerData.GitCustomEndpoint = v })
setStringField(providerConfig.IaaSCustomEndpoint, func(v string) { providerData.IaaSCustomEndpoint = v })
setStringField(providerConfig.KmsCustomEndpoint, func(v string) { providerData.KMSCustomEndpoint = v })
@ -473,7 +475,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"Error configuring provider",
providerConfigError,
fmt.Sprintf("Setting up experiments: %v", diags.Errors()),
)
}
@ -485,7 +487,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"Error configuring provider",
providerConfigError,
fmt.Sprintf("Setting up authentication: %v", err),
)
return
@ -533,15 +535,15 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
postgresFlexAlphaUser.NewUserDataSource,
postgresflexalphaFlavors.NewFlavorsDataSource,
sqlserverFlexAlphaFlavor.NewFlavorDataSource,
sqlServerFlexAlphaInstance.NewInstanceDataSource,
sqlserverFlexAlphaUser.NewUserDataSource,
// sqlserverFlexAlphaFlavor.NewFlavorDataSource,
sqlserverflexalphaInstance.NewInstanceDataSource,
sqlserverflexalphaUser.NewUserDataSource,
sqlserverflexalphaDatabase.NewDatabaseDataSource,
sqlserverflexBetaDatabase.NewDatabaseDataSource,
sqlserverFlexBetaDatabase.NewDatabaseDataSource,
sqlserverflexBetaInstance.NewInstanceDataSource,
sqlserverFlexBetaUser.NewUserDataSource,
sqlserverFlexBetaFlavor.NewFlavorDataSource,
sqlserverflexbetaUser.NewUserDataSource,
// sqlserverFlexBetaFlavor.NewFlavorDataSource,
}
}
@ -552,13 +554,13 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
postgresFlexAlphaUser.NewUserResource,
postgresFlexAlphaDatabase.NewDatabaseResource,
sqlServerFlexAlphaInstance.NewInstanceResource,
sqlserverFlexAlphaUser.NewUserResource,
sqlserverflexalphaInstance.NewInstanceResource,
sqlserverflexalphaUser.NewUserResource,
sqlserverflexalphaDatabase.NewDatabaseResource,
sqlserverflexBetaInstance.NewInstanceResource,
sqlserverFlexBetaUser.NewUserResource,
sqlserverflexBetaDatabase.NewDatabaseResource,
sqlserverflexbetaUser.NewUserResource,
sqlserverFlexBetaDatabase.NewDatabaseResource,
}
return resources
}

View file

@ -3,22 +3,16 @@ package stackit_test
import (
"context"
_ "embed"
"fmt"
"net/http"
"os"
"reflect"
"regexp"
"testing"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/google/go-cmp/cmp"
test "github.com/hashicorp/terraform-plugin-testing/helper/resource" //nolint:staticcheck // used for acceptance testing
"github.com/jarcoal/httpmock"
"github.com/stackitcloud/stackit-sdk-go/core/clients"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
//nolint:staticcheck // used for acceptance testing
postgresFlexAlphaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor"
"github.com/hashicorp/terraform-plugin-framework/datasource"
@ -29,12 +23,9 @@ import (
postgresflexalphaFlavors "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavors"
postgresFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
postgresFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user"
sqlserverflexalphaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
sqlserverFlexAlphaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavor"
sqlserverFlexAlphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
sqlserverFlexAlphaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
sqlserverflexBetaDatabase "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/database"
sqlserverFlexBetaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavor"
sqlserverFlexBetaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance"
sqlserverFlexBetaUser "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user"
@ -62,106 +53,6 @@ func TestMain(m *testing.M) {
os.Exit(code)
}
func TestMshTest(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
testutils.ActivateEnvironmentHttpMocks()
httpmock.RegisterResponder(
"POST", `https://service-account.api.stackit.cloud/token`,
func(_ *http.Request) (*http.Response, error) {
token := jwt.NewWithClaims(
jwt.SigningMethodHS256, jwt.MapClaims{
"foo": "bar",
"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
},
)
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte("mySecret"))
if err != nil {
panic(err)
}
tR := clients.TokenResponseBody{
AccessToken: tokenString,
ExpiresIn: 3600,
RefreshToken: "",
Scope: "",
TokenType: "",
}
return httpmock.NewJsonResponse(http.StatusOK, tR)
},
)
httpmock.RegisterResponder(
"GET",
`https://postgres-flex-service.api.eu01.stackit.cloud/v3alpha1/projects/xyz-project-id/regions/eu01/flavors?page=1&size=25&sort=id.asc`,
func(_ *http.Request) (*http.Response, error) {
res := postgresflexalpha.GetFlavorsResponse{
Flavors: &[]postgresflexalpha.ListFlavors{
{
Cpu: nil,
Description: nil,
Id: nil,
MaxGB: nil,
Memory: nil,
MinGB: nil,
NodeType: nil,
StorageClasses: nil,
},
},
Pagination: &postgresflexalpha.Pagination{
Page: utils.Ptr(int64(1)),
Size: utils.Ptr(int64(25)),
Sort: nil,
TotalPages: utils.Ptr(int64(1)),
TotalRows: utils.Ptr(int64(0)),
},
}
return httpmock.NewJsonResponse(
http.StatusOK,
res,
)
},
)
test.Test(
t, test.TestCase{
IsUnitTest: true,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []test.TestStep{
{
ConfigVariables: map[string]config.Variable{
"project_id": config.StringVariable("xyz-project-id"),
},
Config: fmt.Sprintf(
`
provider "stackitprivatepreview" {
default_region = "%[1]s"
service_account_key_path = "%[2]s"
}
variable "project_id" {
type = string
}
data "stackitprivatepreview_postgresflexalpha_flavor" "all" {
project_id = var.project_id
region = "eu01"
cpu = 2
ram = 4
node_type = "Single"
storage_class = "premium-perf2-stackit"
}`,
os.Getenv("TF_ACC_REGION"),
os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
),
},
},
},
)
}
func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
expectedDataSources := []datasource.DataSource{
postgresFlexAlphaFlavor.NewFlavorDataSource(),
@ -171,7 +62,7 @@ func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
postgresFlexAlphaUser.NewUserDataSource(),
postgresflexalphaFlavors.NewFlavorsDataSource(),
sqlserverFlexAlphaFlavor.NewFlavorDataSource(),
// sqlserverFlexAlphaFlavor.NewFlavorDataSource(),
sqlserverFlexAlphaInstance.NewInstanceDataSource(),
sqlserverFlexAlphaUser.NewUserDataSource(),
sqlserverflexalphaDatabase.NewDatabaseDataSource(),
@ -179,7 +70,7 @@ func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
sqlserverflexBetaDatabase.NewDatabaseDataSource(),
sqlserverFlexBetaInstance.NewInstanceDataSource(),
sqlserverFlexBetaUser.NewUserDataSource(),
sqlserverFlexBetaFlavor.NewFlavorDataSource(),
// sqlserverFlexBetaFlavor.NewFlavorDataSource(),
}
provider, ok := stackit.New("testing")().(*stackit.Provider)
if !ok {