From 25fb4453f0bd435e65c1814728c57ee2203069fa Mon Sep 17 00:00:00 2001 From: "Marcel S. Henselin" Date: Tue, 23 Dec 2025 11:38:05 +0100 Subject: [PATCH] Feat/alpa postgres database (#15) * chore: implement datasource * chore: register datasource --------- Co-authored-by: Andre Harms --- .../{datasource.go.bak => datasource.go} | 36 ++- .../database/{resource.go.bak => resource.go} | 211 ++++++++++++------ ...{resource_test.go.bak => resource_test.go} | 119 +++++----- stackit/provider.go | 6 +- 4 files changed, 231 insertions(+), 141 deletions(-) rename stackit/internal/services/postgresflexalpha/database/{datasource.go.bak => datasource.go} (86%) rename stackit/internal/services/postgresflexalpha/database/{resource.go.bak => resource.go} (74%) rename stackit/internal/services/postgresflexalpha/database/{resource_test.go.bak => resource_test.go} (55%) diff --git a/stackit/internal/services/postgresflexalpha/database/datasource.go.bak b/stackit/internal/services/postgresflexalpha/database/datasource.go similarity index 86% rename from stackit/internal/services/postgresflexalpha/database/datasource.go.bak rename to stackit/internal/services/postgresflexalpha/database/datasource.go index 2e41a98e..e1180c0f 100644 --- a/stackit/internal/services/postgresflexalpha/database/datasource.go.bak +++ b/stackit/internal/services/postgresflexalpha/database/datasource.go @@ -1,4 +1,4 @@ -package postgresflexa +package postgresflexalpha import ( "context" @@ -36,12 +36,20 @@ type databaseDataSource struct { } // Metadata returns the data source type name. -func (r *databaseDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { +func (r *databaseDataSource) Metadata( + _ context.Context, + req datasource.MetadataRequest, + resp *datasource.MetadataResponse, +) { resp.TypeName = req.ProviderTypeName + "_postgresflexalpha_database" } // Configure adds the provider configured client to the data source. -func (r *databaseDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { +func (r *databaseDataSource) Configure( + ctx context.Context, + req datasource.ConfigureRequest, + resp *datasource.ConfigureResponse, +) { var ok bool r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics) if !ok { @@ -117,7 +125,11 @@ func (r *databaseDataSource) Schema(_ context.Context, _ datasource.SchemaReques } // Read refreshes the Terraform state with the latest data. -func (r *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseDataSource) Read( + ctx context.Context, + req datasource.ReadRequest, + resp *datasource.ReadResponse, +) { // nolint:gocritic // function signature required by Terraform var model Model diags := req.Config.Get(ctx, &model) resp.Diagnostics.Append(diags...) @@ -129,7 +141,7 @@ func (r *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques projectId := model.ProjectId.ValueString() instanceId := model.InstanceId.ValueString() - databaseId := model.DatabaseId.ValueString() + databaseId := model.DatabaseId.ValueInt64() region := r.providerData.GetRegionWithOverride(model.Region) ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "instance_id", instanceId) @@ -143,7 +155,12 @@ func (r *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques &resp.Diagnostics, err, "Reading database", - fmt.Sprintf("Database with ID %q or instance with ID %q does not exist in project %q.", databaseId, instanceId, projectId), + fmt.Sprintf( + "Database with ID %q or instance with ID %q does not exist in project %q.", + databaseId, + instanceId, + projectId, + ), map[int]string{ http.StatusForbidden: fmt.Sprintf("Project with ID %q not found or forbidden access", projectId), }, @@ -157,7 +174,12 @@ func (r *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques // Map response body to schema and populate Computed attribute values err = mapFields(databaseResp, &model, region) if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Processing API payload: %v", err)) + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error reading database", + fmt.Sprintf("Processing API payload: %v", err), + ) return } diff --git a/stackit/internal/services/postgresflexalpha/database/resource.go.bak b/stackit/internal/services/postgresflexalpha/database/resource.go similarity index 74% rename from stackit/internal/services/postgresflexalpha/database/resource.go.bak rename to stackit/internal/services/postgresflexalpha/database/resource.go index 23279b4f..01fd8799 100644 --- a/stackit/internal/services/postgresflexalpha/database/resource.go.bak +++ b/stackit/internal/services/postgresflexalpha/database/resource.go @@ -1,29 +1,27 @@ -package postgresflexa +package postgresflexalpha import ( "context" "errors" "fmt" "net/http" + "strconv" "strings" - "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" - "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha" - "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/conversion" - postgresflexUtils "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils" - - "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/core" - "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/utils" - "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/validate" - "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/conversion" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/core" + postgresflexUtils "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/utils" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/validate" "github.com/stackitcloud/stackit-sdk-go/core/oapierror" ) @@ -36,21 +34,13 @@ var ( ) type Model struct { - Id types.String `tfsdk:"id"` // needed by TF - DatabaseId types.String `tfsdk:"database_id"` - InstanceId types.String `tfsdk:"instance_id"` - ProjectId types.String `tfsdk:"project_id"` - Name types.String `tfsdk:"name"` - Owner types.String `tfsdk:"owner"` - Region types.String `tfsdk:"region"` - Encryption encryptionModel `tfsdk:"encryption"` -} - -type encryptionModel struct { - KeyId types.String `tfsdk:"key_id"` - //keyringid = xxxx - //keyversion = xxxx - //serviceaccount = xxxx + Id types.String `tfsdk:"id"` // needed by TF + DatabaseId types.Int64 `tfsdk:"database_id"` + InstanceId types.String `tfsdk:"instance_id"` + ProjectId types.String `tfsdk:"project_id"` + Name types.String `tfsdk:"name"` + Owner types.String `tfsdk:"owner"` + Region types.String `tfsdk:"region"` } // NewDatabaseResource is a helper function to simplify the provider implementation. @@ -66,7 +56,11 @@ type databaseResource struct { // ModifyPlan implements resource.ResourceWithModifyPlan. // Use the modifier to set the effective region in the current plan. -func (r *databaseResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseResource) ModifyPlan( + ctx context.Context, + req resource.ModifyPlanRequest, + resp *resource.ModifyPlanResponse, +) { // nolint:gocritic // function signature required by Terraform var configModel Model // skip initial empty configuration to avoid follow-up errors if req.Config.Raw.IsNull() { @@ -100,7 +94,11 @@ func (r *databaseResource) Metadata(_ context.Context, req resource.MetadataRequ } // Configure adds the provider configured client to the resource. -func (r *databaseResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +func (r *databaseResource) Configure( + ctx context.Context, + req resource.ConfigureRequest, + resp *resource.ConfigureResponse, +) { var ok bool r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics) if !ok { @@ -200,7 +198,11 @@ func (r *databaseResource) Schema(_ context.Context, _ resource.SchemaRequest, r } // Create creates the resource and sets the initial Terraform state. -func (r *databaseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseResource) Create( + ctx context.Context, + req resource.CreateRequest, + resp *resource.CreateResponse, +) { // nolint:gocritic // function signature required by Terraform var model Model diags := req.Plan.Get(ctx, &model) resp.Diagnostics.Append(diags...) @@ -220,11 +222,21 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques // Generate API request body from model payload, err := toCreatePayload(&model) if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating database", fmt.Sprintf("Creating API payload: %v", err)) + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error creating database", + fmt.Sprintf("Creating API payload: %v", err), + ) return } // Create new database - databaseResp, err := r.client.CreateDatabaseRequest(ctx, projectId, region, instanceId).CreateDatabaseRequestPayload(*payload).Execute() + databaseResp, err := r.client.CreateDatabaseRequest( + ctx, + projectId, + region, + instanceId, + ).CreateDatabaseRequestPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating database", fmt.Sprintf("Calling API: %v", err)) return @@ -232,8 +244,13 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques ctx = core.LogResponse(ctx) - if databaseResp == nil || databaseResp.Id == nil || *databaseResp.Id == "" { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating database", "API didn't return database Id. A database might have been created") + if databaseResp == nil || databaseResp.Id == nil { + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error creating database", + "API didn't return database Id. A database might have been created", + ) return } databaseId := *databaseResp.Id @@ -241,14 +258,24 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques database, err := getDatabase(ctx, r.client, projectId, region, instanceId, databaseId) if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating database", fmt.Sprintf("Getting database details after creation: %v", err)) + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error creating database", + fmt.Sprintf("Getting database details after creation: %v", err), + ) return } // Map response body to schema err = mapFields(database, &model, region) if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating database", fmt.Sprintf("Processing API payload: %v", err)) + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error creating database", + fmt.Sprintf("Processing API payload: %v", err), + ) return } // Set state to fully populated data @@ -261,7 +288,11 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques } // Read refreshes the Terraform state with the latest data. -func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseResource) Read( + ctx context.Context, + req resource.ReadRequest, + resp *resource.ReadResponse, +) { // nolint:gocritic // function signature required by Terraform var model Model diags := req.State.Get(ctx, &model) resp.Diagnostics.Append(diags...) @@ -273,7 +304,7 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r projectId := model.ProjectId.ValueString() instanceId := model.InstanceId.ValueString() - databaseId := model.DatabaseId.ValueString() + databaseId := model.DatabaseId.ValueInt64() region := r.providerData.GetRegionWithOverride(model.Region) ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "instance_id", instanceId) @@ -296,7 +327,12 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r // Map response body to schema err = mapFields(databaseResp, &model, region) if err != nil { - core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Processing API payload: %v", err)) + core.LogAndAddError( + ctx, + &resp.Diagnostics, + "Error reading database", + fmt.Sprintf("Processing API payload: %v", err), + ) return } @@ -310,13 +346,21 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r } // Update updates the resource and sets the updated Terraform state on success. -func (r *databaseResource) Update(ctx context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseResource) Update( + ctx context.Context, + _ resource.UpdateRequest, + resp *resource.UpdateResponse, +) { // nolint:gocritic // function signature required by Terraform // Update shouldn't be called core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating database", "Database can't be updated") } // Delete deletes the resource and removes the Terraform state on success. -func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // nolint:gocritic // function signature required by Terraform +func (r *databaseResource) Delete( + ctx context.Context, + req resource.DeleteRequest, + resp *resource.DeleteResponse, +) { // nolint:gocritic // function signature required by Terraform // Retrieve values from plan var model Model diags := req.State.Get(ctx, &model) @@ -329,7 +373,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques projectId := model.ProjectId.ValueString() instanceId := model.InstanceId.ValueString() - databaseId := model.DatabaseId.ValueString() + databaseId := model.DatabaseId.ValueInt64() region := model.Region.ValueString() ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "instance_id", instanceId) @@ -337,7 +381,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques ctx = tflog.SetField(ctx, "region", region) // Delete existing record set - err := r.client.DeleteDatabase(ctx, projectId, region, instanceId, databaseId).Execute() + err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseId) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting database", fmt.Sprintf("Calling API: %v", err)) } @@ -349,12 +393,20 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques // ImportState imports a resource into the Terraform state on success. // The expected format of the resource import identifier is: project_id,zone_id,record_set_id -func (r *databaseResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { +func (r *databaseResource) ImportState( + ctx context.Context, + req resource.ImportStateRequest, + resp *resource.ImportStateResponse, +) { idParts := strings.Split(req.ID, core.Separator) if len(idParts) != 4 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" || idParts[3] == "" { - core.LogAndAddError(ctx, &resp.Diagnostics, + core.LogAndAddError( + ctx, &resp.Diagnostics, "Error importing database", - fmt.Sprintf("Expected import identifier with format [project_id],[region],[instance_id],[database_id], got %q", req.ID), + fmt.Sprintf( + "Expected import identifier with format [project_id],[region],[instance_id],[database_id], got %q", + req.ID, + ), ) return } @@ -363,75 +415,88 @@ func (r *databaseResource) ImportState(ctx context.Context, req resource.ImportS 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("database_id"), idParts[3])...) - core.LogAndAddWarning(ctx, &resp.Diagnostics, + core.LogAndAddWarning( + ctx, + &resp.Diagnostics, "Postgresflex database imported with empty password", "The database password is not imported as it is only available upon creation of a new database. The password field will be empty.", ) tflog.Info(ctx, "Postgres Flex database state imported") } -func mapFields(databaseResp *postgresflex.InstanceDatabase, model *Model, region string) error { +func mapFields(databaseResp *postgresflexalpha.ListDatabase, model *Model, region string) error { if databaseResp == nil { return fmt.Errorf("response is nil") } - if databaseResp.Id == nil || *databaseResp.Id == "" { + if databaseResp.Id == nil || *databaseResp.Id == 0 { return fmt.Errorf("id not present") } if model == nil { return fmt.Errorf("model input is nil") } - var databaseId string - if model.DatabaseId.ValueString() != "" { - databaseId = model.DatabaseId.ValueString() + var databaseId int64 + if model.DatabaseId.ValueInt64() != 0 { + databaseId = model.DatabaseId.ValueInt64() } else if databaseResp.Id != nil { databaseId = *databaseResp.Id } else { return fmt.Errorf("database id not present") } model.Id = utils.BuildInternalTerraformId( - model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), databaseId, + model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(databaseId, 10), ) - model.DatabaseId = types.StringValue(databaseId) + model.DatabaseId = types.Int64Value(databaseId) model.Name = types.StringPointerValue(databaseResp.Name) model.Region = types.StringValue(region) - if databaseResp.Options != nil { - owner, ok := (*databaseResp.Options)["owner"] - if ok { - ownerStr, ok := owner.(string) - if !ok { - return fmt.Errorf("owner is not a string") - } - // If the field is returned between with quotes, we trim them to prevent an inconsistent result after apply - ownerStr = strings.TrimPrefix(ownerStr, `"`) - ownerStr = strings.TrimSuffix(ownerStr, `"`) - model.Owner = types.StringValue(ownerStr) - } + ownerStr, err := mapOwner(databaseResp) + if err != nil { + return fmt.Errorf("error mapping owner: %v", err) } + model.Owner = types.StringPointerValue(ownerStr) return nil } +func mapOwner(databaseResp *postgresflexalpha.ListDatabase) (*string, error) { + if databaseResp == nil { + return nil, fmt.Errorf("response is nil") + } + + if databaseResp.Owner == nil { + return nil, nil + } + ownerStr := *databaseResp.Owner + + // If the field is returned between with quotes, we trim them to prevent an inconsistent result after apply + ownerStr = strings.TrimPrefix(ownerStr, `"`) + ownerStr = strings.TrimSuffix(ownerStr, `"`) + + return &ownerStr, nil +} + func toCreatePayload(model *Model) (*postgresflexalpha.CreateDatabaseRequestPayload, error) { if model == nil { return nil, fmt.Errorf("nil model") } return &postgresflexalpha.CreateDatabaseRequestPayload{ - Name: model.Name.ValueStringPointer(), - // TODO - //Options: &map[string]string{ - // "owner": model.Owner.ValueString(), - //}, + Name: model.Name.ValueStringPointer(), + Owner: model.Owner.ValueStringPointer(), }, nil } var databaseNotFoundErr = errors.New("database not found") // The API does not have a GetDatabase endpoint, only ListDatabases -func getDatabase(ctx context.Context, client *postgresflexalpha.APIClient, projectId, region, instanceId, databaseId string) (*postgresflex.InstanceDatabase, error) { - resp, err := client.ListDatabasesRequest(ctx, projectId, region, instanceId).Execute() +func getDatabase( + ctx context.Context, + client *postgresflexalpha.APIClient, + projectId, region, instanceId string, + databaseId int64, +) (*postgresflexalpha.ListDatabase, error) { + resp, err := client.ListDatabasesRequestExecute(ctx, projectId, region, instanceId) if err != nil { return nil, err } diff --git a/stackit/internal/services/postgresflexalpha/database/resource_test.go.bak b/stackit/internal/services/postgresflexalpha/database/resource_test.go similarity index 55% rename from stackit/internal/services/postgresflexalpha/database/resource_test.go.bak rename to stackit/internal/services/postgresflexalpha/database/resource_test.go index 9aed9f99..6602ffe6 100644 --- a/stackit/internal/services/postgresflexalpha/database/resource_test.go.bak +++ b/stackit/internal/services/postgresflexalpha/database/resource_test.go @@ -5,6 +5,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha" "github.com/stackitcloud/stackit-sdk-go/core/utils" "github.com/stackitcloud/stackit-sdk-go/services/postgresflex" ) @@ -13,20 +14,20 @@ func TestMapFields(t *testing.T) { const testRegion = "region" tests := []struct { description string - input *postgresflex.InstanceDatabase + input *postgresflexalpha.ListDatabase region string expected Model isValid bool }{ { "default_values", - &postgresflex.InstanceDatabase{ - Id: utils.Ptr("uid"), + &postgresflexalpha.ListDatabase{ + Id: utils.Ptr(int64(1)), }, testRegion, Model{ - Id: types.StringValue("pid,region,iid,uid"), - DatabaseId: types.StringValue("uid"), + Id: types.StringValue("pid,region,iid,1"), + DatabaseId: types.Int64Value(int64(1)), InstanceId: types.StringValue("iid"), ProjectId: types.StringValue("pid"), Name: types.StringNull(), @@ -37,17 +38,15 @@ func TestMapFields(t *testing.T) { }, { "simple_values", - &postgresflex.InstanceDatabase{ - Id: utils.Ptr("uid"), - Name: utils.Ptr("dbname"), - Options: &map[string]interface{}{ - "owner": "username", - }, + &postgresflexalpha.ListDatabase{ + Id: utils.Ptr(int64(1)), + Name: utils.Ptr("dbname"), + Owner: utils.Ptr("username"), }, testRegion, Model{ - Id: types.StringValue("pid,region,iid,uid"), - DatabaseId: types.StringValue("uid"), + Id: types.StringValue("pid,region,iid,1"), + DatabaseId: types.Int64Value(int64(1)), InstanceId: types.StringValue("iid"), ProjectId: types.StringValue("pid"), Name: types.StringValue("dbname"), @@ -58,17 +57,15 @@ func TestMapFields(t *testing.T) { }, { "null_fields_and_int_conversions", - &postgresflex.InstanceDatabase{ - Id: utils.Ptr("uid"), - Name: utils.Ptr(""), - Options: &map[string]interface{}{ - "owner": "", - }, + &postgresflexalpha.ListDatabase{ + Id: utils.Ptr(int64(1)), + Name: utils.Ptr(""), + Owner: utils.Ptr(""), }, testRegion, Model{ - Id: types.StringValue("pid,region,iid,uid"), - DatabaseId: types.StringValue("uid"), + Id: types.StringValue("pid,region,iid,1"), + DatabaseId: types.Int64Value(int64(1)), InstanceId: types.StringValue("iid"), ProjectId: types.StringValue("pid"), Name: types.StringValue(""), @@ -86,19 +83,17 @@ func TestMapFields(t *testing.T) { }, { "empty_response", - &postgresflex.InstanceDatabase{}, + &postgresflexalpha.ListDatabase{}, testRegion, Model{}, false, }, { "no_resource_id", - &postgresflex.InstanceDatabase{ - Id: utils.Ptr(""), - Name: utils.Ptr("dbname"), - Options: &map[string]interface{}{ - "owner": "username", - }, + &postgresflexalpha.ListDatabase{ + Id: utils.Ptr(int64(0)), + Name: utils.Ptr("dbname"), + Owner: utils.Ptr("username"), }, testRegion, Model{}, @@ -106,25 +101,27 @@ func TestMapFields(t *testing.T) { }, } for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - state := &Model{ - ProjectId: tt.expected.ProjectId, - InstanceId: tt.expected.InstanceId, - } - err := mapFields(tt.input, state, tt.region) - if !tt.isValid && err == nil { - t.Fatalf("Should have failed") - } - if tt.isValid && err != nil { - t.Fatalf("Should not have failed: %v", err) - } - if tt.isValid { - diff := cmp.Diff(state, &tt.expected) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) + t.Run( + tt.description, func(t *testing.T) { + state := &Model{ + ProjectId: tt.expected.ProjectId, + InstanceId: tt.expected.InstanceId, } - } - }) + err := mapFields(tt.input, state, tt.region) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") + } + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + if tt.isValid { + diff := cmp.Diff(state, &tt.expected) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + } + }, + ) } } @@ -171,20 +168,22 @@ func TestToCreatePayload(t *testing.T) { }, } for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - output, err := toCreatePayload(tt.input) - if !tt.isValid && err == nil { - t.Fatalf("Should have failed") - } - if tt.isValid && err != nil { - t.Fatalf("Should not have failed: %v", err) - } - if tt.isValid { - diff := cmp.Diff(output, tt.expected) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) + t.Run( + tt.description, func(t *testing.T) { + output, err := toCreatePayload(tt.input) + if !tt.isValid && err == nil { + t.Fatalf("Should have failed") } - } - }) + if tt.isValid && err != nil { + t.Fatalf("Should not have failed: %v", err) + } + if tt.isValid { + diff := cmp.Diff(output, tt.expected) + if diff != "" { + t.Fatalf("Data does not match: %s", diff) + } + } + }, + ) } } diff --git a/stackit/provider.go b/stackit/provider.go index 9a891519..16af561f 100644 --- a/stackit/provider.go +++ b/stackit/provider.go @@ -21,6 +21,7 @@ import ( sdkauth "github.com/stackitcloud/stackit-sdk-go/core/auth" "github.com/stackitcloud/stackit-sdk-go/core/config" + postgresFlexAlphaDatabase "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/database" postgresFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance" postgresFlexAlphaUser "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user" sqlServerFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance" @@ -361,7 +362,8 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest, setStringField(providerConfig.DefaultRegion, func(v string) { providerData.DefaultRegion = v }) setStringField( - providerConfig.Region, func(v string) { providerData.Region = v }) // nolint:staticcheck // preliminary handling of deprecated attribute + providerConfig.Region, func(v string) { providerData.Region = v }, + ) // nolint:staticcheck // preliminary handling of deprecated attribute setBoolField(providerConfig.EnableBetaResources, func(v bool) { providerData.EnableBetaResources = v }) setStringField( @@ -486,6 +488,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest, // DataSources defines the data sources implemented in the provider. func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + postgresFlexAlphaDatabase.NewDatabaseDataSource, postgresFlexAlphaInstance.NewInstanceDataSource, postgresFlexAlphaUser.NewUserDataSource, sqlServerFlexAlphaInstance.NewInstanceDataSource, @@ -496,6 +499,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource // Resources defines the resources implemented in the provider. func (p *Provider) Resources(_ context.Context) []func() resource.Resource { resources := []func() resource.Resource{ + postgresFlexAlphaDatabase.NewDatabaseResource, postgresFlexAlphaInstance.NewInstanceResource, postgresFlexAlphaUser.NewUserResource, sqlServerFlexAlphaInstance.NewInstanceResource,