feat: update sql server flex configuration for user and database #46
23 changed files with 3959 additions and 1764 deletions
|
|
@ -2,9 +2,12 @@ package sqlserverflexalpha
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"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/pkg_gen/sqlserverflexalpha"
|
||||||
|
|
@ -12,6 +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/core"
|
||||||
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
|
sqlserverflexalphaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
|
||||||
sqlserverflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/utils"
|
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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// dataSourceModel maps the data source schema data.
|
// dataSourceModel maps the data source schema data.
|
||||||
|
|
@ -22,6 +26,7 @@ type dataSourceModel struct {
|
||||||
|
|
||||||
var _ datasource.DataSource = (*databaseDataSource)(nil)
|
var _ datasource.DataSource = (*databaseDataSource)(nil)
|
||||||
|
|
||||||
|
// NewDatabaseDataSource creates a new database data source.
|
||||||
func NewDatabaseDataSource() datasource.DataSource {
|
func NewDatabaseDataSource() datasource.DataSource {
|
||||||
return &databaseDataSource{}
|
return &databaseDataSource{}
|
||||||
}
|
}
|
||||||
|
|
@ -31,6 +36,7 @@ type databaseDataSource struct {
|
||||||
providerData core.ProviderData
|
providerData core.ProviderData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Metadata returns the data source type name.
|
||||||
func (d *databaseDataSource) Metadata(
|
func (d *databaseDataSource) Metadata(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
req datasource.MetadataRequest,
|
req datasource.MetadataRequest,
|
||||||
|
|
@ -39,6 +45,7 @@ func (d *databaseDataSource) Metadata(
|
||||||
resp.TypeName = req.ProviderTypeName + "_sqlserverflexalpha_database"
|
resp.TypeName = req.ProviderTypeName + "_sqlserverflexalpha_database"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Schema defines the data source schema.
|
||||||
func (d *databaseDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
func (d *databaseDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||||
s := sqlserverflexalphaGen.DatabaseDataSourceSchema(ctx)
|
s := sqlserverflexalphaGen.DatabaseDataSourceSchema(ctx)
|
||||||
s.Attributes["id"] = schema.StringAttribute{
|
s.Attributes["id"] = schema.StringAttribute{
|
||||||
|
|
@ -67,24 +74,92 @@ func (d *databaseDataSource) Configure(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.client = apiClient
|
d.client = apiClient
|
||||||
tflog.Info(ctx, "SQL SERVER Flex database client configured")
|
tflog.Info(ctx, "SQL SERVER Flex alpha database client configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read retrieves the resource's state from the API.
|
||||||
func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||||
var data dataSourceModel
|
|
||||||
|
|
||||||
// Read Terraform configuration data into the model
|
|
||||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
|
var model dataSourceModel
|
||||||
|
diags := req.Config.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Read API call logic
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
// Example data value setting
|
// Extract identifiers from the plan
|
||||||
// data.Id = types.StringValue("example-id")
|
projectId := model.ProjectId.ValueString()
|
||||||
|
instanceId := model.InstanceId.ValueString()
|
||||||
|
region := d.providerData.GetRegionWithOverride(model.Region)
|
||||||
|
databaseName := model.DatabaseName.ValueString()
|
||||||
|
|
||||||
// Save data into Terraform state
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
// Fetch database from the API
|
||||||
|
databaseResp, err := d.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
|
||||||
|
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
handleReadError(ctx, &resp.Diagnostics, err, projectId, instanceId)
|
||||||
|
resp.State.RemoveResource(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set refreshed state
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tflog.Info(ctx, "SQL Server Flex alpha database read")
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleReadError centralizes API error handling for the Read operation.
|
||||||
|
func handleReadError(ctx context.Context, diags *diag.Diagnostics, err error, projectId, instanceId string) {
|
||||||
|
utils.LogError(
|
||||||
|
ctx,
|
||||||
|
diags,
|
||||||
|
err,
|
||||||
|
"Reading database",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"Could not retrieve database for instance %q in project %q.",
|
||||||
|
instanceId,
|
||||||
|
projectId,
|
||||||
|
),
|
||||||
|
map[int]string{
|
||||||
|
http.StatusBadRequest: fmt.Sprintf(
|
||||||
|
"Invalid request parameters for project %q and instance %q.",
|
||||||
|
projectId,
|
||||||
|
instanceId,
|
||||||
|
),
|
||||||
|
http.StatusNotFound: fmt.Sprintf(
|
||||||
|
"Database, instance %q, or project %q not found.",
|
||||||
|
instanceId,
|
||||||
|
projectId,
|
||||||
|
),
|
||||||
|
http.StatusForbidden: fmt.Sprintf("Forbidden access to project %q.", projectId),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package sqlserverflexalpha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// mapFields maps fields from a ListDatabase API response to a resourceModel for the data source.
|
||||||
|
func mapFields(source *sqlserverflexalpha.GetDatabaseResponse, model *dataSourceModel, region string) error {
|
||||||
|
if source == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if source.Id == nil || *source.Id == 0 {
|
||||||
|
return fmt.Errorf("id not present")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model given is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseId int64
|
||||||
|
if model.Id.ValueInt64() != 0 {
|
||||||
|
databaseId = model.Id.ValueInt64()
|
||||||
|
} else if source.Id != nil {
|
||||||
|
databaseId = *source.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("database id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Id = types.Int64Value(databaseId)
|
||||||
|
model.DatabaseName = types.StringValue(source.GetName())
|
||||||
|
model.Name = types.StringValue(source.GetName())
|
||||||
|
model.Owner = types.StringValue(strings.Trim(source.GetOwner(), "\""))
|
||||||
|
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.CollationName = types.StringValue(source.GetCollationName())
|
||||||
|
|
||||||
|
model.TerraformID = utils.BuildInternalTerraformId(
|
||||||
|
model.ProjectId.ValueString(),
|
||||||
|
region,
|
||||||
|
model.InstanceId.ValueString(),
|
||||||
|
model.DatabaseName.ValueString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapResourceFields maps fields from a ListDatabase API response to a resourceModel for the resource.
|
||||||
|
func mapResourceFields(source *sqlserverflexalpha.GetDatabaseResponse, model *resourceModel, region string) error {
|
||||||
|
if source == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if source.Id == nil || *source.Id == 0 {
|
||||||
|
return fmt.Errorf("id not present")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseId int64
|
||||||
|
if model.Id.ValueInt64() != 0 {
|
||||||
|
databaseId = model.Id.ValueInt64()
|
||||||
|
} else if source.Id != nil {
|
||||||
|
databaseId = *source.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("database id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Id = types.Int64Value(databaseId)
|
||||||
|
model.DatabaseName = types.StringValue(source.GetName())
|
||||||
|
model.Name = types.StringValue(source.GetName())
|
||||||
|
model.Owner = types.StringValue(strings.Trim(source.GetOwner(), "\""))
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
|
||||||
|
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCreatePayload converts the resource model to an API create payload.
|
||||||
|
func toCreatePayload(model *resourceModel) (*sqlserverflexalpha.CreateDatabaseRequestPayload, error) {
|
||||||
|
if model == nil {
|
||||||
|
return nil, fmt.Errorf("nil model")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sqlserverflexalpha.CreateDatabaseRequestPayload{
|
||||||
|
Name: model.Name.ValueStringPointer(),
|
||||||
|
Owner: model.Owner.ValueStringPointer(),
|
||||||
|
Collation: model.Collation.ValueStringPointer(),
|
||||||
|
Compatibility: model.Compatibility.ValueInt64Pointer(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
package sqlserverflexalpha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"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"
|
||||||
|
datasource "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapFields(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
source *sqlserverflexalpha.GetDatabaseResponse
|
||||||
|
model *dataSourceModel
|
||||||
|
region string
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
model *dataSourceModel
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
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\""),
|
||||||
|
},
|
||||||
|
model: &dataSourceModel{
|
||||||
|
DatabaseModel: datasource.DatabaseModel{
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
region: "eu01",
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
model: &dataSourceModel{
|
||||||
|
DatabaseModel: datasource.DatabaseModel{
|
||||||
|
Id: types.Int64Value(1),
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
DatabaseName: types.StringValue("my-db"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
Region: types.StringValue("eu01"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
CompatibilityLevel: types.Int64Value(150),
|
||||||
|
CollationName: types.StringValue("collation"),
|
||||||
|
},
|
||||||
|
TerraformID: types.StringValue("my-project,eu01,my-instance,my-db"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source",
|
||||||
|
given: given{
|
||||||
|
source: nil,
|
||||||
|
model: &dataSourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source ID",
|
||||||
|
given: given{
|
||||||
|
source: &sqlserverflexalpha.GetDatabaseResponse{Id: nil},
|
||||||
|
model: &dataSourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil model",
|
||||||
|
given: given{
|
||||||
|
source: &sqlserverflexalpha.GetDatabaseResponse{Id: utils.Ptr(int64(1))},
|
||||||
|
model: nil,
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
err := mapFields(tc.given.source, tc.given.model, tc.given.region)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.model, tc.given.model); diff != "" {
|
||||||
|
t.Errorf("model mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapResourceFields(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
source *sqlserverflexalpha.GetDatabaseResponse
|
||||||
|
model *resourceModel
|
||||||
|
region string
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
model *resourceModel
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
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\""),
|
||||||
|
},
|
||||||
|
model: &resourceModel{
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
},
|
||||||
|
region: "eu01",
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
model: &resourceModel{
|
||||||
|
Id: types.Int64Value(1),
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
DatabaseName: types.StringValue("my-db"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
Region: types.StringValue("eu01"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source",
|
||||||
|
given: given{
|
||||||
|
source: nil,
|
||||||
|
model: &resourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
err := mapResourceFields(tc.given.source, tc.given.model, tc.given.region)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.model, tc.given.model); diff != "" {
|
||||||
|
t.Errorf("model mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCreatePayload(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
model *resourceModel
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
payload *sqlserverflexalpha.CreateDatabaseRequestPayload
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should convert model to payload",
|
||||||
|
given: given{
|
||||||
|
model: &resourceModel{
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
payload: &sqlserverflexalpha.CreateDatabaseRequestPayload{
|
||||||
|
Name: utils.Ptr("my-db"),
|
||||||
|
Owner: utils.Ptr("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil model",
|
||||||
|
given: given{model: nil},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
actual, err := toCreatePayload(tc.given.model)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.payload, actual); diff != "" {
|
||||||
|
t.Errorf("payload mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@ package sqlserverflexalpha
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -13,6 +15,7 @@ import (
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||||
"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/pkg_gen/sqlserverflexalpha"
|
||||||
"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/conversion"
|
||||||
|
|
||||||
|
|
@ -28,6 +31,13 @@ var (
|
||||||
_ resource.ResourceWithImportState = &databaseResource{}
|
_ resource.ResourceWithImportState = &databaseResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &databaseResource{}
|
_ resource.ResourceWithModifyPlan = &databaseResource{}
|
||||||
_ resource.ResourceWithIdentity = &databaseResource{}
|
_ resource.ResourceWithIdentity = &databaseResource{}
|
||||||
|
|
||||||
|
// Define errors
|
||||||
|
errDatabaseNotFound = errors.New("database not found")
|
||||||
|
|
||||||
|
// Error message constants
|
||||||
|
extractErrorSummary = "extracting failed"
|
||||||
|
extractErrorMessage = "Extracting identity data: %v"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDatabaseResource() resource.Resource {
|
func NewDatabaseResource() resource.Resource {
|
||||||
|
|
@ -137,73 +147,230 @@ func (r *databaseResource) Configure(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *databaseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
func (r *databaseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||||
var data sqlserverflexalphaGen.DatabaseModel
|
var model resourceModel
|
||||||
|
|
||||||
// Read Terraform plan data into the model
|
|
||||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
|
diags := req.Plan.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create API call logic
|
// Read identity data
|
||||||
|
var identityData DatabaseResourceIdentityModel
|
||||||
|
resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Example data value setting
|
ctx = core.InitProviderContext(ctx)
|
||||||
// data.DatabaseId = types.StringValue("id-from-response")
|
|
||||||
|
|
||||||
// Save data into Terraform state
|
projectId := identityData.ProjectID.ValueString()
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
region := identityData.ProjectID.ValueString()
|
||||||
|
instanceId := identityData.InstanceID.ValueString()
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Create new database
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
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
|
||||||
|
databaseName := model.DatabaseName.String()
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "database_id", databaseId)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
database, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating database",
|
||||||
|
fmt.Sprintf("Getting database details after creation: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map response body to schema
|
||||||
|
err = mapResourceFields(database, &model, region)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating database",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
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() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexalpha.Database created")
|
tflog.Info(ctx, "sqlserverflexalpha.Database created")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||||
var data resourceModel
|
var model resourceModel
|
||||||
|
diags := req.State.Get(ctx, &model)
|
||||||
// Read Terraform prior state data into the model
|
resp.Diagnostics.Append(diags...)
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Read API call logic
|
// Read identity data
|
||||||
|
var identityData DatabaseResourceIdentityModel
|
||||||
|
resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
ctx = core.InitProviderContext(ctx)
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
projectId, instanceId, region, databaseName, errExt := r.extractIdentityData(model, identityData)
|
||||||
|
if errExt != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
extractErrorSummary,
|
||||||
|
fmt.Sprintf(extractErrorMessage, errExt),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
databaseResp, err := r.client.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) {
|
||||||
|
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, region)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error reading database",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set refreshed state
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexalpha.Database read")
|
tflog.Info(ctx, "sqlserverflexalpha.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) {
|
||||||
var data resourceModel
|
// 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")
|
||||||
// Read Terraform plan data into the model
|
|
||||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Todo: Update API call logic
|
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexalpha.Database updated")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||||
var data sqlserverflexalphaGen.DatabaseModel
|
// nolint:gocritic // function signature required by Terraform
|
||||||
|
var model resourceModel
|
||||||
// Read Terraform prior state data into the model
|
diags := req.State.Get(ctx, &model)
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
resp.Diagnostics.Append(diags...)
|
||||||
|
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Delete API call logic
|
// Read identity data
|
||||||
|
var identityData DatabaseResourceIdentityModel
|
||||||
|
resp.Diagnostics.Append(req.Identity.Get(ctx, &identityData)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
|
projectId, instanceId, region, databaseName, errExt := r.extractIdentityData(model, identityData)
|
||||||
|
if errExt != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
extractErrorSummary,
|
||||||
|
fmt.Sprintf(extractErrorMessage, errExt),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
// Delete existing record set
|
||||||
|
err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting database", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexalpha.Database deleted")
|
tflog.Info(ctx, "sqlserverflexalpha.Database deleted")
|
||||||
}
|
}
|
||||||
|
|
@ -312,3 +479,46 @@ func (r *databaseResource) ImportState(
|
||||||
|
|
||||||
tflog.Info(ctx, "Sqlserverflexalpha database state imported")
|
tflog.Info(ctx, "Sqlserverflexalpha database state imported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractIdentityData extracts essential identifiers from the resource model, falling back to the identity model.
|
||||||
|
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()
|
||||||
|
} else {
|
||||||
|
if identity.DatabaseName.IsNull() || identity.DatabaseName.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("database_name not found in config")
|
||||||
|
}
|
||||||
|
databaseName = identity.DatabaseName.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.ProjectId.IsNull() && !model.ProjectId.IsUnknown() {
|
||||||
|
projectId = model.ProjectId.ValueString()
|
||||||
|
} else {
|
||||||
|
if identity.ProjectID.IsNull() || identity.ProjectID.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("project_id not found in config")
|
||||||
|
}
|
||||||
|
projectId = identity.ProjectID.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.Region.IsNull() && !model.Region.IsUnknown() {
|
||||||
|
region = r.providerData.GetRegionWithOverride(model.Region)
|
||||||
|
} else {
|
||||||
|
if identity.Region.IsNull() || identity.Region.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("region not found in config")
|
||||||
|
}
|
||||||
|
region = r.providerData.GetRegionWithOverride(identity.Region)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.InstanceId.IsNull() && !model.InstanceId.IsUnknown() {
|
||||||
|
instanceId = model.InstanceId.ValueString()
|
||||||
|
} else {
|
||||||
|
if identity.InstanceID.IsNull() || identity.InstanceID.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("instance_id not found in config")
|
||||||
|
}
|
||||||
|
instanceId = identity.InstanceID.ValueString()
|
||||||
|
}
|
||||||
|
return projectId, region, instanceId, databaseName, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,34 @@ var (
|
||||||
|
|
||||||
var testConfigVarsMin = config.Variables{
|
var testConfigVarsMin = config.Variables{
|
||||||
"project_id": config.StringVariable(testutil.ProjectId),
|
"project_id": config.StringVariable(testutil.ProjectId),
|
||||||
"name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))),
|
"name": config.StringVariable(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"tf-acc-%s",
|
||||||
|
acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum),
|
||||||
|
),
|
||||||
|
),
|
||||||
"flavor_cpu": config.IntegerVariable(4),
|
"flavor_cpu": config.IntegerVariable(4),
|
||||||
"flavor_ram": config.IntegerVariable(16),
|
"flavor_ram": config.IntegerVariable(16),
|
||||||
"flavor_description": config.StringVariable("SQLServer-Flex-4.16-Standard-EU01"),
|
"flavor_description": config.StringVariable("SQLServer-Flex-4.16-Standard-EU01"),
|
||||||
"replicas": config.IntegerVariable(1),
|
"replicas": config.IntegerVariable(1),
|
||||||
"flavor_id": config.StringVariable("4.16-Single"),
|
"flavor_id": config.StringVariable("4.16-Single"),
|
||||||
"username": config.StringVariable(fmt.Sprintf("tf-acc-user-%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlpha))),
|
"username": config.StringVariable(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"tf-acc-user-%s",
|
||||||
|
acctest.RandStringFromCharSet(7, acctest.CharSetAlpha),
|
||||||
|
),
|
||||||
|
),
|
||||||
"role": config.StringVariable("##STACKIT_LoginManager##"),
|
"role": config.StringVariable("##STACKIT_LoginManager##"),
|
||||||
}
|
}
|
||||||
|
|
||||||
var testConfigVarsMax = config.Variables{
|
var testConfigVarsMax = config.Variables{
|
||||||
"project_id": config.StringVariable(testutil.ProjectId),
|
"project_id": config.StringVariable(testutil.ProjectId),
|
||||||
"name": config.StringVariable(fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum))),
|
"name": config.StringVariable(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"tf-acc-%s",
|
||||||
|
acctest.RandStringFromCharSet(7, acctest.CharSetAlphaNum),
|
||||||
|
),
|
||||||
|
),
|
||||||
"acl1": config.StringVariable("192.168.0.0/16"),
|
"acl1": config.StringVariable("192.168.0.0/16"),
|
||||||
"flavor_cpu": config.IntegerVariable(4),
|
"flavor_cpu": config.IntegerVariable(4),
|
||||||
"flavor_ram": config.IntegerVariable(16),
|
"flavor_ram": config.IntegerVariable(16),
|
||||||
|
|
@ -55,7 +70,12 @@ var testConfigVarsMax = config.Variables{
|
||||||
"options_retention_days": config.IntegerVariable(64),
|
"options_retention_days": config.IntegerVariable(64),
|
||||||
"flavor_id": config.StringVariable("4.16-Single"),
|
"flavor_id": config.StringVariable("4.16-Single"),
|
||||||
"backup_schedule": config.StringVariable("00 6 * * *"),
|
"backup_schedule": config.StringVariable("00 6 * * *"),
|
||||||
"username": config.StringVariable(fmt.Sprintf("tf-acc-user-%s", acctest.RandStringFromCharSet(7, acctest.CharSetAlpha))),
|
"username": config.StringVariable(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"tf-acc-user-%s",
|
||||||
|
acctest.RandStringFromCharSet(7, acctest.CharSetAlpha),
|
||||||
|
),
|
||||||
|
),
|
||||||
"role": config.StringVariable("##STACKIT_LoginManager##"),
|
"role": config.StringVariable("##STACKIT_LoginManager##"),
|
||||||
"region": config.StringVariable(testutil.Region),
|
"region": config.StringVariable(testutil.Region),
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +93,8 @@ func configVarsMaxUpdated() config.Variables {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccSQLServerFlexMinResource(t *testing.T) {
|
func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(
|
||||||
|
t, resource.TestCase{
|
||||||
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||||
CheckDestroy: testAccChecksqlserverflexDestroy,
|
CheckDestroy: testAccChecksqlserverflexDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
|
|
@ -83,15 +104,39 @@ func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMin,
|
ConfigVariables: testConfigVarsMin,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance
|
// Instance
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMin["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "replicas", testutil.ConvertConfigVariable(testConfigVarsMin["replicas"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"])),
|
"flavor.description",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"])),
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"replicas",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["replicas"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"]),
|
||||||
|
),
|
||||||
// User
|
// User
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"stackit_sqlserverflex_user.user", "project_id",
|
"stackit_sqlserverflex_user.user", "project_id",
|
||||||
|
|
@ -111,14 +156,34 @@ func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMin,
|
ConfigVariables: testConfigVarsMin,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance
|
// Instance
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMin["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"])),
|
"flavor.description",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"]),
|
||||||
|
),
|
||||||
// User
|
// User
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"stackit_sqlserverflex_user.user", "project_id",
|
"stackit_sqlserverflex_user.user", "project_id",
|
||||||
|
|
@ -138,8 +203,16 @@ func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMin,
|
ConfigVariables: testConfigVarsMin,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance data
|
// Instance data
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMin["name"])),
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["project_id"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"data.stackit_sqlserverflex_instance.instance", "project_id",
|
"data.stackit_sqlserverflex_instance.instance", "project_id",
|
||||||
"stackit_sqlserverflex_instance.instance", "project_id",
|
"stackit_sqlserverflex_instance.instance", "project_id",
|
||||||
|
|
@ -154,17 +227,45 @@ func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
),
|
),
|
||||||
|
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.id", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"])),
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"])),
|
"flavor.id",
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"])),
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_id"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.description",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_description"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["flavor_ram"]),
|
||||||
|
),
|
||||||
|
|
||||||
// User data
|
// User data
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "project_id", testutil.ConvertConfigVariable(testConfigVarsMin["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "user_id"),
|
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "user_id"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "username", testutil.ConvertConfigVariable(testConfigVarsMin["username"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"username",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMin["username"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.#", "1"),
|
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.#", "1"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.0", testutil.ConvertConfigVariable(testConfigVarsMax["role"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"roles.0",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["role"]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// Import
|
// Import
|
||||||
|
|
@ -222,23 +323,44 @@ func TestAccSQLServerFlexMinResource(t *testing.T) {
|
||||||
ConfigVariables: configVarsMinUpdated(),
|
ConfigVariables: configVarsMinUpdated(),
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance data
|
// Instance data
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(configVarsMinUpdated()["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMinUpdated()["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(configVarsMinUpdated()["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMinUpdated()["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.description"),
|
resource.TestCheckResourceAttrSet(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(configVarsMinUpdated()["flavor_cpu"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(configVarsMinUpdated()["flavor_ram"])),
|
"flavor.description",
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMinUpdated()["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMinUpdated()["flavor_ram"]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// Deletion is done by the framework implicitly
|
// Deletion is done by the framework implicitly
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(
|
||||||
|
t, resource.TestCase{
|
||||||
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||||
CheckDestroy: testAccChecksqlserverflexDestroy,
|
CheckDestroy: testAccChecksqlserverflexDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
|
|
@ -248,22 +370,74 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMax,
|
ConfigVariables: testConfigVarsMax,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance
|
// Instance
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMax["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl1"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"acl.0",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["acl1"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "replicas", testutil.ConvertConfigVariable(testConfigVarsMax["replicas"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"])),
|
"flavor.description",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"])),
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"]),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.class", testutil.ConvertConfigVariable(testConfigVarsMax["storage_class"])),
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.size", testutil.ConvertConfigVariable(testConfigVarsMax["storage_size"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "version", testutil.ConvertConfigVariable(testConfigVarsMax["server_version"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "options.retention_days", testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"])),
|
"replicas",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "backup_schedule", testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"])),
|
testutil.ConvertConfigVariable(testConfigVarsMax["replicas"]),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "region", testutil.Region),
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.class",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["storage_class"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.size",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["storage_size"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"version",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["server_version"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"options.retention_days",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"backup_schedule",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"region",
|
||||||
|
testutil.Region,
|
||||||
|
),
|
||||||
// User
|
// User
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"stackit_sqlserverflex_user.user", "project_id",
|
"stackit_sqlserverflex_user.user", "project_id",
|
||||||
|
|
@ -283,22 +457,74 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMax,
|
ConfigVariables: testConfigVarsMax,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance
|
// Instance
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMax["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl1"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"acl.0",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["acl1"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "replicas", testutil.ConvertConfigVariable(testConfigVarsMax["replicas"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"])),
|
"flavor.description",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"])),
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"]),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.class", testutil.ConvertConfigVariable(testConfigVarsMax["storage_class"])),
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.size", testutil.ConvertConfigVariable(testConfigVarsMax["storage_size"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "version", testutil.ConvertConfigVariable(testConfigVarsMax["server_version"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "options.retention_days", testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"])),
|
"replicas",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "backup_schedule", testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"])),
|
testutil.ConvertConfigVariable(testConfigVarsMax["replicas"]),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "region", testutil.Region),
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.class",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["storage_class"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.size",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["storage_size"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"version",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["server_version"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"options.retention_days",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"backup_schedule",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"region",
|
||||||
|
testutil.Region,
|
||||||
|
),
|
||||||
// User
|
// User
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"stackit_sqlserverflex_user.user", "project_id",
|
"stackit_sqlserverflex_user.user", "project_id",
|
||||||
|
|
@ -318,8 +544,16 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
ConfigVariables: testConfigVarsMax,
|
ConfigVariables: testConfigVarsMax,
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance data
|
// Instance data
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(testConfigVarsMax["name"])),
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["project_id"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrPair(
|
resource.TestCheckResourceAttrPair(
|
||||||
"data.stackit_sqlserverflex_instance.instance", "project_id",
|
"data.stackit_sqlserverflex_instance.instance", "project_id",
|
||||||
"stackit_sqlserverflex_instance.instance", "project_id",
|
"stackit_sqlserverflex_instance.instance", "project_id",
|
||||||
|
|
@ -334,21 +568,65 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
),
|
),
|
||||||
|
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "acl.0", testutil.ConvertConfigVariable(testConfigVarsMax["acl1"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.id", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_id"])),
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.description", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"])),
|
"acl.0",
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"])),
|
testutil.ConvertConfigVariable(testConfigVarsMax["acl1"]),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"])),
|
),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "replicas", testutil.ConvertConfigVariable(testConfigVarsMax["replicas"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "options.retention_days", testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"])),
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_instance.instance", "backup_schedule", testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"])),
|
"flavor.id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_id"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.description",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_description"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.cpu",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_cpu"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["flavor_ram"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"replicas",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["replicas"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"options.retention_days",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["options_retention_days"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_instance.instance",
|
||||||
|
"backup_schedule",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"]),
|
||||||
|
),
|
||||||
|
|
||||||
// User data
|
// User data
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "project_id", testutil.ConvertConfigVariable(testConfigVarsMax["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "user_id"),
|
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "user_id"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "username", testutil.ConvertConfigVariable(testConfigVarsMax["username"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"username",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["username"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.#", "1"),
|
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.#", "1"),
|
||||||
resource.TestCheckResourceAttr("data.stackit_sqlserverflex_user.user", "roles.0", testutil.ConvertConfigVariable(testConfigVarsMax["role"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"data.stackit_sqlserverflex_user.user",
|
||||||
|
"roles.0",
|
||||||
|
testutil.ConvertConfigVariable(testConfigVarsMax["role"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "host"),
|
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "host"),
|
||||||
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "port"),
|
resource.TestCheckResourceAttrSet("data.stackit_sqlserverflex_user.user", "port"),
|
||||||
),
|
),
|
||||||
|
|
@ -377,7 +655,11 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
return fmt.Errorf("expected 1 state, got %d", len(s))
|
return fmt.Errorf("expected 1 state, got %d", len(s))
|
||||||
}
|
}
|
||||||
if s[0].Attributes["backup_schedule"] != testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"]) {
|
if s[0].Attributes["backup_schedule"] != testutil.ConvertConfigVariable(testConfigVarsMax["backup_schedule"]) {
|
||||||
return fmt.Errorf("expected backup_schedule %s, got %s", testConfigVarsMax["backup_schedule"], s[0].Attributes["backup_schedule"])
|
return fmt.Errorf(
|
||||||
|
"expected backup_schedule %s, got %s",
|
||||||
|
testConfigVarsMax["backup_schedule"],
|
||||||
|
s[0].Attributes["backup_schedule"],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
@ -411,26 +693,74 @@ func TestAccSQLServerFlexMaxResource(t *testing.T) {
|
||||||
ConfigVariables: configVarsMaxUpdated(),
|
ConfigVariables: configVarsMaxUpdated(),
|
||||||
Check: resource.ComposeAggregateTestCheckFunc(
|
Check: resource.ComposeAggregateTestCheckFunc(
|
||||||
// Instance data
|
// Instance data
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "project_id", testutil.ConvertConfigVariable(configVarsMaxUpdated()["project_id"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"project_id",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["project_id"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "instance_id"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "name", testutil.ConvertConfigVariable(configVarsMaxUpdated()["name"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"name",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["name"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.#", "1"),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "acl.0", testutil.ConvertConfigVariable(configVarsMaxUpdated()["acl1"])),
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"acl.0",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["acl1"]),
|
||||||
|
),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.id"),
|
||||||
resource.TestCheckResourceAttrSet("stackit_sqlserverflex_instance.instance", "flavor.description"),
|
resource.TestCheckResourceAttrSet(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.cpu", testutil.ConvertConfigVariable(configVarsMaxUpdated()["flavor_cpu"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "flavor.ram", testutil.ConvertConfigVariable(configVarsMaxUpdated()["flavor_ram"])),
|
"flavor.description",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "replicas", testutil.ConvertConfigVariable(configVarsMaxUpdated()["replicas"])),
|
),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.class", testutil.ConvertConfigVariable(configVarsMaxUpdated()["storage_class"])),
|
resource.TestCheckResourceAttr(
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "storage.size", testutil.ConvertConfigVariable(configVarsMaxUpdated()["storage_size"])),
|
"stackit_sqlserverflex_instance.instance",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "version", testutil.ConvertConfigVariable(configVarsMaxUpdated()["server_version"])),
|
"flavor.cpu",
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "options.retention_days", testutil.ConvertConfigVariable(configVarsMaxUpdated()["options_retention_days"])),
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["flavor_cpu"]),
|
||||||
resource.TestCheckResourceAttr("stackit_sqlserverflex_instance.instance", "backup_schedule", testutil.ConvertConfigVariable(configVarsMaxUpdated()["backup_schedule"])),
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"flavor.ram",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["flavor_ram"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"replicas",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["replicas"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.class",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["storage_class"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"storage.size",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["storage_size"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"version",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["server_version"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"options.retention_days",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["options_retention_days"]),
|
||||||
|
),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"stackit_sqlserverflex_instance.instance",
|
||||||
|
"backup_schedule",
|
||||||
|
testutil.ConvertConfigVariable(configVarsMaxUpdated()["backup_schedule"]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// Deletion is done by the framework implicitly
|
// Deletion is done by the framework implicitly
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccChecksqlserverflexDestroy(s *terraform.State) error {
|
func testAccChecksqlserverflexDestroy(s *terraform.State) error {
|
||||||
|
|
@ -473,9 +803,19 @@ func testAccChecksqlserverflexDestroy(s *terraform.State) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("destroying instance %s during CheckDestroy: %w", *items[i].Id, err)
|
return fmt.Errorf("destroying instance %s during CheckDestroy: %w", *items[i].Id, err)
|
||||||
}
|
}
|
||||||
_, err = wait.DeleteInstanceWaitHandler(ctx, client, testutil.ProjectId, *items[i].Id, testutil.Region).WaitWithContext(ctx)
|
_, err = wait.DeleteInstanceWaitHandler(
|
||||||
|
ctx,
|
||||||
|
client,
|
||||||
|
testutil.ProjectId,
|
||||||
|
*items[i].Id,
|
||||||
|
testutil.Region,
|
||||||
|
).WaitWithContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("destroying instance %s during CheckDestroy: waiting for deletion %w", *items[i].Id, err)
|
return fmt.Errorf(
|
||||||
|
"destroying instance %s during CheckDestroy: waiting for deletion %w",
|
||||||
|
*items[i].Id,
|
||||||
|
err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,19 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
"github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"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/pkg_gen/sqlserverflexalpha"
|
||||||
"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/conversion"
|
||||||
sqlserverflexUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/utils"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
|
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
|
||||||
"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/core"
|
||||||
|
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"
|
"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/stackit/internal/validate"
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/validate"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure the implementation satisfies the expected interfaces.
|
// Ensure the implementation satisfies the expected interfaces.
|
||||||
|
|
@ -34,6 +30,7 @@ func NewUserDataSource() datasource.DataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
type dataSourceModel struct {
|
type dataSourceModel struct {
|
||||||
|
//TODO: check generated data source for the correct types and pointers
|
||||||
Id types.String `tfsdk:"id"` // needed by TF
|
Id types.String `tfsdk:"id"` // needed by TF
|
||||||
UserId types.Int64 `tfsdk:"user_id"`
|
UserId types.Int64 `tfsdk:"user_id"`
|
||||||
InstanceId types.String `tfsdk:"instance_id"`
|
InstanceId types.String `tfsdk:"instance_id"`
|
||||||
|
|
@ -79,7 +76,7 @@ func (r *userDataSource) Configure(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.client = apiClient
|
r.client = apiClient
|
||||||
tflog.Info(ctx, "SQLServer Flex user client configured")
|
tflog.Info(ctx, "SQLServer Flex beta user client configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schema defines the schema for the data source.
|
// Schema defines the schema for the data source.
|
||||||
|
|
@ -223,50 +220,5 @@ func (r *userDataSource) Read(
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tflog.Info(ctx, "SQLServer Flex instance read")
|
tflog.Info(ctx, "SQLServer Flex alpha instance read")
|
||||||
}
|
|
||||||
|
|
||||||
func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *dataSourceModel, region string) error {
|
|
||||||
if userResp == nil {
|
|
||||||
return fmt.Errorf("response is nil")
|
|
||||||
}
|
|
||||||
if model == nil {
|
|
||||||
return fmt.Errorf("model input is nil")
|
|
||||||
}
|
|
||||||
user := userResp
|
|
||||||
|
|
||||||
var userId int64
|
|
||||||
if model.UserId.ValueInt64() != 0 {
|
|
||||||
userId = model.UserId.ValueInt64()
|
|
||||||
} else if user.Id != nil {
|
|
||||||
userId = *user.Id
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("user id not present")
|
|
||||||
}
|
|
||||||
model.Id = utils.BuildInternalTerraformId(
|
|
||||||
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
|
|
||||||
)
|
|
||||||
model.UserId = types.Int64Value(userId)
|
|
||||||
model.Username = types.StringPointerValue(user.Username)
|
|
||||||
|
|
||||||
if user.Roles == nil {
|
|
||||||
model.Roles = types.SetNull(types.StringType)
|
|
||||||
} else {
|
|
||||||
var roles []attr.Value
|
|
||||||
for _, role := range *user.Roles {
|
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
|
||||||
}
|
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
|
||||||
if diags.HasError() {
|
|
||||||
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
|
||||||
}
|
|
||||||
model.Roles = rolesSet
|
|
||||||
}
|
|
||||||
model.Host = types.StringPointerValue(user.Host)
|
|
||||||
model.Port = types.Int64PointerValue(user.Port)
|
|
||||||
model.Region = types.StringValue(region)
|
|
||||||
model.Status = types.StringPointerValue(user.Status)
|
|
||||||
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
package sqlserverflexalpha
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"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"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMapDataSourceFields(t *testing.T) {
|
|
||||||
const testRegion = "region"
|
|
||||||
tests := []struct {
|
|
||||||
description string
|
|
||||||
input *sqlserverflexalpha.GetUserResponse
|
|
||||||
region string
|
|
||||||
expected dataSourceModel
|
|
||||||
isValid bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"default_values",
|
|
||||||
&sqlserverflexalpha.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(),
|
|
||||||
Roles: types.SetNull(types.StringType),
|
|
||||||
Host: types.StringNull(),
|
|
||||||
Port: types.Int64Null(),
|
|
||||||
Region: types.StringValue(testRegion),
|
|
||||||
Status: types.StringNull(),
|
|
||||||
DefaultDatabase: types.StringNull(),
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"simple_values",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{
|
|
||||||
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{
|
|
||||||
"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"),
|
|
||||||
},
|
|
||||||
testRegion,
|
|
||||||
dataSourceModel{
|
|
||||||
Id: types.StringValue("pid,region,iid,1"),
|
|
||||||
UserId: types.Int64Value(1),
|
|
||||||
InstanceId: types.StringValue("iid"),
|
|
||||||
ProjectId: types.StringValue("pid"),
|
|
||||||
Username: types.StringValue("username"),
|
|
||||||
Roles: types.SetValueMust(
|
|
||||||
types.StringType, []attr.Value{
|
|
||||||
types.StringValue("role_1"),
|
|
||||||
types.StringValue("role_2"),
|
|
||||||
types.StringValue(""),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Host: types.StringValue("host"),
|
|
||||||
Port: types.Int64Value(1234),
|
|
||||||
Region: types.StringValue(testRegion),
|
|
||||||
Status: types.StringValue("active"),
|
|
||||||
DefaultDatabase: types.StringValue("default_db"),
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"null_fields_and_int_conversions",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{
|
|
||||||
Id: utils.Ptr(int64(1)),
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{},
|
|
||||||
Username: nil,
|
|
||||||
Host: nil,
|
|
||||||
Port: utils.Ptr(int64(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.SetValueMust(types.StringType, []attr.Value{}),
|
|
||||||
Host: types.StringNull(),
|
|
||||||
Port: types.Int64Value(2123456789),
|
|
||||||
Region: types.StringValue(testRegion),
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_response",
|
|
||||||
nil,
|
|
||||||
testRegion,
|
|
||||||
dataSourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_response_2",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
dataSourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"no_resource_id",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
dataSourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(
|
|
||||||
tt.description, func(t *testing.T) {
|
|
||||||
state := &dataSourceModel{
|
|
||||||
ProjectId: tt.expected.ProjectId,
|
|
||||||
InstanceId: tt.expected.InstanceId,
|
|
||||||
UserId: tt.expected.UserId,
|
|
||||||
}
|
|
||||||
err := mapDataSourceFields(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
179
stackit/internal/services/sqlserverflexalpha/user/mapper.go
Normal file
179
stackit/internal/services/sqlserverflexalpha/user/mapper.go
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
package sqlserverflexalpha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"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 {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
// Handle user ID
|
||||||
|
var userId int64
|
||||||
|
if model.UserId.ValueInt64() != 0 {
|
||||||
|
userId = model.UserId.ValueInt64()
|
||||||
|
} else if user.Id != nil {
|
||||||
|
userId = *user.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("user id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set main attributes
|
||||||
|
model.Id = utils.BuildInternalTerraformId(
|
||||||
|
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
|
||||||
|
)
|
||||||
|
model.UserId = types.Int64Value(userId)
|
||||||
|
model.Username = types.StringPointerValue(user.Username)
|
||||||
|
|
||||||
|
// Map roles
|
||||||
|
if user.Roles == nil {
|
||||||
|
model.Roles = types.SetNull(types.StringType)
|
||||||
|
} else {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = rolesSet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set remaining attributes
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(user.Port)
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.Status = types.StringPointerValue(user.Status)
|
||||||
|
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapFields maps the API response to a resourceModel.
|
||||||
|
func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceModel, region string) error {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
// Handle user ID
|
||||||
|
var userId int64
|
||||||
|
if model.UserId.ValueInt64() != 0 {
|
||||||
|
userId = model.UserId.ValueInt64()
|
||||||
|
} else if user.Id != nil {
|
||||||
|
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)
|
||||||
|
|
||||||
|
// Map roles
|
||||||
|
if user.Roles != nil {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = types.List(rolesSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure roles is not null
|
||||||
|
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
||||||
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set connection details
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(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 {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
if user.Id == nil {
|
||||||
|
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)
|
||||||
|
|
||||||
|
if user.Password == nil {
|
||||||
|
return fmt.Errorf("user password not present")
|
||||||
|
}
|
||||||
|
model.Password = types.StringValue(*user.Password)
|
||||||
|
|
||||||
|
if user.Roles != nil {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = types.List(rolesSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
||||||
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(user.Port)
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.Status = types.StringPointerValue(user.Status)
|
||||||
|
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCreatePayload converts a resourceModel to an API CreateUserRequestPayload.
|
||||||
|
func toCreatePayload(
|
||||||
|
model *resourceModel,
|
||||||
|
roles []sqlserverflexalpha.UserRole,
|
||||||
|
) (*sqlserverflexalpha.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
|
||||||
|
}
|
||||||
525
stackit/internal/services/sqlserverflexalpha/user/mapper_test.go
Normal file
525
stackit/internal/services/sqlserverflexalpha/user/mapper_test.go
Normal file
|
|
@ -0,0 +1,525 @@
|
||||||
|
package sqlserverflexalpha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapDataSourceFields(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexalpha.GetUserResponse
|
||||||
|
region string
|
||||||
|
expected dataSourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexalpha.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(),
|
||||||
|
Roles: types.SetNull(types.StringType),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Null(),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringNull(),
|
||||||
|
DefaultDatabase: types.StringNull(),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{
|
||||||
|
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{
|
||||||
|
"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"),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{
|
||||||
|
Id: types.StringValue("pid,region,iid,1"),
|
||||||
|
UserId: types.Int64Value(1),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringValue("active"),
|
||||||
|
DefaultDatabase: types.StringValue("default_db"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(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.SetValueMust(types.StringType, []attr.Value{}),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Value(2123456789),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response_2",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_resource_id",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &dataSourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
UserId: tt.expected.UserId,
|
||||||
|
}
|
||||||
|
err := mapDataSourceFields(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFieldsCreate(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexalpha.CreateUserResponse
|
||||||
|
region string
|
||||||
|
expected resourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Password: utils.Ptr(""),
|
||||||
|
},
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(2)),
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{
|
||||||
|
"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"),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(2),
|
||||||
|
UserId: types.Int64Value(2),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.List(
|
||||||
|
types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Password: types.StringValue("password"),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringValue("status"),
|
||||||
|
DefaultDatabase: types.StringValue("default_db"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(3)),
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Password: utils.Ptr(""),
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(2123456789)),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(3),
|
||||||
|
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),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
DefaultDatabase: types.StringNull(),
|
||||||
|
Status: types.StringNull(),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response_2",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_resource_id",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_password",
|
||||||
|
&sqlserverflexalpha.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &resourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
}
|
||||||
|
err := mapFieldsCreate(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFields(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexalpha.GetUserResponse
|
||||||
|
region string
|
||||||
|
expected resourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{},
|
||||||
|
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)),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Null(),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
Host: utils.Ptr("host"),
|
||||||
|
Port: utils.Ptr(int64(1234)),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(2),
|
||||||
|
UserId: types.Int64Value(2),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.List(
|
||||||
|
types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(2123456789)),
|
||||||
|
},
|
||||||
|
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.SetValueMust(types.StringType, []attr.Value{})),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Value(2123456789),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response_2",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_resource_id",
|
||||||
|
&sqlserverflexalpha.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &resourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
UserId: tt.expected.UserId,
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCreatePayload(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *resourceModel
|
||||||
|
inputRoles []sqlserverflexalpha.UserRole
|
||||||
|
expected *sqlserverflexalpha.CreateUserRequestPayload
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&resourceModel{},
|
||||||
|
[]sqlserverflexalpha.UserRole{},
|
||||||
|
&sqlserverflexalpha.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
},
|
||||||
|
[]sqlserverflexalpha.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
},
|
||||||
|
&sqlserverflexalpha.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringNull(),
|
||||||
|
},
|
||||||
|
[]sqlserverflexalpha.UserRole{
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
&sqlserverflexalpha.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
Username: nil,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_model",
|
||||||
|
nil,
|
||||||
|
[]sqlserverflexalpha.UserRole{},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_roles",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
},
|
||||||
|
[]sqlserverflexalpha.UserRole{},
|
||||||
|
&sqlserverflexalpha.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexalpha.UserRole{},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
output, err := toCreatePayload(tt.input, tt.inputRoles)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,12 +9,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
|
||||||
"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/pkg_gen/sqlserverflexalpha"
|
||||||
sqlserverflexalphagen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user/resources_gen"
|
sqlserverflexalphagen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user/resources_gen"
|
||||||
sqlserverflexalphaUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/utils"
|
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"
|
sqlserverflexalphaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexalpha"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
|
@ -31,6 +31,7 @@ var (
|
||||||
_ resource.ResourceWithConfigure = &userResource{}
|
_ resource.ResourceWithConfigure = &userResource{}
|
||||||
_ resource.ResourceWithImportState = &userResource{}
|
_ resource.ResourceWithImportState = &userResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &userResource{}
|
_ resource.ResourceWithModifyPlan = &userResource{}
|
||||||
|
_ resource.ResourceWithIdentity = &userResource{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewUserResource is a helper function to simplify the provider implementation.
|
// NewUserResource is a helper function to simplify the provider implementation.
|
||||||
|
|
@ -131,6 +132,30 @@ func (r *userResource) Schema(ctx context.Context, _ resource.SchemaRequest, res
|
||||||
resp.Schema = s
|
resp.Schema = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IdentitySchema defines the schema for the resource's identity attributes.
|
||||||
|
func (r *userResource) IdentitySchema(
|
||||||
|
_ context.Context,
|
||||||
|
_ resource.IdentitySchemaRequest,
|
||||||
|
response *resource.IdentitySchemaResponse,
|
||||||
|
) {
|
||||||
|
response.IdentitySchema = identityschema.Schema{
|
||||||
|
Attributes: map[string]identityschema.Attribute{
|
||||||
|
"project_id": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // must be set during import by the practitioner
|
||||||
|
},
|
||||||
|
"region": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
"instance_id": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
"user_id": identityschema.Int64Attribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create creates the resource and sets the initial Terraform state.
|
// Create creates the resource and sets the initial Terraform state.
|
||||||
func (r *userResource) Create(
|
func (r *userResource) Create(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|
@ -402,109 +427,3 @@ func (r *userResource) ImportState(
|
||||||
)
|
)
|
||||||
tflog.Info(ctx, "SQLServer Flex user state imported")
|
tflog.Info(ctx, "SQLServer Flex user state imported")
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *resourceModel, region string) error {
|
|
||||||
if userResp == nil {
|
|
||||||
return fmt.Errorf("response is nil")
|
|
||||||
}
|
|
||||||
if model == nil {
|
|
||||||
return fmt.Errorf("model input is nil")
|
|
||||||
}
|
|
||||||
user := userResp
|
|
||||||
|
|
||||||
if user.Id == nil {
|
|
||||||
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)
|
|
||||||
|
|
||||||
if user.Password == nil {
|
|
||||||
return fmt.Errorf("user password not present")
|
|
||||||
}
|
|
||||||
model.Password = types.StringValue(*user.Password)
|
|
||||||
|
|
||||||
if user.Roles != nil {
|
|
||||||
var roles []attr.Value
|
|
||||||
for _, role := range *user.Roles {
|
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
|
||||||
}
|
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
|
||||||
if diags.HasError() {
|
|
||||||
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
|
||||||
}
|
|
||||||
model.Roles = types.List(rolesSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
|
||||||
model.Roles = types.List(types.SetNull(types.StringType))
|
|
||||||
}
|
|
||||||
|
|
||||||
model.Host = types.StringPointerValue(user.Host)
|
|
||||||
model.Port = types.Int64PointerValue(user.Port)
|
|
||||||
model.Region = types.StringValue(region)
|
|
||||||
model.Status = types.StringPointerValue(user.Status)
|
|
||||||
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceModel, region string) error {
|
|
||||||
if userResp == nil {
|
|
||||||
return fmt.Errorf("response is nil")
|
|
||||||
}
|
|
||||||
if model == nil {
|
|
||||||
return fmt.Errorf("model input is nil")
|
|
||||||
}
|
|
||||||
user := userResp
|
|
||||||
|
|
||||||
var userId int64
|
|
||||||
if model.UserId.ValueInt64() != 0 {
|
|
||||||
userId = model.UserId.ValueInt64()
|
|
||||||
} else if user.Id != nil {
|
|
||||||
userId = *user.Id
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("user id not present")
|
|
||||||
}
|
|
||||||
|
|
||||||
model.Id = types.Int64Value(userId)
|
|
||||||
model.UserId = types.Int64Value(userId)
|
|
||||||
model.Username = types.StringPointerValue(user.Username)
|
|
||||||
|
|
||||||
if user.Roles != nil {
|
|
||||||
var roles []attr.Value
|
|
||||||
for _, role := range *user.Roles {
|
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
|
||||||
}
|
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
|
||||||
if diags.HasError() {
|
|
||||||
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
|
||||||
}
|
|
||||||
model.Roles = types.List(rolesSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
|
||||||
model.Roles = types.List(types.SetNull(types.StringType))
|
|
||||||
}
|
|
||||||
|
|
||||||
model.Host = types.StringPointerValue(user.Host)
|
|
||||||
model.Port = types.Int64PointerValue(user.Port)
|
|
||||||
model.Region = types.StringValue(region)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func toCreatePayload(
|
|
||||||
model *resourceModel,
|
|
||||||
roles []sqlserverflexalpha.UserRole,
|
|
||||||
) (*sqlserverflexalpha.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
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,388 +0,0 @@
|
||||||
package sqlserverflexalpha
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"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"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMapFieldsCreate(t *testing.T) {
|
|
||||||
const testRegion = "region"
|
|
||||||
tests := []struct {
|
|
||||||
description string
|
|
||||||
input *sqlserverflexalpha.CreateUserResponse
|
|
||||||
region string
|
|
||||||
expected resourceModel
|
|
||||||
isValid bool
|
|
||||||
}{
|
|
||||||
//{
|
|
||||||
// "default_values",
|
|
||||||
// &sqlserverflexalpha.CreateUserResponse{
|
|
||||||
// Id: utils.Ptr(int64(1)),
|
|
||||||
// Password: utils.Ptr(""),
|
|
||||||
// },
|
|
||||||
// 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),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
//{
|
|
||||||
// "simple_values",
|
|
||||||
// &sqlserverflexalpha.CreateUserResponse{
|
|
||||||
// Id: utils.Ptr(int64(2)),
|
|
||||||
// Roles: &[]sqlserverflexalpha.UserRole{
|
|
||||||
// "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"),
|
|
||||||
// },
|
|
||||||
// testRegion,
|
|
||||||
// resourceModel{
|
|
||||||
// Id: types.Int64Value(2),
|
|
||||||
// UserId: types.Int64Value(2),
|
|
||||||
// InstanceId: types.StringValue("iid"),
|
|
||||||
// ProjectId: types.StringValue("pid"),
|
|
||||||
// Username: types.StringValue("username"),
|
|
||||||
// Roles: types.List(
|
|
||||||
// types.SetValueMust(
|
|
||||||
// types.StringType, []attr.Value{
|
|
||||||
// types.StringValue("role_1"),
|
|
||||||
// types.StringValue("role_2"),
|
|
||||||
// types.StringValue(""),
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Password: types.StringValue("password"),
|
|
||||||
// Host: types.StringValue("host"),
|
|
||||||
// Port: types.Int64Value(1234),
|
|
||||||
// Region: types.StringValue(testRegion),
|
|
||||||
// Status: types.StringValue("status"),
|
|
||||||
// DefaultDatabase: types.StringValue("default_db"),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
//{
|
|
||||||
// "null_fields_and_int_conversions",
|
|
||||||
// &sqlserverflexalpha.CreateUserResponse{
|
|
||||||
// Id: utils.Ptr(int64(3)),
|
|
||||||
// Roles: &[]sqlserverflexalpha.UserRole{},
|
|
||||||
// Username: nil,
|
|
||||||
// Password: utils.Ptr(""),
|
|
||||||
// Host: nil,
|
|
||||||
// Port: utils.Ptr(int64(2123456789)),
|
|
||||||
// },
|
|
||||||
// testRegion,
|
|
||||||
// resourceModel{
|
|
||||||
// Id: types.Int64Value(3),
|
|
||||||
// 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),
|
|
||||||
// Region: types.StringValue(testRegion),
|
|
||||||
// DefaultDatabase: types.StringNull(),
|
|
||||||
// Status: types.StringNull(),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
{
|
|
||||||
"nil_response",
|
|
||||||
nil,
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_response_2",
|
|
||||||
&sqlserverflexalpha.CreateUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"no_resource_id",
|
|
||||||
&sqlserverflexalpha.CreateUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"no_password",
|
|
||||||
&sqlserverflexalpha.CreateUserResponse{
|
|
||||||
Id: utils.Ptr(int64(1)),
|
|
||||||
},
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(
|
|
||||||
tt.description, func(t *testing.T) {
|
|
||||||
state := &resourceModel{
|
|
||||||
ProjectId: tt.expected.ProjectId,
|
|
||||||
InstanceId: tt.expected.InstanceId,
|
|
||||||
}
|
|
||||||
err := mapFieldsCreate(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapFields(t *testing.T) {
|
|
||||||
const testRegion = "region"
|
|
||||||
tests := []struct {
|
|
||||||
description string
|
|
||||||
input *sqlserverflexalpha.GetUserResponse
|
|
||||||
region string
|
|
||||||
expected resourceModel
|
|
||||||
isValid bool
|
|
||||||
}{
|
|
||||||
//{
|
|
||||||
// "default_values",
|
|
||||||
// &sqlserverflexalpha.GetUserResponse{},
|
|
||||||
// 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)),
|
|
||||||
// Host: types.StringNull(),
|
|
||||||
// Port: types.Int64Null(),
|
|
||||||
// Region: types.StringValue(testRegion),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
//{
|
|
||||||
// "simple_values",
|
|
||||||
// &sqlserverflexalpha.GetUserResponse{
|
|
||||||
// Roles: &[]sqlserverflexalpha.UserRole{
|
|
||||||
// "role_1",
|
|
||||||
// "role_2",
|
|
||||||
// "",
|
|
||||||
// },
|
|
||||||
// Username: utils.Ptr("username"),
|
|
||||||
// Host: utils.Ptr("host"),
|
|
||||||
// Port: utils.Ptr(int64(1234)),
|
|
||||||
// },
|
|
||||||
// testRegion,
|
|
||||||
// resourceModel{
|
|
||||||
// Id: types.Int64Value(2),
|
|
||||||
// UserId: types.Int64Value(2),
|
|
||||||
// InstanceId: types.StringValue("iid"),
|
|
||||||
// ProjectId: types.StringValue("pid"),
|
|
||||||
// Username: types.StringValue("username"),
|
|
||||||
// Roles: types.List(
|
|
||||||
// types.SetValueMust(
|
|
||||||
// types.StringType, []attr.Value{
|
|
||||||
// types.StringValue("role_1"),
|
|
||||||
// types.StringValue("role_2"),
|
|
||||||
// types.StringValue(""),
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Host: types.StringValue("host"),
|
|
||||||
// Port: types.Int64Value(1234),
|
|
||||||
// Region: types.StringValue(testRegion),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
//{
|
|
||||||
// "null_fields_and_int_conversions",
|
|
||||||
// &sqlserverflexalpha.GetUserResponse{
|
|
||||||
// Id: utils.Ptr(int64(1)),
|
|
||||||
// Roles: &[]sqlserverflexalpha.UserRole{},
|
|
||||||
// Username: nil,
|
|
||||||
// Host: nil,
|
|
||||||
// Port: utils.Ptr(int64(2123456789)),
|
|
||||||
// },
|
|
||||||
// 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.SetValueMust(types.StringType, []attr.Value{})),
|
|
||||||
// Host: types.StringNull(),
|
|
||||||
// Port: types.Int64Value(2123456789),
|
|
||||||
// Region: types.StringValue(testRegion),
|
|
||||||
// },
|
|
||||||
// true,
|
|
||||||
//},
|
|
||||||
{
|
|
||||||
"nil_response",
|
|
||||||
nil,
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_response_2",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"no_resource_id",
|
|
||||||
&sqlserverflexalpha.GetUserResponse{},
|
|
||||||
testRegion,
|
|
||||||
resourceModel{},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(
|
|
||||||
tt.description, func(t *testing.T) {
|
|
||||||
state := &resourceModel{
|
|
||||||
ProjectId: tt.expected.ProjectId,
|
|
||||||
InstanceId: tt.expected.InstanceId,
|
|
||||||
UserId: tt.expected.UserId,
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToCreatePayload(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
description string
|
|
||||||
input *resourceModel
|
|
||||||
inputRoles []sqlserverflexalpha.UserRole
|
|
||||||
expected *sqlserverflexalpha.CreateUserRequestPayload
|
|
||||||
isValid bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"default_values",
|
|
||||||
&resourceModel{},
|
|
||||||
[]sqlserverflexalpha.UserRole{},
|
|
||||||
&sqlserverflexalpha.CreateUserRequestPayload{
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{},
|
|
||||||
Username: nil,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default_values",
|
|
||||||
&resourceModel{
|
|
||||||
Username: types.StringValue("username"),
|
|
||||||
},
|
|
||||||
[]sqlserverflexalpha.UserRole{
|
|
||||||
"role_1",
|
|
||||||
"role_2",
|
|
||||||
},
|
|
||||||
&sqlserverflexalpha.CreateUserRequestPayload{
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{
|
|
||||||
"role_1",
|
|
||||||
"role_2",
|
|
||||||
},
|
|
||||||
Username: utils.Ptr("username"),
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"null_fields_and_int_conversions",
|
|
||||||
&resourceModel{
|
|
||||||
Username: types.StringNull(),
|
|
||||||
},
|
|
||||||
[]sqlserverflexalpha.UserRole{
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
&sqlserverflexalpha.CreateUserRequestPayload{
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
Username: nil,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_model",
|
|
||||||
nil,
|
|
||||||
[]sqlserverflexalpha.UserRole{},
|
|
||||||
nil,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"nil_roles",
|
|
||||||
&resourceModel{
|
|
||||||
Username: types.StringValue("username"),
|
|
||||||
},
|
|
||||||
[]sqlserverflexalpha.UserRole{},
|
|
||||||
&sqlserverflexalpha.CreateUserRequestPayload{
|
|
||||||
Roles: &[]sqlserverflexalpha.UserRole{},
|
|
||||||
Username: utils.Ptr("username"),
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(
|
|
||||||
tt.description, func(t *testing.T) {
|
|
||||||
output, err := toCreatePayload(tt.input, tt.inputRoles)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
|
@ -28,7 +29,7 @@ func NewDatabaseDataSource() datasource.DataSource {
|
||||||
|
|
||||||
type dataSourceModel struct {
|
type dataSourceModel struct {
|
||||||
sqlserverflexbetaGen.DatabaseModel
|
sqlserverflexbetaGen.DatabaseModel
|
||||||
TfId types.String `tfsdk:"id"`
|
TerraformId types.String `tfsdk:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type databaseDataSource struct {
|
type databaseDataSource struct {
|
||||||
|
|
@ -97,8 +98,6 @@ func (d *databaseDataSource) Configure(
|
||||||
|
|
||||||
func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||||
var data dataSourceModel
|
var data dataSourceModel
|
||||||
readErr := "Read DB error"
|
|
||||||
|
|
||||||
// Read Terraform configuration data into the model
|
// Read Terraform configuration data into the model
|
||||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||||
|
|
||||||
|
|
@ -108,6 +107,7 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
|
||||||
|
|
||||||
ctx = core.InitProviderContext(ctx)
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
|
// Extract identifiers from the plan
|
||||||
projectId := data.ProjectId.ValueString()
|
projectId := data.ProjectId.ValueString()
|
||||||
region := d.providerData.GetRegionWithOverride(data.Region)
|
region := d.providerData.GetRegionWithOverride(data.Region)
|
||||||
instanceId := data.InstanceId.ValueString()
|
instanceId := data.InstanceId.ValueString()
|
||||||
|
|
@ -120,44 +120,55 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
|
||||||
|
|
||||||
databaseResp, err := d.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
|
databaseResp, err := d.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.LogError(
|
handleReadError(ctx, &resp.Diagnostics, err, projectId, instanceId)
|
||||||
ctx,
|
|
||||||
&resp.Diagnostics,
|
|
||||||
err,
|
|
||||||
"Reading database",
|
|
||||||
fmt.Sprintf("database with %q does not exist in project %q.", databaseName, projectId),
|
|
||||||
map[int]string{
|
|
||||||
http.StatusForbidden: fmt.Sprintf("Project with %q not found or forbidden access", projectId),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
resp.State.RemoveResource(ctx)
|
resp.State.RemoveResource(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = core.LogResponse(ctx)
|
ctx = core.LogResponse(ctx)
|
||||||
|
// Map response body to schema and populate Computed attribute values
|
||||||
dbId, ok := databaseResp.GetIdOk()
|
err = mapFields(databaseResp, &data, region)
|
||||||
if !ok {
|
if err != nil {
|
||||||
core.LogAndAddError(
|
core.LogAndAddError(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
readErr,
|
"Error reading database",
|
||||||
"Database creation waiting: returned id is nil",
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Id = types.Int64Value(dbId)
|
|
||||||
data.TfId = utils.BuildInternalTerraformId(projectId, region, instanceId, databaseName)
|
|
||||||
data.Owner = types.StringValue(databaseResp.GetOwner())
|
|
||||||
data.CollationName = types.StringValue(databaseResp.GetCollationName())
|
|
||||||
data.CompatibilityLevel = types.Int64Value(databaseResp.GetCompatibilityLevel())
|
|
||||||
data.DatabaseName = types.StringValue(databaseResp.GetName())
|
|
||||||
// data.InstanceId = types.StringValue(databaseResp.GetInstanceId())
|
|
||||||
// data.Name = types.Sometype(apiResponse.GetName())
|
|
||||||
// data.ProjectId = types.Sometype(apiResponse.GetProjectId())
|
|
||||||
// data.Region = types.Sometype(apiResponse.GetRegion())
|
|
||||||
|
|
||||||
// Save data into Terraform state
|
// Save data into Terraform state
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||||
|
|
||||||
|
tflog.Info(ctx, "SQL Server Flex beta database read")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleReadError centralizes API error handling for the Read operation.
|
||||||
|
func handleReadError(ctx context.Context, diags *diag.Diagnostics, err error, projectId, instanceId string) {
|
||||||
|
utils.LogError(
|
||||||
|
ctx,
|
||||||
|
diags,
|
||||||
|
err,
|
||||||
|
"Reading database",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"Could not retrieve database for instance %q in project %q.",
|
||||||
|
instanceId,
|
||||||
|
projectId,
|
||||||
|
),
|
||||||
|
map[int]string{
|
||||||
|
http.StatusBadRequest: fmt.Sprintf(
|
||||||
|
"Invalid request parameters for project %q and instance %q.",
|
||||||
|
projectId,
|
||||||
|
instanceId,
|
||||||
|
),
|
||||||
|
http.StatusNotFound: fmt.Sprintf(
|
||||||
|
"Database, instance %q, or project %q not found.",
|
||||||
|
instanceId,
|
||||||
|
projectId,
|
||||||
|
),
|
||||||
|
http.StatusForbidden: fmt.Sprintf("Forbidden access to project %q.", projectId),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package sqlserverflexbeta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// mapFields maps fields from a ListDatabase API response to a resourceModel for the data source.
|
||||||
|
func mapFields(source *sqlserverflexbeta.GetDatabaseResponse, model *dataSourceModel, region string) error {
|
||||||
|
if source == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if source.Id == nil || *source.Id == 0 {
|
||||||
|
return fmt.Errorf("id not present")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model given is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseId int64
|
||||||
|
if model.Id.ValueInt64() != 0 {
|
||||||
|
databaseId = model.Id.ValueInt64()
|
||||||
|
} else if source.Id != nil {
|
||||||
|
databaseId = *source.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("database id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Id = types.Int64Value(databaseId)
|
||||||
|
model.DatabaseName = types.StringValue(source.GetName())
|
||||||
|
model.Name = types.StringValue(source.GetName())
|
||||||
|
model.Owner = types.StringValue(strings.Trim(source.GetOwner(), "\""))
|
||||||
|
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.CollationName = types.StringValue(source.GetCollationName())
|
||||||
|
|
||||||
|
model.TerraformId = utils.BuildInternalTerraformId(
|
||||||
|
model.ProjectId.ValueString(),
|
||||||
|
region,
|
||||||
|
model.InstanceId.ValueString(),
|
||||||
|
model.DatabaseName.ValueString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapResourceFields maps fields from a ListDatabase API response to a resourceModel for the resource.
|
||||||
|
func mapResourceFields(source *sqlserverflexbeta.GetDatabaseResponse, model *resourceModel, region string) error {
|
||||||
|
if source == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if source.Id == nil || *source.Id == 0 {
|
||||||
|
return fmt.Errorf("id not present")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var databaseId int64
|
||||||
|
if model.Id.ValueInt64() != 0 {
|
||||||
|
databaseId = model.Id.ValueInt64()
|
||||||
|
} else if source.Id != nil {
|
||||||
|
databaseId = *source.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("database id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Id = types.Int64Value(databaseId)
|
||||||
|
model.DatabaseName = types.StringValue(source.GetName())
|
||||||
|
model.Name = types.StringValue(source.GetName())
|
||||||
|
model.Owner = types.StringValue(strings.Trim(source.GetOwner(), "\""))
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.ProjectId = types.StringValue(model.ProjectId.ValueString())
|
||||||
|
model.InstanceId = types.StringValue(model.InstanceId.ValueString())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCreatePayload converts the resource model to an API create payload.
|
||||||
|
func toCreatePayload(model *resourceModel) (*sqlserverflexbeta.CreateDatabaseRequestPayload, error) {
|
||||||
|
if model == nil {
|
||||||
|
return nil, fmt.Errorf("nil model")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sqlserverflexbeta.CreateDatabaseRequestPayload{
|
||||||
|
Name: model.Name.ValueStringPointer(),
|
||||||
|
Owner: model.Owner.ValueStringPointer(),
|
||||||
|
Collation: model.Collation.ValueStringPointer(),
|
||||||
|
Compatibility: model.Compatibility.ValueInt64Pointer(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
package sqlserverflexbeta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"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"
|
||||||
|
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
|
||||||
|
model *dataSourceModel
|
||||||
|
region string
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
model *dataSourceModel
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
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\""),
|
||||||
|
},
|
||||||
|
model: &dataSourceModel{
|
||||||
|
DatabaseModel: datasource.DatabaseModel{
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
region: "eu01",
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
model: &dataSourceModel{
|
||||||
|
DatabaseModel: datasource.DatabaseModel{
|
||||||
|
Id: types.Int64Value(1),
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
DatabaseName: types.StringValue("my-db"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
Region: types.StringValue("eu01"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
CompatibilityLevel: types.Int64Value(150),
|
||||||
|
CollationName: types.StringValue("collation"),
|
||||||
|
},
|
||||||
|
TerraformId: types.StringValue("my-project,eu01,my-instance,my-db"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source",
|
||||||
|
given: given{
|
||||||
|
source: nil,
|
||||||
|
model: &dataSourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source ID",
|
||||||
|
given: given{
|
||||||
|
source: &sqlserverflexbeta.GetDatabaseResponse{Id: nil},
|
||||||
|
model: &dataSourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil model",
|
||||||
|
given: given{
|
||||||
|
source: &sqlserverflexbeta.GetDatabaseResponse{Id: utils.Ptr(int64(1))},
|
||||||
|
model: nil,
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
err := mapFields(tc.given.source, tc.given.model, tc.given.region)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.model, tc.given.model); diff != "" {
|
||||||
|
t.Errorf("model mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapResourceFields(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
source *sqlserverflexbeta.GetDatabaseResponse
|
||||||
|
model *resourceModel
|
||||||
|
region string
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
model *resourceModel
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
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\""),
|
||||||
|
},
|
||||||
|
model: &resourceModel{
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
},
|
||||||
|
region: "eu01",
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
model: &resourceModel{
|
||||||
|
Id: types.Int64Value(1),
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
DatabaseName: types.StringValue("my-db"),
|
||||||
|
InstanceId: types.StringValue("my-instance"),
|
||||||
|
ProjectId: types.StringValue("my-project"),
|
||||||
|
Region: types.StringValue("eu01"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil source",
|
||||||
|
given: given{
|
||||||
|
source: nil,
|
||||||
|
model: &resourceModel{},
|
||||||
|
},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
err := mapResourceFields(tc.given.source, tc.given.model, tc.given.region)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.model, tc.given.model); diff != "" {
|
||||||
|
t.Errorf("model mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCreatePayload(t *testing.T) {
|
||||||
|
type given struct {
|
||||||
|
model *resourceModel
|
||||||
|
}
|
||||||
|
type expected struct {
|
||||||
|
payload *sqlserverflexbeta.CreateDatabaseRequestPayload
|
||||||
|
err bool
|
||||||
|
}
|
||||||
|
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
given given
|
||||||
|
expected expected
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should convert model to payload",
|
||||||
|
given: given{
|
||||||
|
model: &resourceModel{
|
||||||
|
Name: types.StringValue("my-db"),
|
||||||
|
Owner: types.StringValue("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: expected{
|
||||||
|
payload: &sqlserverflexbeta.CreateDatabaseRequestPayload{
|
||||||
|
Name: utils.Ptr("my-db"),
|
||||||
|
Owner: utils.Ptr("my-owner"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should fail on nil model",
|
||||||
|
given: given{model: nil},
|
||||||
|
expected: expected{err: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testcases {
|
||||||
|
t.Run(
|
||||||
|
tc.name, func(t *testing.T) {
|
||||||
|
actual, err := toCreatePayload(tc.given.model)
|
||||||
|
if (err != nil) != tc.expected.err {
|
||||||
|
t.Fatalf("expected error: %v, got: %v", tc.expected.err, err)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if diff := cmp.Diff(tc.expected.payload, actual); diff != "" {
|
||||||
|
t.Errorf("payload mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,9 +3,10 @@ package sqlserverflexbeta
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||||
|
|
@ -13,10 +14,9 @@ import (
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
|
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||||
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"
|
"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"
|
||||||
|
|
||||||
"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/core"
|
||||||
"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/stackit/internal/utils"
|
||||||
|
|
@ -30,6 +30,13 @@ var (
|
||||||
_ resource.ResourceWithImportState = &databaseResource{}
|
_ resource.ResourceWithImportState = &databaseResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &databaseResource{}
|
_ resource.ResourceWithModifyPlan = &databaseResource{}
|
||||||
_ resource.ResourceWithIdentity = &databaseResource{}
|
_ resource.ResourceWithIdentity = &databaseResource{}
|
||||||
|
|
||||||
|
// Define errors
|
||||||
|
errDatabaseNotFound = errors.New("database not found")
|
||||||
|
|
||||||
|
// Error message constants
|
||||||
|
extractErrorSummary = "extracting failed"
|
||||||
|
extractErrorMessage = "Extracting identity data: %v"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDatabaseResource() resource.Resource {
|
func NewDatabaseResource() resource.Resource {
|
||||||
|
|
@ -192,18 +199,24 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = core.LogResponse(ctx)
|
if createResp == nil || createResp.Id == nil {
|
||||||
createId, ok := createResp.GetIdOk()
|
|
||||||
if !ok {
|
|
||||||
core.LogAndAddError(
|
core.LogAndAddError(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
createErr,
|
"Error creating database",
|
||||||
fmt.Sprintf("Calling API: %v", err),
|
"API didn't return database Id. A database might have been created",
|
||||||
)
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
waitResp, err := wait.CreateDatabaseWaitHandler(
|
databaseId := *createResp.Id
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "database_id", databaseId)
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
// TODO: is this neccessary to wait for the database-> API say 200 ?
|
||||||
|
/*waitResp, err := wait.CreateDatabaseWaitHandler(
|
||||||
ctx,
|
ctx,
|
||||||
r.client,
|
r.client,
|
||||||
projectId,
|
projectId,
|
||||||
|
|
@ -263,23 +276,58 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
|
||||||
"Database creation waiting: returned name is different",
|
"Database creation waiting: returned name is different",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
}*/
|
||||||
|
|
||||||
|
database, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating database",
|
||||||
|
fmt.Sprintf("Getting database details after creation: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Id = types.Int64PointerValue(waitResp.Id)
|
// Map response body to schema
|
||||||
data.Name = types.StringPointerValue(waitResp.Name)
|
err = mapResourceFields(database, &data, region)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating database",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
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() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Save data into Terraform state
|
// Save data into Terraform state
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.Database created")
|
tflog.Info(ctx, "sqlserverflexbeta.Database created")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||||
var data resourceModel
|
var model resourceModel
|
||||||
readErr := "[Database Read]"
|
diags := req.State.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
// Read Terraform prior state data into the model
|
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -293,78 +341,66 @@ func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, r
|
||||||
|
|
||||||
ctx = core.InitProviderContext(ctx)
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
projectId := identityData.ProjectID.ValueString()
|
projectId, instanceId, region, databaseName, errExt := r.extractIdentityData(model, identityData)
|
||||||
region := identityData.Region.ValueString()
|
if errExt != nil {
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
instanceId := identityData.InstanceID.ValueString()
|
|
||||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
|
||||||
|
|
||||||
dbName := identityData.DatabaseName.ValueString()
|
|
||||||
ctx = tflog.SetField(ctx, "database_name", dbName)
|
|
||||||
|
|
||||||
getResp, err := r.client.GetDatabaseRequest(ctx, projectId, region, instanceId, dbName).Execute()
|
|
||||||
if err != nil {
|
|
||||||
core.LogAndAddError(
|
core.LogAndAddError(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
readErr,
|
extractErrorSummary,
|
||||||
fmt.Sprintf("Calling API: %v", err),
|
fmt.Sprintf(extractErrorMessage, errExt),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
databaseResp, err := r.client.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) {
|
||||||
|
resp.State.RemoveResource(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading database", fmt.Sprintf("Calling API: %v", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = core.LogResponse(ctx)
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
data.Id = types.Int64Value(getResp.GetId())
|
// Map response body to schema
|
||||||
data.Owner = types.StringValue(getResp.GetOwner())
|
err = mapResourceFields(databaseResp, &model, region)
|
||||||
data.Name = types.StringValue(getResp.GetName())
|
if err != nil {
|
||||||
data.DatabaseName = types.StringValue(getResp.GetName())
|
core.LogAndAddError(
|
||||||
data.CollationName = types.StringValue(getResp.GetCollationName())
|
ctx,
|
||||||
data.CompatibilityLevel = types.Int64Value(getResp.GetCompatibilityLevel())
|
&resp.Diagnostics,
|
||||||
|
"Error reading database",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set refreshed state
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.Database read")
|
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, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||||
var data resourceModel
|
// 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")
|
||||||
// Read Terraform prior state data into the model
|
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
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()
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
// Todo: Update API call logic
|
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.Database updated")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||||
var data resourceModel
|
// nolint:gocritic // function signature required by Terraform
|
||||||
|
var model resourceModel
|
||||||
// Read Terraform prior state data into the model
|
diags := req.State.Get(ctx, &model)
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
resp.Diagnostics.Append(diags...)
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -378,12 +414,28 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques
|
||||||
|
|
||||||
ctx = core.InitProviderContext(ctx)
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
projectId := identityData.ProjectID.ValueString()
|
projectId, instanceId, region, databaseName, errExt := r.extractIdentityData(model, identityData)
|
||||||
region := identityData.Region.ValueString()
|
if errExt != nil {
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
core.LogAndAddError(
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
extractErrorSummary,
|
||||||
|
fmt.Sprintf(extractErrorMessage, errExt),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Todo: Delete API call logic
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
ctx = tflog.SetField(ctx, "database_name", databaseName)
|
||||||
|
|
||||||
|
// Delete existing record set
|
||||||
|
err := r.client.DeleteDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting database", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.Database deleted")
|
tflog.Info(ctx, "sqlserverflexbeta.Database deleted")
|
||||||
}
|
}
|
||||||
|
|
@ -504,3 +556,46 @@ func (r *databaseResource) ImportState(
|
||||||
|
|
||||||
tflog.Info(ctx, "Sqlserverflexbeta database state imported")
|
tflog.Info(ctx, "Sqlserverflexbeta database state imported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractIdentityData extracts essential identifiers from the resource model, falling back to the identity model.
|
||||||
|
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()
|
||||||
|
} else {
|
||||||
|
if identity.DatabaseName.IsNull() || identity.DatabaseName.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("database_name not found in config")
|
||||||
|
}
|
||||||
|
databaseName = identity.DatabaseName.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.ProjectId.IsNull() && !model.ProjectId.IsUnknown() {
|
||||||
|
projectId = model.ProjectId.ValueString()
|
||||||
|
} else {
|
||||||
|
if identity.ProjectID.IsNull() || identity.ProjectID.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("project_id not found in config")
|
||||||
|
}
|
||||||
|
projectId = identity.ProjectID.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.Region.IsNull() && !model.Region.IsUnknown() {
|
||||||
|
region = r.providerData.GetRegionWithOverride(model.Region)
|
||||||
|
} else {
|
||||||
|
if identity.Region.IsNull() || identity.Region.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("region not found in config")
|
||||||
|
}
|
||||||
|
region = r.providerData.GetRegionWithOverride(identity.Region)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !model.InstanceId.IsNull() && !model.InstanceId.IsUnknown() {
|
||||||
|
instanceId = model.InstanceId.ValueString()
|
||||||
|
} else {
|
||||||
|
if identity.InstanceID.IsNull() || identity.InstanceID.IsUnknown() {
|
||||||
|
return "", "", "", "", fmt.Errorf("instance_id not found in config")
|
||||||
|
}
|
||||||
|
instanceId = identity.InstanceID.ValueString()
|
||||||
|
}
|
||||||
|
return projectId, region, instanceId, databaseName, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,12 @@ import (
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
|
"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/core"
|
||||||
|
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"
|
"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 "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
|
||||||
|
|
||||||
// sqlserverflexbetaUtils "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/utils"
|
|
||||||
|
|
||||||
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user/datasources_gen"
|
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user/datasources_gen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,7 +28,7 @@ func NewUserDataSource() datasource.DataSource {
|
||||||
type dataSourceModel struct {
|
type dataSourceModel struct {
|
||||||
DefaultDatabase types.String `tfsdk:"default_database"`
|
DefaultDatabase types.String `tfsdk:"default_database"`
|
||||||
Host types.String `tfsdk:"host"`
|
Host types.String `tfsdk:"host"`
|
||||||
Id types.Int64 `tfsdk:"id"`
|
Id types.String `tfsdk:"id"`
|
||||||
InstanceId types.String `tfsdk:"instance_id"`
|
InstanceId types.String `tfsdk:"instance_id"`
|
||||||
Port types.Int64 `tfsdk:"port"`
|
Port types.Int64 `tfsdk:"port"`
|
||||||
ProjectId types.String `tfsdk:"project_id"`
|
ProjectId types.String `tfsdk:"project_id"`
|
||||||
|
|
@ -63,50 +62,52 @@ func (d *userDataSource) Configure(
|
||||||
req datasource.ConfigureRequest,
|
req datasource.ConfigureRequest,
|
||||||
resp *datasource.ConfigureResponse,
|
resp *datasource.ConfigureResponse,
|
||||||
) {
|
) {
|
||||||
//var ok bool
|
var ok bool
|
||||||
//d.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
|
d.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
|
||||||
//if !ok {
|
if !ok {
|
||||||
// return
|
return
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//apiClient := sqlserverflexbetaUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics)
|
apiClient := sqlserverflexUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics)
|
||||||
//if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
// return
|
return
|
||||||
//}
|
}
|
||||||
//d.client = apiClient
|
d.client = apiClient
|
||||||
tflog.Info(ctx, fmt.Sprintf("%s client configured", errorPrefix))
|
tflog.Info(ctx, "SQL SERVER Flex alpha database client configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||||
var data dataSourceModel
|
var model dataSourceModel
|
||||||
|
diags := req.Config.Get(ctx, &model)
|
||||||
// Read Terraform configuration data into the model
|
resp.Diagnostics.Append(diags...)
|
||||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = core.InitProviderContext(ctx)
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
projectId := data.ProjectId.ValueString()
|
projectId := model.ProjectId.ValueString()
|
||||||
region := d.providerData.GetRegionWithOverride(data.Region)
|
instanceId := model.InstanceId.ValueString()
|
||||||
instanceId := data.InstanceId.ValueString()
|
userId := model.UserId.ValueInt64()
|
||||||
userId := data.UserId.ValueInt64()
|
region := d.providerData.GetRegionWithOverride(model.Region)
|
||||||
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
ctx = tflog.SetField(ctx, "user_id", userId)
|
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
|
||||||
userResp, err := d.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
recordSetResp, err := d.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.LogError(
|
utils.LogError(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
err,
|
err,
|
||||||
"Reading user",
|
"Reading user",
|
||||||
fmt.Sprintf("user with ID %q does not exist in project %q.", userId, projectId),
|
fmt.Sprintf(
|
||||||
|
"User with ID %q or instance with ID %q does not exist in project %q.",
|
||||||
|
userId,
|
||||||
|
instanceId,
|
||||||
|
projectId,
|
||||||
|
),
|
||||||
map[int]string{
|
map[int]string{
|
||||||
http.StatusForbidden: fmt.Sprintf("Project with ID %q not found or forbidden access", projectId),
|
http.StatusForbidden: fmt.Sprintf("Project with ID %q not found or forbidden access", projectId),
|
||||||
},
|
},
|
||||||
|
|
@ -117,22 +118,23 @@ func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
|
||||||
|
|
||||||
ctx = core.LogResponse(ctx)
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
// Todo: Read API call logic
|
// Map response body to schema and populate Computed attribute values
|
||||||
|
err = mapDataSourceFields(recordSetResp, &model, region)
|
||||||
// Example data value setting
|
|
||||||
// data.Id = types.StringValue("example-id")
|
|
||||||
|
|
||||||
err = mapResponseToModel(ctx, userResp, &data, resp.Diagnostics)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
core.LogAndAddError(
|
core.LogAndAddError(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
fmt.Sprintf("%s Read", errorPrefix),
|
"Error reading user",
|
||||||
fmt.Sprintf("Processing API payload: %v", err),
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data into Terraform state
|
// Set refreshed state
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "SQLServer Flex beta instance read")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
package sqlserverflexbeta
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
||||||
|
|
||||||
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mapResponseToModel(
|
|
||||||
ctx context.Context,
|
|
||||||
resp *sqlserverflexbeta.GetUserResponse,
|
|
||||||
m *dataSourceModel,
|
|
||||||
tfDiags diag.Diagnostics,
|
|
||||||
) error {
|
|
||||||
if resp == nil {
|
|
||||||
return fmt.Errorf("response is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Id = types.Int64Value(resp.GetId())
|
|
||||||
m.UserId = types.Int64Value(resp.GetId())
|
|
||||||
m.Username = types.StringValue(resp.GetUsername())
|
|
||||||
m.Port = types.Int64Value(resp.GetPort())
|
|
||||||
m.Host = types.StringValue(resp.GetHost())
|
|
||||||
m.DefaultDatabase = types.StringValue(resp.GetDefaultDatabase())
|
|
||||||
m.Status = types.StringValue(resp.GetStatus())
|
|
||||||
|
|
||||||
if resp.Roles != nil {
|
|
||||||
roles, diags := types.ListValueFrom(ctx, types.StringType, *resp.Roles)
|
|
||||||
tfDiags.Append(diags...)
|
|
||||||
if tfDiags.HasError() {
|
|
||||||
return fmt.Errorf("failed to map roles")
|
|
||||||
}
|
|
||||||
m.Roles = roles
|
|
||||||
} else {
|
|
||||||
m.Roles = types.ListNull(types.StringType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Status != nil {
|
|
||||||
m.Status = types.StringValue(*resp.Status)
|
|
||||||
} else {
|
|
||||||
m.Status = types.StringNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: complete and refactor
|
|
||||||
|
|
||||||
/*
|
|
||||||
sampleList, diags := types.ListValueFrom(ctx, types.StringType, resp.GetList())
|
|
||||||
tfDiags.Append(diags...)
|
|
||||||
if diags.HasError() {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"error converting list response value",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
sample, diags := sqlserverflexbetaResGen.NewSampleValue(
|
|
||||||
sqlserverflexbetaResGen.SampleValue{}.AttributeTypes(ctx),
|
|
||||||
map[string]attr.Value{
|
|
||||||
"field": types.StringValue(string(resp.GetField())),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
tfDiags.Append(diags...)
|
|
||||||
if diags.HasError() {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"error converting sample response value",
|
|
||||||
"sample",
|
|
||||||
types.StringValue(string(resp.GetField())),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
m.Sample = sample
|
|
||||||
*/
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//func toCreatePayload(
|
|
||||||
// ctx context.Context,
|
|
||||||
// model *resourceModel,
|
|
||||||
//) (*sqlserverflexbeta.CreateUserRequestPayload, error) {
|
|
||||||
// if model == nil {
|
|
||||||
// return nil, fmt.Errorf("nil model")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var roles []sqlserverflexbeta.UserRole
|
|
||||||
// if !model.Roles.IsNull() && !model.Roles.IsUnknown() {
|
|
||||||
// diags := model.Roles.ElementsAs(ctx, &roles, false)
|
|
||||||
// if diags.HasError() {
|
|
||||||
// return nil, fmt.Errorf("failed to convert roles: %v", diags)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return &sqlserverflexbeta.CreateUserRequestPayload{
|
|
||||||
// DefaultDatabase: model.DefaultDatabase.ValueStringPointer(),
|
|
||||||
// Username: model.Username.ValueStringPointer(),
|
|
||||||
// Roles: &roles,
|
|
||||||
// }, nil
|
|
||||||
//}
|
|
||||||
179
stackit/internal/services/sqlserverflexbeta/user/mapper.go
Normal file
179
stackit/internal/services/sqlserverflexbeta/user/mapper.go
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
package sqlserverflexbeta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"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 {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
// Handle user ID
|
||||||
|
var userId int64
|
||||||
|
if model.UserId.ValueInt64() != 0 {
|
||||||
|
userId = model.UserId.ValueInt64()
|
||||||
|
} else if user.Id != nil {
|
||||||
|
userId = *user.Id
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("user id not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set main attributes
|
||||||
|
model.Id = utils.BuildInternalTerraformId(
|
||||||
|
model.ProjectId.ValueString(), region, model.InstanceId.ValueString(), strconv.FormatInt(userId, 10),
|
||||||
|
)
|
||||||
|
model.UserId = types.Int64Value(userId)
|
||||||
|
model.Username = types.StringPointerValue(user.Username)
|
||||||
|
|
||||||
|
// Map roles
|
||||||
|
if user.Roles == nil {
|
||||||
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
|
} else {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = types.List(rolesSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set remaining attributes
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(user.Port)
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.Status = types.StringPointerValue(user.Status)
|
||||||
|
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapFields maps the API response to a resourceModel.
|
||||||
|
func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel, region string) error {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
// Handle user ID
|
||||||
|
var userId int64
|
||||||
|
if model.UserId.ValueInt64() != 0 {
|
||||||
|
userId = model.UserId.ValueInt64()
|
||||||
|
} else if user.Id != nil {
|
||||||
|
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)
|
||||||
|
|
||||||
|
// Map roles
|
||||||
|
if user.Roles != nil {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = types.List(rolesSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure roles is not null
|
||||||
|
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
||||||
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set connection details
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(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 {
|
||||||
|
if userResp == nil {
|
||||||
|
return fmt.Errorf("response is nil")
|
||||||
|
}
|
||||||
|
if model == nil {
|
||||||
|
return fmt.Errorf("model input is nil")
|
||||||
|
}
|
||||||
|
user := userResp
|
||||||
|
|
||||||
|
if user.Id == nil {
|
||||||
|
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)
|
||||||
|
|
||||||
|
if user.Password == nil {
|
||||||
|
return fmt.Errorf("user password not present")
|
||||||
|
}
|
||||||
|
model.Password = types.StringValue(*user.Password)
|
||||||
|
|
||||||
|
if user.Roles != nil {
|
||||||
|
var roles []attr.Value
|
||||||
|
for _, role := range *user.Roles {
|
||||||
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
|
}
|
||||||
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
if diags.HasError() {
|
||||||
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
}
|
||||||
|
model.Roles = types.List(rolesSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.Roles.IsNull() || model.Roles.IsUnknown() {
|
||||||
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Host = types.StringPointerValue(user.Host)
|
||||||
|
model.Port = types.Int64PointerValue(user.Port)
|
||||||
|
model.Region = types.StringValue(region)
|
||||||
|
model.Status = types.StringPointerValue(user.Status)
|
||||||
|
model.DefaultDatabase = types.StringPointerValue(user.DefaultDatabase)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCreatePayload converts a resourceModel to an API CreateUserRequestPayload.
|
||||||
|
func toCreatePayload(
|
||||||
|
model *resourceModel,
|
||||||
|
roles []sqlserverflexbeta.UserRole,
|
||||||
|
) (*sqlserverflexbeta.CreateUserRequestPayload, error) {
|
||||||
|
if model == nil {
|
||||||
|
return nil, fmt.Errorf("nil model")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sqlserverflexbeta.CreateUserRequestPayload{
|
||||||
|
Username: conversion.StringValueToPointer(model.Username),
|
||||||
|
DefaultDatabase: conversion.StringValueToPointer(model.DefaultDatabase),
|
||||||
|
Roles: &roles,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
527
stackit/internal/services/sqlserverflexbeta/user/mapper_test.go
Normal file
527
stackit/internal/services/sqlserverflexbeta/user/mapper_test.go
Normal file
|
|
@ -0,0 +1,527 @@
|
||||||
|
package sqlserverflexbeta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapDataSourceFields(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexbeta.GetUserResponse
|
||||||
|
region string
|
||||||
|
expected dataSourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexbeta.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(),
|
||||||
|
Roles: types.List(types.SetNull(types.StringType)),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Null(),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringNull(),
|
||||||
|
DefaultDatabase: types.StringNull(),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{
|
||||||
|
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{
|
||||||
|
"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"),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{
|
||||||
|
Id: types.StringValue("pid,region,iid,1"),
|
||||||
|
UserId: types.Int64Value(1),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.List(
|
||||||
|
types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringValue("active"),
|
||||||
|
DefaultDatabase: types.StringValue("default_db"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(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),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response_2",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_resource_id",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
dataSourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &dataSourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
UserId: tt.expected.UserId,
|
||||||
|
}
|
||||||
|
err := mapDataSourceFields(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFieldsCreate(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexbeta.CreateUserResponse
|
||||||
|
region string
|
||||||
|
expected resourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexbeta.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Password: utils.Ptr(""),
|
||||||
|
},
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexbeta.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(2)),
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{
|
||||||
|
"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"),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(2),
|
||||||
|
UserId: types.Int64Value(2),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.List(
|
||||||
|
types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Password: types.StringValue("password"),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
Status: types.StringValue("status"),
|
||||||
|
DefaultDatabase: types.StringValue("default_db"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexbeta.CreateUserResponse{
|
||||||
|
Id: utils.Ptr(int64(3)),
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Password: utils.Ptr(""),
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(2123456789)),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(3),
|
||||||
|
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),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
DefaultDatabase: types.StringNull(),
|
||||||
|
Status: types.StringNull(),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &resourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
}
|
||||||
|
err := mapFieldsCreate(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFields(t *testing.T) {
|
||||||
|
const testRegion = "region"
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *sqlserverflexbeta.GetUserResponse
|
||||||
|
region string
|
||||||
|
expected resourceModel
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{},
|
||||||
|
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)),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Null(),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simple_values",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
Host: utils.Ptr("host"),
|
||||||
|
Port: utils.Ptr(int64(1234)),
|
||||||
|
},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{
|
||||||
|
Id: types.Int64Value(2),
|
||||||
|
UserId: types.Int64Value(2),
|
||||||
|
InstanceId: types.StringValue("iid"),
|
||||||
|
ProjectId: types.StringValue("pid"),
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
Roles: types.List(
|
||||||
|
types.SetValueMust(
|
||||||
|
types.StringType, []attr.Value{
|
||||||
|
types.StringValue("role_1"),
|
||||||
|
types.StringValue("role_2"),
|
||||||
|
types.StringValue(""),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Host: types.StringValue("host"),
|
||||||
|
Port: types.Int64Value(1234),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{
|
||||||
|
Id: utils.Ptr(int64(1)),
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
Host: nil,
|
||||||
|
Port: utils.Ptr(int64(2123456789)),
|
||||||
|
},
|
||||||
|
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.SetValueMust(types.StringType, []attr.Value{})),
|
||||||
|
Host: types.StringNull(),
|
||||||
|
Port: types.Int64Value(2123456789),
|
||||||
|
Region: types.StringValue(testRegion),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response",
|
||||||
|
nil,
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_response_2",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no_resource_id",
|
||||||
|
&sqlserverflexbeta.GetUserResponse{},
|
||||||
|
testRegion,
|
||||||
|
resourceModel{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
state := &resourceModel{
|
||||||
|
ProjectId: tt.expected.ProjectId,
|
||||||
|
InstanceId: tt.expected.InstanceId,
|
||||||
|
UserId: tt.expected.UserId,
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToCreatePayload(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
description string
|
||||||
|
input *resourceModel
|
||||||
|
inputRoles []sqlserverflexbeta.UserRole
|
||||||
|
expected *sqlserverflexbeta.CreateUserRequestPayload
|
||||||
|
isValid bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&resourceModel{},
|
||||||
|
[]sqlserverflexbeta.UserRole{},
|
||||||
|
&sqlserverflexbeta.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{},
|
||||||
|
Username: nil,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default_values",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
},
|
||||||
|
[]sqlserverflexbeta.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
},
|
||||||
|
&sqlserverflexbeta.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{
|
||||||
|
"role_1",
|
||||||
|
"role_2",
|
||||||
|
},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"null_fields_and_int_conversions",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringNull(),
|
||||||
|
},
|
||||||
|
[]sqlserverflexbeta.UserRole{
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
&sqlserverflexbeta.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
Username: nil,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_model",
|
||||||
|
nil,
|
||||||
|
[]sqlserverflexbeta.UserRole{},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nil_roles",
|
||||||
|
&resourceModel{
|
||||||
|
Username: types.StringValue("username"),
|
||||||
|
},
|
||||||
|
[]sqlserverflexbeta.UserRole{},
|
||||||
|
&sqlserverflexbeta.CreateUserRequestPayload{
|
||||||
|
Roles: &[]sqlserverflexbeta.UserRole{},
|
||||||
|
Username: utils.Ptr("username"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.description, func(t *testing.T) {
|
||||||
|
output, err := toCreatePayload(tt.input, tt.inputRoles)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@ package sqlserverflexbeta
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -12,9 +14,12 @@ import (
|
||||||
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
|
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||||
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||||
"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/pkg_gen/sqlserverflexbeta"
|
||||||
"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/conversion"
|
||||||
|
sqlserverflexbetagen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/user/resources_gen"
|
||||||
|
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"
|
||||||
|
|
||||||
"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/core"
|
||||||
"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/stackit/internal/utils"
|
||||||
|
|
@ -54,319 +59,20 @@ func (r *userResource) Metadata(ctx context.Context, req resource.MetadataReques
|
||||||
resp.TypeName = req.ProviderTypeName + "_sqlserverflexbeta_user"
|
resp.TypeName = req.ProviderTypeName + "_sqlserverflexbeta_user"
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed planModifiers.yaml
|
|
||||||
var modifiersFileByte []byte
|
|
||||||
|
|
||||||
func (r *userResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
|
||||||
|
|
||||||
s := sqlserverflexbetaResGen.UserResourceSchema(ctx)
|
|
||||||
|
|
||||||
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
|
|
||||||
if err != nil {
|
|
||||||
resp.Diagnostics.AddError("error during read modifiers config file", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = utils.AddPlanModifiersToResourceSchema(fields, &s)
|
|
||||||
if err != nil {
|
|
||||||
resp.Diagnostics.AddError("error adding plan modifiers", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.Schema = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userResource) IdentitySchema(
|
|
||||||
_ context.Context,
|
|
||||||
_ resource.IdentitySchemaRequest,
|
|
||||||
resp *resource.IdentitySchemaResponse,
|
|
||||||
) {
|
|
||||||
resp.IdentitySchema = identityschema.Schema{
|
|
||||||
Attributes: map[string]identityschema.Attribute{
|
|
||||||
"project_id": identityschema.StringAttribute{
|
|
||||||
RequiredForImport: true, // must be set during import by the practitioner
|
|
||||||
},
|
|
||||||
"region": identityschema.StringAttribute{
|
|
||||||
RequiredForImport: true, // can be defaulted by the provider configuration
|
|
||||||
},
|
|
||||||
"instance_id": identityschema.StringAttribute{
|
|
||||||
RequiredForImport: true, // can be defaulted by the provider configuration
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure adds the provider configured client to the resource.
|
// Configure adds the provider configured client to the resource.
|
||||||
func (r *userResource) Configure(
|
func (r *userResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||||
ctx context.Context,
|
|
||||||
req resource.ConfigureRequest,
|
|
||||||
resp *resource.ConfigureResponse,
|
|
||||||
) {
|
|
||||||
var ok bool
|
var ok bool
|
||||||
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
|
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
apiClientConfigOptions := []config.ConfigurationOption{
|
apiClient := sqlserverflexbetaUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics)
|
||||||
config.WithCustomAuth(r.providerData.RoundTripper),
|
if resp.Diagnostics.HasError() {
|
||||||
utils.UserAgentConfigOption(r.providerData.Version),
|
|
||||||
}
|
|
||||||
if r.providerData.SQLServerFlexCustomEndpoint != "" {
|
|
||||||
apiClientConfigOptions = append(
|
|
||||||
apiClientConfigOptions,
|
|
||||||
config.WithEndpoint(r.providerData.SQLServerFlexCustomEndpoint),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(r.providerData.GetRegion()))
|
|
||||||
}
|
|
||||||
apiClient, err := sqlserverflexbeta.NewAPIClient(apiClientConfigOptions...)
|
|
||||||
if err != nil {
|
|
||||||
resp.Diagnostics.AddError(
|
|
||||||
"Error configuring API client",
|
|
||||||
fmt.Sprintf(
|
|
||||||
"Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration",
|
|
||||||
err,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.client = apiClient
|
r.client = apiClient
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.User client configured")
|
tflog.Info(ctx, "SQLServer Beta Flex user client configured")
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
|
||||||
var data resourceModel
|
|
||||||
|
|
||||||
// Read Terraform plan data into the model
|
|
||||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
|
||||||
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read identity data
|
|
||||||
var identityData UserResourceIdentityModel
|
|
||||||
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()
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
//payload, err := toCreatePayload(ctx, &data)
|
|
||||||
//if err != nil {
|
|
||||||
// core.LogAndAddError(
|
|
||||||
// ctx,
|
|
||||||
// &resp.Diagnostics,
|
|
||||||
// "Error creating User",
|
|
||||||
// fmt.Sprintf("Creating API payload: %v", err),
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//payload = payload
|
|
||||||
|
|
||||||
// TODO: Create API call logic
|
|
||||||
/*
|
|
||||||
// Generate API request body from model
|
|
||||||
payload, err := toCreatePayload(ctx, &model)
|
|
||||||
if err != nil {
|
|
||||||
core.LogAndAddError(
|
|
||||||
ctx,
|
|
||||||
&resp.Diagnostics,
|
|
||||||
"Error creating User",
|
|
||||||
fmt.Sprintf("Creating API payload: %v", err),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Create new User
|
|
||||||
createResp, err := r.client.CreateUserRequest(
|
|
||||||
ctx,
|
|
||||||
projectId,
|
|
||||||
region,
|
|
||||||
).CreateUserRequestPayload(*payload).Execute()
|
|
||||||
if err != nil {
|
|
||||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating User", fmt.Sprintf("Calling API: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = core.LogResponse(ctx)
|
|
||||||
|
|
||||||
UserId := *createResp.Id
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Example data value setting
|
|
||||||
//data.UserId = types.StringValue("id-from-response")
|
|
||||||
|
|
||||||
// TODO: Set data returned by API in identity
|
|
||||||
identity := UserResourceIdentityModel{
|
|
||||||
ProjectID: types.StringValue(projectId),
|
|
||||||
Region: types.StringValue(region),
|
|
||||||
// TODO: add missing values
|
|
||||||
// UserID: types.StringValue(UserId),
|
|
||||||
}
|
|
||||||
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement wait handler if needed
|
|
||||||
/*
|
|
||||||
|
|
||||||
waitResp, err := wait.CreateUserWaitHandler(
|
|
||||||
ctx,
|
|
||||||
r.client,
|
|
||||||
projectId,
|
|
||||||
UserId,
|
|
||||||
region,
|
|
||||||
).SetSleepBeforeWait(
|
|
||||||
30 * time.Second,
|
|
||||||
).SetTimeout(
|
|
||||||
90 * time.Minute,
|
|
||||||
).WaitWithContext(ctx)
|
|
||||||
if err != nil {
|
|
||||||
core.LogAndAddError(
|
|
||||||
ctx,
|
|
||||||
&resp.Diagnostics,
|
|
||||||
"Error creating User",
|
|
||||||
fmt.Sprintf("User creation waiting: %v", err),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if waitResp.Id == nil {
|
|
||||||
core.LogAndAddError(
|
|
||||||
ctx,
|
|
||||||
&resp.Diagnostics,
|
|
||||||
"Error creating User",
|
|
||||||
"User creation waiting: returned id is nil",
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map response body to schema
|
|
||||||
err = mapResponseToModel(ctx, waitResp, &model, resp.Diagnostics)
|
|
||||||
if err != nil {
|
|
||||||
core.LogAndAddError(
|
|
||||||
ctx,
|
|
||||||
&resp.Diagnostics,
|
|
||||||
"Error creating User",
|
|
||||||
fmt.Sprintf("Processing API payload: %v", err),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Save data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.User created")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
|
||||||
var data resourceModel
|
|
||||||
|
|
||||||
// Read Terraform prior state data into the model
|
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read identity data
|
|
||||||
var identityData UserResourceIdentityModel
|
|
||||||
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()
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
// Todo: Read API call logic
|
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
// TODO: Set data returned by API in identity
|
|
||||||
identity := UserResourceIdentityModel{
|
|
||||||
ProjectID: types.StringValue(projectId),
|
|
||||||
Region: types.StringValue(region),
|
|
||||||
// InstanceID: types.StringValue(instanceId),
|
|
||||||
}
|
|
||||||
resp.Diagnostics.Append(resp.Identity.Set(ctx, identity)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.User read")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
|
||||||
var data resourceModel
|
|
||||||
|
|
||||||
// Read Terraform prior state data into the model
|
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read identity data
|
|
||||||
var identityData UserResourceIdentityModel
|
|
||||||
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()
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
// Todo: Update API call logic
|
|
||||||
|
|
||||||
// Save updated data into Terraform state
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.User updated")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
|
||||||
var data resourceModel
|
|
||||||
|
|
||||||
// Read Terraform prior state data into the model
|
|
||||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read identity data
|
|
||||||
var identityData UserResourceIdentityModel
|
|
||||||
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()
|
|
||||||
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
||||||
ctx = tflog.SetField(ctx, "region", region)
|
|
||||||
|
|
||||||
// Todo: Delete API call logic
|
|
||||||
|
|
||||||
tflog.Info(ctx, "sqlserverflexbeta.User deleted")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModifyPlan implements resource.ResourceWithModifyPlan.
|
// ModifyPlan implements resource.ResourceWithModifyPlan.
|
||||||
|
|
@ -397,25 +103,256 @@ func (r *userResource) ModifyPlan(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var identityModel UserResourceIdentityModel
|
|
||||||
identityModel.ProjectID = planModel.ProjectId
|
|
||||||
identityModel.Region = planModel.Region
|
|
||||||
// TODO: complete
|
|
||||||
//if !planModel.InstanceId.IsNull() && !planModel.InstanceId.IsUnknown() {
|
|
||||||
// identityModel.InstanceID = planModel.InstanceId
|
|
||||||
//}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.Identity.Set(ctx, identityModel)...)
|
|
||||||
if resp.Diagnostics.HasError() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
|
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:embed planModifiers.yaml
|
||||||
|
var modifiersFileByte []byte
|
||||||
|
|
||||||
|
// Schema defines the schema for the resource.
|
||||||
|
func (r *userResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||||
|
s := sqlserverflexbetagen.UserResourceSchema(ctx)
|
||||||
|
|
||||||
|
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
|
||||||
|
if err != nil {
|
||||||
|
resp.Diagnostics.AddError("error during read modifiers config file", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = utils.AddPlanModifiersToResourceSchema(fields, &s)
|
||||||
|
if err != nil {
|
||||||
|
resp.Diagnostics.AddError("error adding plan modifiers", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Schema = s
|
||||||
|
}
|
||||||
|
|
||||||
|
// IdentitySchema defines the schema for the resource's identity attributes.
|
||||||
|
func (r *userResource) IdentitySchema(
|
||||||
|
_ context.Context,
|
||||||
|
_ resource.IdentitySchemaRequest,
|
||||||
|
response *resource.IdentitySchemaResponse,
|
||||||
|
) {
|
||||||
|
response.IdentitySchema = identityschema.Schema{
|
||||||
|
Attributes: map[string]identityschema.Attribute{
|
||||||
|
"project_id": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // must be set during import by the practitioner
|
||||||
|
},
|
||||||
|
"region": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
"instance_id": identityschema.StringAttribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
"user_id": identityschema.Int64Attribute{
|
||||||
|
RequiredForImport: true, // can be defaulted by the provider configuration
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates the resource and sets the initial Terraform state.
|
||||||
|
func (r *userResource) Create(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.CreateRequest,
|
||||||
|
resp *resource.CreateResponse,
|
||||||
|
) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model resourceModel
|
||||||
|
diags := req.Plan.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
|
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, "region", region)
|
||||||
|
|
||||||
|
var roles []sqlserverflexbeta.UserRole
|
||||||
|
if !model.Roles.IsNull() && !model.Roles.IsUnknown() {
|
||||||
|
diags = model.Roles.ElementsAs(ctx, &roles, false)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate API request body from model
|
||||||
|
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(
|
||||||
|
ctx,
|
||||||
|
projectId,
|
||||||
|
region,
|
||||||
|
instanceId,
|
||||||
|
).CreateUserRequestPayload(*payload).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
if userResp == nil || userResp.Id == nil || *userResp.Id == 0 {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating user",
|
||||||
|
"API didn't return user Id. A user might have been created",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userId := *userResp.Id
|
||||||
|
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||||
|
|
||||||
|
// Map response body to schema
|
||||||
|
err = mapFieldsCreate(userResp, &model, region)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error creating user",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Set state to fully populated data
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "SQLServer Flex user created")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read refreshes the Terraform state with the latest data.
|
||||||
|
func (r *userResource) Read(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.ReadRequest,
|
||||||
|
resp *resource.ReadResponse,
|
||||||
|
) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
var model resourceModel
|
||||||
|
diags := req.State.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
instanceId := model.InstanceId.ValueString()
|
||||||
|
userId := model.UserId.ValueInt64()
|
||||||
|
region := r.providerData.GetRegionWithOverride(model.Region)
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
|
||||||
|
recordSetResp, err := r.client.GetUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||||
|
if err != nil {
|
||||||
|
var oapiErr *oapierror.GenericOpenAPIError
|
||||||
|
ok := errors.As(
|
||||||
|
err,
|
||||||
|
&oapiErr,
|
||||||
|
)
|
||||||
|
//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 {
|
||||||
|
resp.State.RemoveResource(ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading user", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
// Map response body to schema
|
||||||
|
err = mapFields(recordSetResp, &model, region)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
&resp.Diagnostics,
|
||||||
|
"Error reading user",
|
||||||
|
fmt.Sprintf("Processing API payload: %v", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set refreshed state
|
||||||
|
diags = resp.State.Set(ctx, model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tflog.Info(ctx, "SQLServer Flex user read")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates the resource and sets the updated Terraform state on success.
|
||||||
|
func (r *userResource) 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 user", "User can't be updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes the resource and removes the Terraform state on success.
|
||||||
|
func (r *userResource) Delete(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.DeleteRequest,
|
||||||
|
resp *resource.DeleteResponse,
|
||||||
|
) { // nolint:gocritic // function signature required by Terraform
|
||||||
|
// Retrieve values from plan
|
||||||
|
var model resourceModel
|
||||||
|
diags := req.State.Get(ctx, &model)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
|
projectId := model.ProjectId.ValueString()
|
||||||
|
instanceId := model.InstanceId.ValueString()
|
||||||
|
userId := model.UserId.ValueInt64()
|
||||||
|
region := model.Region.ValueString()
|
||||||
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
||||||
|
ctx = tflog.SetField(ctx, "instance_id", instanceId)
|
||||||
|
ctx = tflog.SetField(ctx, "user_id", userId)
|
||||||
|
ctx = tflog.SetField(ctx, "region", region)
|
||||||
|
|
||||||
|
// Delete existing record set
|
||||||
|
// err := r.client.DeleteUserRequest(ctx, projectId, region, instanceId, userId).Execute()
|
||||||
|
|
||||||
|
// Delete existing record set
|
||||||
|
_, err := sqlserverflexbetaWait.DeleteUserWaitHandler(ctx, r.client, projectId, region, instanceId, userId).
|
||||||
|
WaitWithContext(ctx)
|
||||||
|
//err := r.client.DeleteUserRequest(ctx, arg.projectId, arg.region, arg.instanceId, userId).Execute()
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(ctx, &resp.Diagnostics, "User Delete Error", fmt.Sprintf("Calling API: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = core.LogResponse(ctx)
|
||||||
|
|
||||||
|
tflog.Info(ctx, "SQLServer Flex user deleted")
|
||||||
|
}
|
||||||
|
|
||||||
// ImportState imports a resource into the Terraform state on success.
|
// 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
|
// The expected format of the resource import identifier is: project_id,zone_id,record_set_id
|
||||||
func (r *userResource) ImportState(
|
func (r *userResource) ImportState(
|
||||||
|
|
@ -423,6 +360,7 @@ func (r *userResource) ImportState(
|
||||||
req resource.ImportStateRequest,
|
req resource.ImportStateRequest,
|
||||||
resp *resource.ImportStateResponse,
|
resp *resource.ImportStateResponse,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
ctx = core.InitProviderContext(ctx)
|
ctx = core.InitProviderContext(ctx)
|
||||||
|
|
||||||
if req.ID != "" {
|
if req.ID != "" {
|
||||||
|
|
@ -457,7 +395,7 @@ func (r *userResource) ImportState(
|
||||||
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("instance_id"), idParts[2])...)
|
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, "Sqlserverflexbeta user state imported")
|
tflog.Info(ctx, "Postgres Flex user state imported")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -482,9 +420,8 @@ func (r *userResource) ImportState(
|
||||||
core.LogAndAddWarning(
|
core.LogAndAddWarning(
|
||||||
ctx,
|
ctx,
|
||||||
&resp.Diagnostics,
|
&resp.Diagnostics,
|
||||||
"Sqlserverflexbeta database imported with empty password",
|
"SQLServer Flex user 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.",
|
"The user password is not imported as it is only available upon creation of a new user. The password field will be empty.",
|
||||||
)
|
)
|
||||||
tflog.Info(ctx, "Sqlserverflexbeta user state imported")
|
tflog.Info(ctx, "SQLServer Flex user state imported")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
stackit/internal/services/sqlserverflexbeta/utils/util.go
Normal file
47
stackit/internal/services/sqlserverflexbeta/utils/util.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||||
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConfigureClient(
|
||||||
|
ctx context.Context,
|
||||||
|
providerData *core.ProviderData,
|
||||||
|
diags *diag.Diagnostics,
|
||||||
|
) *sqlserverflex.APIClient {
|
||||||
|
apiClientConfigOptions := []config.ConfigurationOption{
|
||||||
|
config.WithCustomAuth(providerData.RoundTripper),
|
||||||
|
utils.UserAgentConfigOption(providerData.Version),
|
||||||
|
}
|
||||||
|
if providerData.SQLServerFlexCustomEndpoint != "" {
|
||||||
|
apiClientConfigOptions = append(
|
||||||
|
apiClientConfigOptions,
|
||||||
|
config.WithEndpoint(providerData.SQLServerFlexCustomEndpoint),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(providerData.GetRegion()))
|
||||||
|
}
|
||||||
|
apiClient, err := sqlserverflex.NewAPIClient(apiClientConfigOptions...)
|
||||||
|
if err != nil {
|
||||||
|
core.LogAndAddError(
|
||||||
|
ctx,
|
||||||
|
diags,
|
||||||
|
"Error configuring API client",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration",
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiClient
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||||
|
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"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testVersion = "1.2.3"
|
||||||
|
testCustomEndpoint = "https://sqlserverflex-custom-endpoint.api.stackit.cloud"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigureClient(t *testing.T) {
|
||||||
|
/* mock authentication by setting service account token env variable */
|
||||||
|
os.Clearenv()
|
||||||
|
err := os.Setenv(sdkClients.ServiceAccountToken, "mock-val")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error setting env variable: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
providerData *core.ProviderData
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
expected *sqlserverflex.APIClient
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default endpoint",
|
||||||
|
args: args{
|
||||||
|
providerData: &core.ProviderData{
|
||||||
|
Version: testVersion,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: func() *sqlserverflex.APIClient {
|
||||||
|
apiClient, err := sqlserverflex.NewAPIClient(
|
||||||
|
config.WithRegion("eu01"),
|
||||||
|
utils.UserAgentConfigOption(testVersion),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error configuring client: %v", err)
|
||||||
|
}
|
||||||
|
return apiClient
|
||||||
|
}(),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom endpoint",
|
||||||
|
args: args{
|
||||||
|
providerData: &core.ProviderData{
|
||||||
|
Version: testVersion,
|
||||||
|
SQLServerFlexCustomEndpoint: testCustomEndpoint,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: func() *sqlserverflex.APIClient {
|
||||||
|
apiClient, err := sqlserverflex.NewAPIClient(
|
||||||
|
utils.UserAgentConfigOption(testVersion),
|
||||||
|
config.WithEndpoint(testCustomEndpoint),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error configuring client: %v", err)
|
||||||
|
}
|
||||||
|
return apiClient
|
||||||
|
}(),
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(
|
||||||
|
tt.name, func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
diags := diag.Diagnostics{}
|
||||||
|
|
||||||
|
actual := ConfigureClient(ctx, tt.args.providerData, &diags)
|
||||||
|
if diags.HasError() != tt.wantErr {
|
||||||
|
t.Errorf("ConfigureClient() error = %v, want %v", diags.HasError(), tt.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, tt.expected) {
|
||||||
|
t.Errorf("ConfigureClient() = %v, want %v", actual, tt.expected)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,9 +27,35 @@ const (
|
||||||
|
|
||||||
// APIClientInterface Interface needed for tests
|
// APIClientInterface Interface needed for tests
|
||||||
type APIClientInterface interface {
|
type APIClientInterface interface {
|
||||||
GetInstanceRequestExecute(ctx context.Context, projectId, region, instanceId string) (*sqlserverflex.GetInstanceResponse, error)
|
GetInstanceRequestExecute(
|
||||||
GetDatabaseRequestExecute(ctx context.Context, projectId string, region string, instanceId string, databaseName string) (*sqlserverflex.GetDatabaseResponse, error)
|
ctx context.Context,
|
||||||
GetUserRequestExecute(ctx context.Context, projectId string, region string, instanceId string, userId int64) (*sqlserverflex.GetUserResponse, error)
|
projectId, region, instanceId string,
|
||||||
|
) (*sqlserverflex.GetInstanceResponse, error)
|
||||||
|
GetDatabaseRequestExecute(
|
||||||
|
ctx context.Context,
|
||||||
|
projectId string,
|
||||||
|
region string,
|
||||||
|
instanceId string,
|
||||||
|
databaseName string,
|
||||||
|
) (*sqlserverflex.GetDatabaseResponse, error)
|
||||||
|
GetUserRequestExecute(
|
||||||
|
ctx context.Context,
|
||||||
|
projectId string,
|
||||||
|
region string,
|
||||||
|
instanceId string,
|
||||||
|
userId int64,
|
||||||
|
) (*sqlserverflex.GetUserResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIClientUserInterface Interface needed for tests
|
||||||
|
type APIClientUserInterface interface {
|
||||||
|
DeleteUserRequestExecute(
|
||||||
|
ctx context.Context,
|
||||||
|
projectId string,
|
||||||
|
region string,
|
||||||
|
instanceId string,
|
||||||
|
userId int64,
|
||||||
|
) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateInstanceWaitHandler will wait for instance creation
|
// CreateInstanceWaitHandler will wait for instance creation
|
||||||
|
|
@ -38,7 +64,8 @@ func CreateInstanceWaitHandler(
|
||||||
a APIClientInterface,
|
a APIClientInterface,
|
||||||
projectId, instanceId, region string,
|
projectId, instanceId, region string,
|
||||||
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
|
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
|
||||||
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
|
handler := wait.New(
|
||||||
|
func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
|
||||||
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
|
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
|
|
@ -62,24 +89,34 @@ func CreateInstanceWaitHandler(
|
||||||
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
|
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
|
||||||
return true, s, fmt.Errorf("create failed for instance with id %s", instanceId)
|
return true, s, fmt.Errorf("create failed for instance with id %s", instanceId)
|
||||||
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
|
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
|
||||||
tflog.Info(ctx, "request is being handled", map[string]interface{}{
|
tflog.Info(
|
||||||
|
ctx, "request is being handled", map[string]interface{}{
|
||||||
"status": *s.Status,
|
"status": *s.Status,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return false, nil, nil
|
return false, nil, nil
|
||||||
default:
|
default:
|
||||||
tflog.Info(ctx, "Wait (create) received unknown status", map[string]interface{}{
|
tflog.Info(
|
||||||
|
ctx, "Wait (create) received unknown status", map[string]interface{}{
|
||||||
"instanceId": instanceId,
|
"instanceId": instanceId,
|
||||||
"status": s.Status,
|
"status": s.Status,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return false, s, nil
|
return false, s, nil
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateInstanceWaitHandler will wait for instance update
|
// UpdateInstanceWaitHandler will wait for instance update
|
||||||
func UpdateInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId, region string) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
|
func UpdateInstanceWaitHandler(
|
||||||
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
|
ctx context.Context,
|
||||||
|
a APIClientInterface,
|
||||||
|
projectId, instanceId, region string,
|
||||||
|
) *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.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
|
|
@ -93,24 +130,34 @@ func UpdateInstanceWaitHandler(ctx context.Context, a APIClientInterface, projec
|
||||||
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
|
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
|
||||||
return true, s, fmt.Errorf("update failed for instance with id %s", instanceId)
|
return true, s, fmt.Errorf("update failed for instance with id %s", instanceId)
|
||||||
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
|
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
|
||||||
tflog.Info(ctx, "request is being handled", map[string]interface{}{
|
tflog.Info(
|
||||||
|
ctx, "request is being handled", map[string]interface{}{
|
||||||
"status": *s.Status,
|
"status": *s.Status,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return false, s, nil
|
return false, s, nil
|
||||||
default:
|
default:
|
||||||
tflog.Info(ctx, "Wait (update) received unknown status", map[string]interface{}{
|
tflog.Info(
|
||||||
|
ctx, "Wait (update) received unknown status", map[string]interface{}{
|
||||||
"instanceId": instanceId,
|
"instanceId": instanceId,
|
||||||
"status": s.Status,
|
"status": s.Status,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return false, s, nil
|
return false, s, nil
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInstanceWaitHandler will wait for instance deletion
|
// DeleteInstanceWaitHandler will wait for instance deletion
|
||||||
func DeleteInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId, region string) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
|
func DeleteInstanceWaitHandler(
|
||||||
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
|
ctx context.Context,
|
||||||
|
a APIClientInterface,
|
||||||
|
projectId, instanceId, region string,
|
||||||
|
) *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.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false, s, nil
|
return false, s, nil
|
||||||
|
|
@ -124,7 +171,8 @@ func DeleteInstanceWaitHandler(ctx context.Context, a APIClientInterface, projec
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return true, nil, nil
|
return true, nil, nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
handler.SetTimeout(30 * time.Minute)
|
handler.SetTimeout(30 * time.Minute)
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +183,8 @@ func CreateDatabaseWaitHandler(
|
||||||
a APIClientInterface,
|
a APIClientInterface,
|
||||||
projectId, instanceId, region, databaseName string,
|
projectId, instanceId, region, databaseName string,
|
||||||
) *wait.AsyncActionHandler[sqlserverflex.GetDatabaseResponse] {
|
) *wait.AsyncActionHandler[sqlserverflex.GetDatabaseResponse] {
|
||||||
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetDatabaseResponse, err error) {
|
handler := wait.New(
|
||||||
|
func() (waitFinished bool, response *sqlserverflex.GetDatabaseResponse, err error) {
|
||||||
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
|
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
|
|
@ -152,6 +201,42 @@ func CreateDatabaseWaitHandler(
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
return true, nil, nil
|
return true, nil, nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUserWaitHandler will wait for instance deletion
|
||||||
|
func DeleteUserWaitHandler(
|
||||||
|
ctx context.Context,
|
||||||
|
a APIClientUserInterface,
|
||||||
|
projectId, instanceId, region string,
|
||||||
|
userId int64,
|
||||||
|
) *wait.AsyncActionHandler[struct{}] {
|
||||||
|
handler := wait.New(
|
||||||
|
func() (waitFinished bool, response *struct{}, err error) {
|
||||||
|
err = a.DeleteUserRequestExecute(ctx, projectId, region, instanceId, userId)
|
||||||
|
if err == nil {
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
var oapiErr *oapierror.GenericOpenAPIError
|
||||||
|
ok := errors.As(err, &oapiErr)
|
||||||
|
if !ok {
|
||||||
|
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch oapiErr.StatusCode {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return true, nil, nil
|
||||||
|
case http.StatusInternalServerError:
|
||||||
|
tflog.Warn(ctx, "Wait handler got error 500")
|
||||||
|
return false, nil, nil
|
||||||
|
default:
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
handler.SetTimeout(15 * time.Minute)
|
||||||
|
handler.SetSleepBeforeWait(15 * time.Second)
|
||||||
return handler
|
return handler
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue