diff --git a/stackit/internal/services/postgresflexalpha/database/datasources_gen/databases_data_source_gen.go b/stackit/internal/services/postgresflexalpha/database/datasources_gen/databases_data_source_gen.go index a533e5ca..b8bc6010 100644 --- a/stackit/internal/services/postgresflexalpha/database/datasources_gen/databases_data_source_gen.go +++ b/stackit/internal/services/postgresflexalpha/database/datasources_gen/databases_data_source_gen.go @@ -23,11 +23,6 @@ func DatabasesDataSourceSchema(ctx context.Context) schema.Schema { "databases": schema.ListNestedAttribute{ NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "created": schema.StringAttribute{ - Computed: true, - Description: "The data when the database was created in RFC3339 format.", - MarkdownDescription: "The data when the database was created in RFC3339 format.", - }, "id": schema.Int64Attribute{ Computed: true, Description: "The id of the database.", @@ -169,24 +164,6 @@ func (t DatabasesType) ValueFromObject(ctx context.Context, in basetypes.ObjectV attributes := in.Attributes() - createdAttribute, ok := attributes["created"] - - if !ok { - diags.AddError( - "Attribute Missing", - `created is missing from object`) - - return nil, diags - } - - createdVal, ok := createdAttribute.(basetypes.StringValue) - - if !ok { - diags.AddError( - "Attribute Wrong Type", - fmt.Sprintf(`created expected to be basetypes.StringValue, was: %T`, createdAttribute)) - } - idAttribute, ok := attributes["id"] if !ok { @@ -246,11 +223,10 @@ func (t DatabasesType) ValueFromObject(ctx context.Context, in basetypes.ObjectV } return DatabasesValue{ - Created: createdVal, - Id: idVal, - Name: nameVal, - Owner: ownerVal, - state: attr.ValueStateKnown, + Id: idVal, + Name: nameVal, + Owner: ownerVal, + state: attr.ValueStateKnown, }, diags } @@ -317,24 +293,6 @@ func NewDatabasesValue(attributeTypes map[string]attr.Type, attributes map[strin return NewDatabasesValueUnknown(), diags } - createdAttribute, ok := attributes["created"] - - if !ok { - diags.AddError( - "Attribute Missing", - `created is missing from object`) - - return NewDatabasesValueUnknown(), diags - } - - createdVal, ok := createdAttribute.(basetypes.StringValue) - - if !ok { - diags.AddError( - "Attribute Wrong Type", - fmt.Sprintf(`created expected to be basetypes.StringValue, was: %T`, createdAttribute)) - } - idAttribute, ok := attributes["id"] if !ok { @@ -394,11 +352,10 @@ func NewDatabasesValue(attributeTypes map[string]attr.Type, attributes map[strin } return DatabasesValue{ - Created: createdVal, - Id: idVal, - Name: nameVal, - Owner: ownerVal, - state: attr.ValueStateKnown, + Id: idVal, + Name: nameVal, + Owner: ownerVal, + state: attr.ValueStateKnown, }, diags } @@ -470,20 +427,18 @@ func (t DatabasesType) ValueType(ctx context.Context) attr.Value { var _ basetypes.ObjectValuable = DatabasesValue{} type DatabasesValue struct { - Created basetypes.StringValue `tfsdk:"created"` - Id basetypes.Int64Value `tfsdk:"id"` - Name basetypes.StringValue `tfsdk:"name"` - Owner basetypes.StringValue `tfsdk:"owner"` - state attr.ValueState + Id basetypes.Int64Value `tfsdk:"id"` + Name basetypes.StringValue `tfsdk:"name"` + Owner basetypes.StringValue `tfsdk:"owner"` + state attr.ValueState } func (v DatabasesValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { - attrTypes := make(map[string]tftypes.Type, 4) + attrTypes := make(map[string]tftypes.Type, 3) var val tftypes.Value var err error - attrTypes["created"] = basetypes.StringType{}.TerraformType(ctx) attrTypes["id"] = basetypes.Int64Type{}.TerraformType(ctx) attrTypes["name"] = basetypes.StringType{}.TerraformType(ctx) attrTypes["owner"] = basetypes.StringType{}.TerraformType(ctx) @@ -492,15 +447,7 @@ func (v DatabasesValue) ToTerraformValue(ctx context.Context) (tftypes.Value, er switch v.state { case attr.ValueStateKnown: - vals := make(map[string]tftypes.Value, 4) - - val, err = v.Created.ToTerraformValue(ctx) - - if err != nil { - return tftypes.NewValue(objectType, tftypes.UnknownValue), err - } - - vals["created"] = val + vals := make(map[string]tftypes.Value, 3) val, err = v.Id.ToTerraformValue(ctx) @@ -556,10 +503,9 @@ func (v DatabasesValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValu var diags diag.Diagnostics attributeTypes := map[string]attr.Type{ - "created": basetypes.StringType{}, - "id": basetypes.Int64Type{}, - "name": basetypes.StringType{}, - "owner": basetypes.StringType{}, + "id": basetypes.Int64Type{}, + "name": basetypes.StringType{}, + "owner": basetypes.StringType{}, } if v.IsNull() { @@ -573,10 +519,9 @@ func (v DatabasesValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValu objVal, diags := types.ObjectValue( attributeTypes, map[string]attr.Value{ - "created": v.Created, - "id": v.Id, - "name": v.Name, - "owner": v.Owner, + "id": v.Id, + "name": v.Name, + "owner": v.Owner, }) return objVal, diags @@ -597,10 +542,6 @@ func (v DatabasesValue) Equal(o attr.Value) bool { return true } - if !v.Created.Equal(other.Created) { - return false - } - if !v.Id.Equal(other.Id) { return false } @@ -626,10 +567,9 @@ func (v DatabasesValue) Type(ctx context.Context) attr.Type { func (v DatabasesValue) AttributeTypes(ctx context.Context) map[string]attr.Type { return map[string]attr.Type{ - "created": basetypes.StringType{}, - "id": basetypes.Int64Type{}, - "name": basetypes.StringType{}, - "owner": basetypes.StringType{}, + "id": basetypes.Int64Type{}, + "name": basetypes.StringType{}, + "owner": basetypes.StringType{}, } } diff --git a/stackit/internal/services/postgresflexalpha/database/resource.go b/stackit/internal/services/postgresflexalpha/database/resource.go index 64c62e70..e2013f29 100644 --- a/stackit/internal/services/postgresflexalpha/database/resource.go +++ b/stackit/internal/services/postgresflexalpha/database/resource.go @@ -178,18 +178,11 @@ func (r *databaseResource) Create( return } - // Read identity data - var identityData DatabaseResourceIdentityModel - resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...) - if resp.Diagnostics.HasError() { - return - } - ctx = core.InitProviderContext(ctx) - projectId := identityData.ProjectID.ValueString() - region := identityData.ProjectID.ValueString() - instanceId := identityData.InstanceID.ValueString() + projectId := model.ProjectId.ValueString() + region := model.InstanceId.ValueString() + instanceId := model.InstanceId.ValueString() ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "instance_id", instanceId) @@ -218,8 +211,6 @@ func (r *databaseResource) Create( return } - ctx = core.LogResponse(ctx) - if databaseResp == nil || databaseResp.Id == nil { core.LogAndAddError( ctx, @@ -231,6 +222,19 @@ func (r *databaseResource) Create( } databaseId := *databaseResp.Id ctx = tflog.SetField(ctx, "database_id", databaseId) + ctx = core.LogResponse(ctx) + + // Save identity into Terraform state + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseID: types.Int64Value(databaseId), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } database, err := getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId) if err != nil { @@ -255,18 +259,6 @@ func (r *databaseResource) Create( return } - // Set data returned by API in identity - identity := DatabaseResourceIdentityModel{ - ProjectID: types.StringValue(projectId), - Region: types.StringValue(region), - InstanceID: types.StringValue(instanceId), - DatabaseID: types.Int64Value(databaseId), - } - resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) - if resp.Diagnostics.HasError() { - return - } - // Set state to fully populated data resp.Diagnostics.Append(resp.State.Set(ctx, model)...) if resp.Diagnostics.HasError() { @@ -337,6 +329,18 @@ func (r *databaseResource) Read( return } + // Save identity into Terraform state + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseID: types.Int64Value(databaseId), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set refreshed state diags = resp.State.Set(ctx, model) resp.Diagnostics.Append(diags...) @@ -415,7 +419,7 @@ func (r *databaseResource) Update( } // Update existing database - res, err := r.client.UpdateDatabasePartiallyRequest( + err := r.client.UpdateDatabasePartiallyRequest( ctx, projectId, region, @@ -430,19 +434,45 @@ func (r *databaseResource) Update( ctx = core.LogResponse(ctx) // Map response body to schema - err = mapResourceFields(res.Database, &model) + databaseResp, err := getDatabaseById(ctx, r.client, projectId, region, instanceId, databaseId64) + 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) { + resp.State.RemoveResource(ctx) + return + } + core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Calling API: %v", err)) + return + } + + ctx = core.LogResponse(ctx) + + // Map response body to schema + err = mapResourceFields(databaseResp, &model) if err != nil { core.LogAndAddError( ctx, &resp.Diagnostics, - "Error updating database", + "Error reading database", fmt.Sprintf("Processing API payload: %v", err), ) return } + + // Save identity into Terraform state + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseID: types.Int64Value(databaseId64), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set state to fully populated data - diags = resp.State.Set(ctx, model) - resp.Diagnostics.Append(diags...) + resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) if resp.Diagnostics.HasError() { return } diff --git a/stackit/internal/services/postgresflexalpha/user/resource.go b/stackit/internal/services/postgresflexalpha/user/resource.go index 842ccbc9..8984a4ea 100644 --- a/stackit/internal/services/postgresflexalpha/user/resource.go +++ b/stackit/internal/services/postgresflexalpha/user/resource.go @@ -159,14 +159,10 @@ func (r *userResource) Create( ctx = core.InitProviderContext(ctx) - arg, errExt := r.extractIdentityData(model, identityData) - if errExt != nil { - core.LogAndAddError( - ctx, - &resp.Diagnostics, - extractErrorSummary, - fmt.Sprintf(extractErrorMessage, errExt), - ) + arg := &clientArg{ + projectId: model.ProjectId.ValueString(), + instanceId: model.InstanceId.ValueString(), + region: r.providerData.GetRegionWithOverride(model.Region), } ctx = r.setTFLogFields(ctx, arg) @@ -204,11 +200,13 @@ func (r *userResource) Create( ) return } - model.Id = types.Int64PointerValue(userResp.Id) - model.UserId = types.Int64PointerValue(userResp.Id) - model.Password = types.StringPointerValue(userResp.Password) + model.Id = types.Int64Value(userResp.GetId()) + model.UserId = types.Int64Value(userResp.GetId()) + model.Password = types.StringValue(userResp.GetPassword()) + model.Status = types.StringValue(userResp.GetStatus()) + model.ConnectionString = types.StringValue(userResp.GetConnectionString()) - ctx = tflog.SetField(ctx, "user_id", *userResp.Id) + ctx = tflog.SetField(ctx, "user_id", userResp.GetId()) ctx = core.LogResponse(ctx) @@ -217,7 +215,7 @@ func (r *userResource) Create( ProjectID: types.StringValue(arg.projectId), Region: types.StringValue(arg.region), InstanceID: types.StringValue(arg.instanceId), - UserID: types.Int64PointerValue(userResp.Id), + UserID: types.Int64Value(userResp.GetId()), } resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) if resp.Diagnostics.HasError() { @@ -261,23 +259,12 @@ func (r *userResource) Read( return } - // Read identity data - var identityData UserResourceIdentityModel - resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...) - if resp.Diagnostics.HasError() { - return - } - ctx = core.InitProviderContext(ctx) - arg, errExt := r.extractIdentityData(model, identityData) - if errExt != nil { - core.LogAndAddError( - ctx, - &resp.Diagnostics, - extractErrorSummary, - fmt.Sprintf(extractErrorMessage, errExt), - ) + arg := &clientArg{ + projectId: model.ProjectId.ValueString(), + instanceId: model.InstanceId.ValueString(), + region: r.providerData.GetRegionWithOverride(model.Region), } ctx = r.setTFLogFields(ctx, arg) @@ -299,6 +286,18 @@ func (r *userResource) Read( ctx = core.LogResponse(ctx) + // Set data returned by API in identity + identity := UserResourceIdentityModel{ + ProjectID: types.StringValue(arg.projectId), + Region: types.StringValue(arg.region), + InstanceID: types.StringValue(arg.instanceId), + UserID: types.Int64Value(arg.userId), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set refreshed state diags = resp.State.Set(ctx, model) resp.Diagnostics.Append(diags...) @@ -385,6 +384,18 @@ func (r *userResource) Update( ctx = core.LogResponse(ctx) + // Set data returned by API in identity + identity := UserResourceIdentityModel{ + ProjectID: types.StringValue(arg.projectId), + Region: types.StringValue(arg.region), + InstanceID: types.StringValue(arg.instanceId), + UserID: types.Int64Value(userId64), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Verify update exists, err := r.getUserResource(ctx, &stateModel, arg) diff --git a/stackit/internal/services/sqlserverflexalpha/database/resource.go b/stackit/internal/services/sqlserverflexalpha/database/resource.go index 0f4ce098..f95b57fb 100644 --- a/stackit/internal/services/sqlserverflexalpha/database/resource.go +++ b/stackit/internal/services/sqlserverflexalpha/database/resource.go @@ -155,18 +155,11 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques return } - // Read identity data - var identityData DatabaseResourceIdentityModel - resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...) - if resp.Diagnostics.HasError() { - return - } - ctx = core.InitProviderContext(ctx) - projectId := identityData.ProjectID.ValueString() - region := identityData.ProjectID.ValueString() - instanceId := identityData.InstanceID.ValueString() + projectId := model.ProjectId.ValueString() + region := model.Region.ValueString() + instanceId := model.InstanceId.ValueString() ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "instance_id", instanceId) @@ -215,6 +208,18 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques ctx = core.LogResponse(ctx) + // Set data returned by API in identity + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseName: types.StringValue(databaseName), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + database, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute() if err != nil { core.LogAndAddError( @@ -238,18 +243,6 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques return } - // Set data returned by API in identity - identity := DatabaseResourceIdentityModel{ - ProjectID: types.StringValue(projectId), - Region: types.StringValue(region), - InstanceID: types.StringValue(instanceId), - DatabaseName: types.StringValue(databaseName), - } - resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) - if resp.Diagnostics.HasError() { - return - } - // Set state to fully populated data resp.Diagnostics.Append(resp.State.Set(ctx, model)...) if resp.Diagnostics.HasError() { @@ -316,9 +309,20 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r return } + // Set data returned by API in identity + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseName: types.StringValue(databaseName), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set refreshed state - diags = resp.State.Set(ctx, model) - resp.Diagnostics.Append(diags...) + resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) if resp.Diagnostics.HasError() { return } @@ -371,6 +375,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques } ctx = core.LogResponse(ctx) + resp.State.RemoveResource(ctx) tflog.Info(ctx, "sqlserverflexalpha.Database deleted") } @@ -382,7 +387,7 @@ func (r *databaseResource) ModifyPlan( req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse, ) { // nolint:gocritic // function signature required by Terraform - var configModel sqlserverflexalphaGen.DatabaseModel + var configModel resourceModel // skip initial empty configuration to avoid follow-up errors if req.Config.Raw.IsNull() { return @@ -392,7 +397,7 @@ func (r *databaseResource) ModifyPlan( return } - var planModel sqlserverflexalphaGen.DatabaseModel + var planModel resourceModel resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) if resp.Diagnostics.HasError() { return @@ -485,8 +490,8 @@ func (r *databaseResource) extractIdentityData( model resourceModel, identity DatabaseResourceIdentityModel, ) (projectId, region, instanceId, databaseName string, err error) { - if !model.DatabaseName.IsNull() && !model.DatabaseName.IsUnknown() { - databaseName = model.DatabaseName.ValueString() + if !model.Name.IsNull() && !model.Name.IsUnknown() { + databaseName = model.Name.ValueString() } else { if identity.DatabaseName.IsNull() || identity.DatabaseName.IsUnknown() { return "", "", "", "", fmt.Errorf("database_name not found in config") diff --git a/stackit/internal/services/sqlserverflexalpha/user/mapper.go b/stackit/internal/services/sqlserverflexalpha/user/mapper.go index 2035029b..0b7baa84 100644 --- a/stackit/internal/services/sqlserverflexalpha/user/mapper.go +++ b/stackit/internal/services/sqlserverflexalpha/user/mapper.go @@ -140,7 +140,7 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res if user.Roles != nil { var roles []attr.Value for _, role := range *user.Roles { - roles = append(roles, types.StringValue(string(role))) + roles = append(roles, types.StringValue(role)) } rolesSet, diags := types.SetValue(types.StringType, roles) if diags.HasError() { @@ -165,7 +165,7 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res // toCreatePayload converts a resourceModel to an API CreateUserRequestPayload. func toCreatePayload( model *resourceModel, - roles []sqlserverflexalpha.UserRole, + roles []string, ) (*sqlserverflexalpha.CreateUserRequestPayload, error) { if model == nil { return nil, fmt.Errorf("nil model") diff --git a/stackit/internal/services/sqlserverflexalpha/user/mapper_test.go b/stackit/internal/services/sqlserverflexalpha/user/mapper_test.go index c97fee9c..e450b581 100644 --- a/stackit/internal/services/sqlserverflexalpha/user/mapper_test.go +++ b/stackit/internal/services/sqlserverflexalpha/user/mapper_test.go @@ -42,7 +42,7 @@ func TestMapDataSourceFields(t *testing.T) { "simple_values", &sqlserverflexalpha.GetUserResponse{ - Roles: &[]sqlserverflexalpha.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -79,7 +79,7 @@ func TestMapDataSourceFields(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexalpha.GetUserResponse{ Id: utils.Ptr(int64(1)), - Roles: &[]sqlserverflexalpha.UserRole{}, + Roles: &[]string{}, Username: nil, Host: nil, Port: utils.Ptr(int64(2123456789)), @@ -180,7 +180,7 @@ func TestMapFieldsCreate(t *testing.T) { "simple_values", &sqlserverflexalpha.CreateUserResponse{ Id: utils.Ptr(int64(2)), - Roles: &[]sqlserverflexalpha.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -221,7 +221,7 @@ func TestMapFieldsCreate(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexalpha.CreateUserResponse{ Id: utils.Ptr(int64(3)), - Roles: &[]sqlserverflexalpha.UserRole{}, + Roles: &[]string{}, Username: nil, Password: utils.Ptr(""), Host: nil, @@ -329,7 +329,7 @@ func TestMapFields(t *testing.T) { { "simple_values", &sqlserverflexalpha.GetUserResponse{ - Roles: &[]sqlserverflexalpha.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -364,7 +364,7 @@ func TestMapFields(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexalpha.GetUserResponse{ Id: utils.Ptr(int64(1)), - Roles: &[]sqlserverflexalpha.UserRole{}, + Roles: &[]string{}, Username: nil, Host: nil, Port: utils.Ptr(int64(2123456789)), @@ -435,16 +435,16 @@ func TestToCreatePayload(t *testing.T) { tests := []struct { description string input *resourceModel - inputRoles []sqlserverflexalpha.UserRole + inputRoles []string expected *sqlserverflexalpha.CreateUserRequestPayload isValid bool }{ { "default_values", &resourceModel{}, - []sqlserverflexalpha.UserRole{}, + []string{}, &sqlserverflexalpha.CreateUserRequestPayload{ - Roles: &[]sqlserverflexalpha.UserRole{}, + Roles: &[]string{}, Username: nil, }, true, @@ -454,12 +454,12 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringValue("username"), }, - []sqlserverflexalpha.UserRole{ + []string{ "role_1", "role_2", }, &sqlserverflexalpha.CreateUserRequestPayload{ - Roles: &[]sqlserverflexalpha.UserRole{ + Roles: &[]string{ "role_1", "role_2", }, @@ -472,11 +472,11 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringNull(), }, - []sqlserverflexalpha.UserRole{ + []string{ "", }, &sqlserverflexalpha.CreateUserRequestPayload{ - Roles: &[]sqlserverflexalpha.UserRole{ + Roles: &[]string{ "", }, Username: nil, @@ -486,7 +486,7 @@ func TestToCreatePayload(t *testing.T) { { "nil_model", nil, - []sqlserverflexalpha.UserRole{}, + []string{}, nil, false, }, @@ -495,9 +495,9 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringValue("username"), }, - []sqlserverflexalpha.UserRole{}, + []string{}, &sqlserverflexalpha.CreateUserRequestPayload{ - Roles: &[]sqlserverflexalpha.UserRole{}, + Roles: &[]string{}, Username: utils.Ptr("username"), }, true, diff --git a/stackit/internal/services/sqlserverflexalpha/user/resource.go b/stackit/internal/services/sqlserverflexalpha/user/resource.go index 3a95c862..52dee432 100644 --- a/stackit/internal/services/sqlserverflexalpha/user/resource.go +++ b/stackit/internal/services/sqlserverflexalpha/user/resource.go @@ -179,7 +179,7 @@ func (r *userResource) Create( ctx = tflog.SetField(ctx, "instance_id", instanceId) ctx = tflog.SetField(ctx, "region", region) - var roles []sqlserverflexalpha.UserRole + var roles []string if !model.Roles.IsNull() && !model.Roles.IsUnknown() { diags = model.Roles.ElementsAs(ctx, &roles, false) resp.Diagnostics.Append(diags...) @@ -220,6 +220,18 @@ func (r *userResource) Create( userId := *userResp.Id ctx = tflog.SetField(ctx, "user_id", userId) + // Set data returned by API in identity + identity := UserResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + UserID: types.Int64Value(userResp.GetId()), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Map response body to schema err = mapFieldsCreate(userResp, &model, region) if err != nil { @@ -282,6 +294,18 @@ func (r *userResource) Read( ctx = core.LogResponse(ctx) + // Set data returned by API in identity + identity := UserResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + UserID: types.Int64Value(userId), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Map response body to schema err = mapFields(recordSetResp, &model, region) if err != nil { @@ -351,6 +375,7 @@ func (r *userResource) Delete( } ctx = core.LogResponse(ctx) + resp.State.RemoveResource(ctx) tflog.Info(ctx, "SQLServer Flex user deleted") } diff --git a/stackit/internal/services/sqlserverflexalpha/user/resources_gen/user_resource_gen.go b/stackit/internal/services/sqlserverflexalpha/user/resources_gen/user_resource_gen.go index 2b456e79..b316b020 100644 --- a/stackit/internal/services/sqlserverflexalpha/user/resources_gen/user_resource_gen.go +++ b/stackit/internal/services/sqlserverflexalpha/user/resources_gen/user_resource_gen.go @@ -66,8 +66,8 @@ func UserResourceSchema(ctx context.Context) schema.Schema { "roles": schema.ListAttribute{ ElementType: types.StringType, Required: true, - Description: "A list containing the user roles for the instance.", - MarkdownDescription: "A list containing the user roles for the instance.", + Description: "A list containing the user roles for the instance. A list with the valid user roles can be retrieved using the List Roles endpoint.", + MarkdownDescription: "A list containing the user roles for the instance. A list with the valid user roles can be retrieved using the List Roles endpoint.", }, "status": schema.StringAttribute{ Computed: true, diff --git a/stackit/internal/services/sqlserverflexbeta/database/resource.go b/stackit/internal/services/sqlserverflexbeta/database/resource.go index 8e09975b..1f57355d 100644 --- a/stackit/internal/services/sqlserverflexbeta/database/resource.go +++ b/stackit/internal/services/sqlserverflexbeta/database/resource.go @@ -69,7 +69,7 @@ func (r *databaseResource) Metadata( //go:embed planModifiers.yaml var modifiersFileByte []byte -func (r *databaseResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +func (r *databaseResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { s := sqlserverflexbetaResGen.DatabaseResourceSchema(ctx) @@ -160,23 +160,16 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques return } - // Read identity data - var identityData DatabaseResourceIdentityModel - resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...) - if resp.Diagnostics.HasError() { - return - } - ctx = core.InitProviderContext(ctx) - projectId := identityData.ProjectID.ValueString() - region := identityData.Region.ValueString() - instanceId := identityData.InstanceID.ValueString() + projectId := data.ProjectId.ValueString() + region := data.Region.ValueString() + instanceId := data.InstanceId.ValueString() ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "instance_id", instanceId) - databaseName := identityData.DatabaseName.ValueString() + databaseName := data.Name.ValueString() ctx = tflog.SetField(ctx, "database_name", databaseName) payLoad := sqlserverflexbeta.CreateDatabaseRequestPayload{ @@ -215,6 +208,18 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques ctx = core.LogResponse(ctx) + // Set data returned by API in identity + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseName: types.StringValue(databaseName), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // TODO: is this neccessary to wait for the database-> API say 200 ? /*waitResp, err := wait.CreateDatabaseWaitHandler( ctx, @@ -301,18 +306,6 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques return } - // Set data returned by API in identity - identity := DatabaseResourceIdentityModel{ - ProjectID: types.StringValue(projectId), - Region: types.StringValue(region), - InstanceID: types.StringValue(instanceId), - DatabaseName: types.StringValue(databaseName), - } - resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) - if resp.Diagnostics.HasError() { - return - } - // Set state to fully populated data resp.Diagnostics.Append(resp.State.Set(ctx, data)...) if resp.Diagnostics.HasError() { @@ -381,9 +374,20 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r return } + // Save identity into Terraform state + identity := DatabaseResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + DatabaseName: types.StringValue(databaseName), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set refreshed state - diags = resp.State.Set(ctx, model) - resp.Diagnostics.Append(diags...) + resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) if resp.Diagnostics.HasError() { return } @@ -391,7 +395,7 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r tflog.Info(ctx, "sqlserverflexbeta.Database read") } -func (r *databaseResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { +func (r *databaseResource) Update(ctx context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { // TODO: Check update api endpoint - not available at the moment, so return an error for now core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating database", "Database can't be updated") } @@ -436,6 +440,7 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques } ctx = core.LogResponse(ctx) + resp.State.RemoveResource(ctx) tflog.Info(ctx, "sqlserverflexbeta.Database deleted") } @@ -453,13 +458,13 @@ func (r *databaseResource) ModifyPlan( return } - var configModel sqlserverflexbetaResGen.DatabaseModel + var configModel resourceModel resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...) if resp.Diagnostics.HasError() { return } - var planModel sqlserverflexbetaResGen.DatabaseModel + var planModel resourceModel resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) if resp.Diagnostics.HasError() { return @@ -562,8 +567,8 @@ func (r *databaseResource) extractIdentityData( model resourceModel, identity DatabaseResourceIdentityModel, ) (projectId, region, instanceId, databaseName string, err error) { - if !model.DatabaseName.IsNull() && !model.DatabaseName.IsUnknown() { - databaseName = model.DatabaseName.ValueString() + if !model.Name.IsNull() && !model.Name.IsUnknown() { + databaseName = model.Name.ValueString() } else { if identity.DatabaseName.IsNull() || identity.DatabaseName.IsUnknown() { return "", "", "", "", fmt.Errorf("database_name not found in config") diff --git a/stackit/internal/services/sqlserverflexbeta/instance/resource.go b/stackit/internal/services/sqlserverflexbeta/instance/resource.go index 5ccfa3c0..741424a0 100644 --- a/stackit/internal/services/sqlserverflexbeta/instance/resource.go +++ b/stackit/internal/services/sqlserverflexbeta/instance/resource.go @@ -160,7 +160,7 @@ func (r *instanceResource) ModifyPlan( if req.Plan.Raw.IsNull() { return } - var planModel sqlserverflexbetaResGen.InstanceModel + var planModel resourceModel resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...) if resp.Diagnostics.HasError() { return @@ -334,6 +334,7 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r return } + // Save identity into Terraform state identity := InstanceResourceIdentityModel{ ProjectID: types.StringValue(projectId), Region: types.StringValue(region), @@ -346,6 +347,9 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } tflog.Info(ctx, "sqlserverflexbeta.Instance read") } @@ -433,6 +437,9 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques // Save updated data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } tflog.Info(ctx, "sqlserverflexbeta.Instance updated") } diff --git a/stackit/internal/services/sqlserverflexbeta/user/mapper.go b/stackit/internal/services/sqlserverflexbeta/user/mapper.go index d2324058..bddea43a 100644 --- a/stackit/internal/services/sqlserverflexbeta/user/mapper.go +++ b/stackit/internal/services/sqlserverflexbeta/user/mapper.go @@ -165,7 +165,7 @@ func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *reso // toCreatePayload converts a resourceModel to an API CreateUserRequestPayload. func toCreatePayload( model *resourceModel, - roles []sqlserverflexbeta.UserRole, + roles []string, ) (*sqlserverflexbeta.CreateUserRequestPayload, error) { if model == nil { return nil, fmt.Errorf("nil model") diff --git a/stackit/internal/services/sqlserverflexbeta/user/mapper_test.go b/stackit/internal/services/sqlserverflexbeta/user/mapper_test.go index 23c6121c..7b23805c 100644 --- a/stackit/internal/services/sqlserverflexbeta/user/mapper_test.go +++ b/stackit/internal/services/sqlserverflexbeta/user/mapper_test.go @@ -42,7 +42,7 @@ func TestMapDataSourceFields(t *testing.T) { "simple_values", &sqlserverflexbeta.GetUserResponse{ - Roles: &[]sqlserverflexbeta.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -81,7 +81,7 @@ func TestMapDataSourceFields(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexbeta.GetUserResponse{ Id: utils.Ptr(int64(1)), - Roles: &[]sqlserverflexbeta.UserRole{}, + Roles: &[]string{}, Username: nil, Host: nil, Port: utils.Ptr(int64(2123456789)), @@ -182,7 +182,7 @@ func TestMapFieldsCreate(t *testing.T) { "simple_values", &sqlserverflexbeta.CreateUserResponse{ Id: utils.Ptr(int64(2)), - Roles: &[]sqlserverflexbeta.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -223,7 +223,7 @@ func TestMapFieldsCreate(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexbeta.CreateUserResponse{ Id: utils.Ptr(int64(3)), - Roles: &[]sqlserverflexbeta.UserRole{}, + Roles: &[]string{}, Username: nil, Password: utils.Ptr(""), Host: nil, @@ -331,7 +331,7 @@ func TestMapFields(t *testing.T) { { "simple_values", &sqlserverflexbeta.GetUserResponse{ - Roles: &[]sqlserverflexbeta.UserRole{ + Roles: &[]string{ "role_1", "role_2", "", @@ -366,7 +366,7 @@ func TestMapFields(t *testing.T) { "null_fields_and_int_conversions", &sqlserverflexbeta.GetUserResponse{ Id: utils.Ptr(int64(1)), - Roles: &[]sqlserverflexbeta.UserRole{}, + Roles: &[]string{}, Username: nil, Host: nil, Port: utils.Ptr(int64(2123456789)), @@ -437,16 +437,16 @@ func TestToCreatePayload(t *testing.T) { tests := []struct { description string input *resourceModel - inputRoles []sqlserverflexbeta.UserRole + inputRoles []string expected *sqlserverflexbeta.CreateUserRequestPayload isValid bool }{ { "default_values", &resourceModel{}, - []sqlserverflexbeta.UserRole{}, + []string{}, &sqlserverflexbeta.CreateUserRequestPayload{ - Roles: &[]sqlserverflexbeta.UserRole{}, + Roles: &[]string{}, Username: nil, }, true, @@ -456,12 +456,12 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringValue("username"), }, - []sqlserverflexbeta.UserRole{ + []string{ "role_1", "role_2", }, &sqlserverflexbeta.CreateUserRequestPayload{ - Roles: &[]sqlserverflexbeta.UserRole{ + Roles: &[]string{ "role_1", "role_2", }, @@ -474,11 +474,11 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringNull(), }, - []sqlserverflexbeta.UserRole{ + []string{ "", }, &sqlserverflexbeta.CreateUserRequestPayload{ - Roles: &[]sqlserverflexbeta.UserRole{ + Roles: &[]string{ "", }, Username: nil, @@ -488,7 +488,7 @@ func TestToCreatePayload(t *testing.T) { { "nil_model", nil, - []sqlserverflexbeta.UserRole{}, + []string{}, nil, false, }, @@ -497,9 +497,9 @@ func TestToCreatePayload(t *testing.T) { &resourceModel{ Username: types.StringValue("username"), }, - []sqlserverflexbeta.UserRole{}, + []string{}, &sqlserverflexbeta.CreateUserRequestPayload{ - Roles: &[]sqlserverflexbeta.UserRole{}, + Roles: &[]string{}, Username: utils.Ptr("username"), }, true, diff --git a/stackit/internal/services/sqlserverflexbeta/user/resource.go b/stackit/internal/services/sqlserverflexbeta/user/resource.go index 03981b93..49850497 100644 --- a/stackit/internal/services/sqlserverflexbeta/user/resource.go +++ b/stackit/internal/services/sqlserverflexbeta/user/resource.go @@ -177,7 +177,7 @@ func (r *userResource) Create( ctx = tflog.SetField(ctx, "instance_id", instanceId) ctx = tflog.SetField(ctx, "region", region) - var roles []sqlserverflexbeta.UserRole + var roles []string if !model.Roles.IsNull() && !model.Roles.IsUnknown() { diags = model.Roles.ElementsAs(ctx, &roles, false) resp.Diagnostics.Append(diags...) @@ -292,6 +292,18 @@ func (r *userResource) Read( return } + // Set data returned by API in identity + identity := UserResourceIdentityModel{ + ProjectID: types.StringValue(projectId), + Region: types.StringValue(region), + InstanceID: types.StringValue(instanceId), + UserID: types.Int64Value(userId), + } + resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...) + if resp.Diagnostics.HasError() { + return + } + // Set refreshed state diags = resp.State.Set(ctx, model) resp.Diagnostics.Append(diags...) @@ -350,6 +362,8 @@ func (r *userResource) Delete( ctx = core.LogResponse(ctx) + resp.State.RemoveResource(ctx) + tflog.Info(ctx, "SQLServer Flex user deleted") } diff --git a/stackit/internal/services/sqlserverflexbeta/user/resources_gen/user_resource_gen.go b/stackit/internal/services/sqlserverflexbeta/user/resources_gen/user_resource_gen.go index 3bf7f4fc..f181f79c 100644 --- a/stackit/internal/services/sqlserverflexbeta/user/resources_gen/user_resource_gen.go +++ b/stackit/internal/services/sqlserverflexbeta/user/resources_gen/user_resource_gen.go @@ -66,8 +66,8 @@ func UserResourceSchema(ctx context.Context) schema.Schema { "roles": schema.ListAttribute{ ElementType: types.StringType, Required: true, - Description: "A list containing the user roles for the instance.", - MarkdownDescription: "A list containing the user roles for the instance.", + Description: "A list containing the user roles for the instance. A list with the valid user roles can be retrieved using the List Roles endpoint.", + MarkdownDescription: "A list containing the user roles for the instance. A list with the valid user roles can be retrieved using the List Roles endpoint.", }, "status": schema.StringAttribute{ Computed: true,