fix: clean up code

This commit is contained in:
Andre_Harms 2026-02-18 14:00:15 +01:00
parent 36eccc52c3
commit 7181f87aba
41 changed files with 875 additions and 682 deletions

View file

@ -32,7 +32,7 @@ const (
type EphemeralProviderData struct {
ProviderData
PrivateKey string
PrivateKey string //nolint:gosec //this is a placeholder and not used in this code
PrivateKeyPath string
ServiceAccountKey string
ServiceAccountKeyPath string
@ -105,11 +105,13 @@ func DiagsToError(diags diag.Diagnostics) error {
diagsError := diags.Errors()
diagsStrings := make([]string, 0)
for _, diagnostic := range diagsError {
diagsStrings = append(diagsStrings, fmt.Sprintf(
"(%s) %s",
diagnostic.Summary(),
diagnostic.Detail(),
))
diagsStrings = append(
diagsStrings, fmt.Sprintf(
"(%s) %s",
diagnostic.Summary(),
diagnostic.Detail(),
),
)
}
return fmt.Errorf("%s", strings.Join(diagsStrings, ";"))
}
@ -136,14 +138,22 @@ func LogAndAddWarning(ctx context.Context, diags *diag.Diagnostics, summary, det
func LogAndAddWarningBeta(ctx context.Context, diags *diag.Diagnostics, name string, resourceType ResourceType) {
warnTitle := fmt.Sprintf("The %s %q is in beta", resourceType, name)
warnContent := fmt.Sprintf("The %s %q is in beta and may be subject to breaking changes in the future. Use with caution.", resourceType, name)
warnContent := fmt.Sprintf(
"The %s %q is in beta and may be subject to breaking changes in the future. Use with caution.",
resourceType,
name,
)
tflog.Warn(ctx, fmt.Sprintf("%s | %s", warnTitle, warnContent))
diags.AddWarning(warnTitle, warnContent)
}
func LogAndAddErrorBeta(ctx context.Context, diags *diag.Diagnostics, name string, resourceType ResourceType) {
errTitle := fmt.Sprintf("The %s %q is in beta and beta is not enabled", resourceType, name)
errContent := fmt.Sprintf(`The %s %q is in beta and the beta functionality is currently not enabled. To enable it, set the environment variable STACKIT_TF_ENABLE_BETA_RESOURCES to "true" or set the "enable_beta_resources" provider field to true.`, resourceType, name)
errContent := fmt.Sprintf(
`The %s %q is in beta and the beta functionality is currently not enabled. To enable it, set the environment variable STACKIT_TF_ENABLE_BETA_RESOURCES to "true" or set the "enable_beta_resources" provider field to true.`,
resourceType,
name,
)
tflog.Error(ctx, fmt.Sprintf("%s | %s", errTitle, errContent))
diags.AddError(errTitle, errContent)
}
@ -161,8 +171,10 @@ func LogResponse(ctx context.Context) context.Context {
traceId := runtime.GetTraceId(ctx)
ctx = tflog.SetField(ctx, "x-trace-id", traceId)
tflog.Info(ctx, "response data", map[string]interface{}{
"x-trace-id": traceId,
})
tflog.Info(
ctx, "response data", map[string]interface{}{
"x-trace-id": traceId,
},
)
return ctx
}

View file

@ -98,7 +98,7 @@ func (rrt *RetryRoundTripper) retryLoop(
waitDuration := rrt.calculateWaitDurationWithJitter(ctx, currentDelay)
if err := rrt.waitForDelay(ctx, waitDuration); err != nil {
return nil, err // Context was cancelled during wait.
return nil, err // Context was canceled during wait.
}
// Exponential backoff for the next potential retry.
@ -153,7 +153,6 @@ func (rrt *RetryRoundTripper) handleFinalError(
) error {
if resp != nil {
if err := resp.Body.Close(); err != nil {
tflog.Warn(
ctx, "Failed to close response body", map[string]interface{}{
"error": err.Error(),
@ -194,7 +193,6 @@ func (rrt *RetryRoundTripper) shouldRetry(resp *http.Response, err error) bool {
}
return false
}
// calculateWaitDurationWithJitter calculates the backoff duration for the next retry,
@ -232,7 +230,7 @@ func (rrt *RetryRoundTripper) calculateWaitDurationWithJitter(
func (rrt *RetryRoundTripper) waitForDelay(ctx context.Context, delay time.Duration) error {
select {
case <-ctx.Done():
return fmt.Errorf("context cancelled during backoff wait: %w", ctx.Err())
return fmt.Errorf("context canceled during backoff wait: %w", ctx.Err())
case <-time.After(delay):
return nil
}

View file

@ -72,7 +72,7 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
},
}
tripper := testRetryConfig(mock)
req := httptest.NewRequest(http.MethodGet, "/", nil)
req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
resp, err := tripper.RoundTrip(req)
if resp != nil {
@ -110,7 +110,7 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
},
}
tripper := testRetryConfig(mock)
req := httptest.NewRequest(http.MethodGet, "/", nil)
req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
resp, err := tripper.RoundTrip(req)
if resp != nil {
@ -155,7 +155,7 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
}, nil
}
tripper := testRetryConfig(mock)
req := httptest.NewRequest(http.MethodGet, "/", nil)
req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
resp, err := tripper.RoundTrip(req)
if resp != nil {
@ -185,12 +185,12 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
mockErr := errors.New("simulated network error")
mock := &mockRoundTripper{
roundTripFunc: func(req *http.Request) (*http.Response, error) {
roundTripFunc: func(_ *http.Request) (*http.Response, error) {
return nil, mockErr
},
}
tripper := testRetryConfig(mock)
req := httptest.NewRequest(http.MethodGet, "/", nil)
req := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
resp, err := tripper.RoundTrip(req)
if resp != nil {
@ -211,7 +211,7 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
)
t.Run(
"should abort retries if the main context is cancelled", func(t *testing.T) {
"should abort retries if the main context is canceled", func(t *testing.T) {
t.Parallel()
mock := &mockRoundTripper{
@ -230,7 +230,7 @@ func TestRetryRoundTripper_RoundTrip(t *testing.T) {
ctx, cancel := context.WithTimeout(baseCtx, 20*time.Millisecond)
defer cancel()
req := httptest.NewRequest(http.MethodGet, "/", nil).WithContext(ctx)
req := httptest.NewRequest(http.MethodGet, "/", http.NoBody).WithContext(ctx)
resp, err := tripper.RoundTrip(req)
if resp != nil {

View file

@ -328,10 +328,6 @@ func (r *instanceResource) Read(
ctx = core.InitProviderContext(ctx)
// projectId := model.ProjectId.ValueString()
// region := r.providerData.GetRegionWithOverride(model.Region)
// instanceId := model.InstanceId.ValueString()
var projectId string
if !model.ProjectId.IsNull() && !model.ProjectId.IsUnknown() {
projectId = model.ProjectId.ValueString()
@ -435,18 +431,6 @@ func (r *instanceResource) Update(
return
}
// if model.InstanceId.IsNull() || model.InstanceId.IsUnknown() {
// core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", "instanceId is null or unknown")
// return
//}
//
// if model.ProjectId.IsNull() || model.ProjectId.IsUnknown() {
// core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating instance", "projectId is null or unknown")
// return
//}
// projectId := model.ProjectId.ValueString()
// instanceId := model.InstanceId.ValueString()
projectId := identityData.ProjectID.ValueString()
instanceId := identityData.InstanceID.ValueString()
region := model.Region.ValueString()

View file

@ -30,39 +30,46 @@ var testInstances []string
func init() {
sweeperName := fmt.Sprintf("%s_%s", pfx, "sweeper")
resource.AddTestSweepers(sweeperName, &resource.Sweeper{
Name: sweeperName,
F: func(region string) error {
ctx := context.Background()
apiClientConfigOptions := []config.ConfigurationOption{}
apiClient, err := postgresflexalpha2.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
resource.AddTestSweepers(
sweeperName, &resource.Sweeper{
Name: sweeperName,
F: func(_ string) error { // region is passed by the testing framework
ctx := context.Background()
apiClientConfigOptions := []config.ConfigurationOption{}
apiClient, err := postgresflexalpha2.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instances, err := apiClient.ListInstancesRequest(ctx, testutils.ProjectId, testutils.Region).
Size(100).
Execute()
if err != nil {
log.Fatalln(err)
}
instances, err := apiClient.ListInstancesRequest(ctx, testutils.ProjectId, testutils.Region).
Size(100).
Execute()
if err != nil {
log.Fatalln(err)
}
for _, inst := range instances.GetInstances() {
if strings.HasPrefix(inst.GetName(), "tf-acc-") {
for _, item := range testInstances {
if inst.GetName() == item {
delErr := apiClient.DeleteInstanceRequestExecute(ctx, testutils.ProjectId, testutils.Region, inst.GetId())
if delErr != nil {
// TODO: maybe just warn?
log.Fatalln(delErr)
for _, inst := range instances.GetInstances() {
if strings.HasPrefix(inst.GetName(), "tf-acc-") {
for _, item := range testInstances {
if inst.GetName() == item {
delErr := apiClient.DeleteInstanceRequestExecute(
ctx,
testutils.ProjectId,
testutils.Region,
inst.GetId(),
)
if delErr != nil {
// TODO: maybe just warn?
log.Fatalln(delErr)
}
}
}
}
}
}
return nil
return nil
},
},
})
)
}
func TestInstanceResourceSchema(t *testing.T) {
@ -195,57 +202,67 @@ func TestAccInstance(t *testing.T) {
updSizeData := exData
updSizeData.Size = 25
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", exData.TfName)
testInstances = append(testInstances, exData.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
exData,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "instance", exData.TfName), "name", exData.Name),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", exData.TfName), "id"),
),
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", exData.TfName)
testInstances = append(testInstances, exData.TfName)
},
// Update name and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updNameData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "instance", exData.TfName), "name", updNameData.Name),
),
},
// Update size and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updSizeData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"storage.size",
strconv.Itoa(int(updSizeData.Size)),
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
exData,
),
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"name",
exData.Name,
),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", exData.TfName), "id"),
),
},
// Update name and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updNameData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"name",
updNameData.Name,
),
),
},
// Update size and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updSizeData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", exData.TfName),
"storage.size",
strconv.Itoa(int(updSizeData.Size)),
),
),
},
//// Import test
//{
// ResourceName: "example_resource.test",
// ImportState: true,
// ImportStateVerify: true,
// },
},
//// Import test
//{
// ResourceName: "example_resource.test",
// ImportState: true,
// ImportStateVerify: true,
// },
},
})
)
}
func TestAccInstanceWithUsers(t *testing.T) {
@ -260,29 +277,35 @@ func TestAccInstanceWithUsers(t *testing.T) {
},
}
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "instance", data.TfName), "name", data.Name),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", data.TfName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
),
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", data.TfName),
"name",
data.Name,
),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", data.TfName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
),
},
},
},
})
)
}
func TestAccInstanceWithDatabases(t *testing.T) {
@ -306,32 +329,38 @@ func TestAccInstanceWithDatabases(t *testing.T) {
},
}
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "instance", data.TfName), "name", data.Name),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", data.TfName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "name", dbName),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "owner", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "database", dbName), "id"),
),
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... working on instance %s", data.TfName)
testInstances = append(testInstances, data.TfName)
},
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
testutils.ResStr(pfx, "instance", data.TfName),
"name",
data.Name,
),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "instance", data.TfName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "name", dbName),
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "database", dbName), "owner", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "database", dbName), "id"),
),
},
},
},
})
)
}
// func setupMockServer() *httptest.Server {
@ -461,7 +490,7 @@ func TestAccInstanceWithDatabases(t *testing.T) {
// "project_id": testutils.ProjectId,
//}
//
//func configResources(backupSchedule string, _ *string) string {
// func configResources(backupSchedule string, _ *string) string {
// return fmt.Sprintf(
// `
// %s
@ -535,7 +564,7 @@ func TestAccInstanceWithDatabases(t *testing.T) {
// )
//}
//
//func TestAccPostgresFlexFlexResource(t *testing.T) {
// func TestAccPostgresFlexFlexResource(t *testing.T) {
// resource.ParallelTest(
// t, resource.TestCase{
// ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
@ -954,7 +983,7 @@ func TestAccInstanceWithDatabases(t *testing.T) {
// )
//}
//
//func testAccCheckPostgresFlexDestroy(s *terraform.State) error {
// func testAccCheckPostgresFlexDestroy(s *terraform.State) error {
// ctx := context.Background()
// var client *postgresflex.APIClient
// var err error

View file

@ -252,7 +252,6 @@ func (r *userResource) Create(
model.UserId = types.Int64Value(id)
model.Password = types.StringValue(userResp.GetPassword())
model.Status = types.StringValue(userResp.GetStatus())
//model.ConnectionString = types.StringValue(userResp.GetConnectionString())
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
ctx,

View file

@ -143,7 +143,6 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
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.

View file

@ -36,10 +36,6 @@ var (
// Define errors
errDatabaseNotFound = errors.New("database not found")
// Error message constants
extractErrorSummary = "extracting failed"
extractErrorMessage = "Extracting identity data: %v"
)
func NewDatabaseResource() resource.Resource {
@ -186,26 +182,6 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques
payLoad.Name = data.Name.ValueStringPointer()
payLoad.Owner = data.Owner.ValueStringPointer()
//_, err := wait.WaitForUserWaitHandler(
// ctx,
// r.client,
// projectId,
// instanceId,
// region,
// data.Owner.ValueString(),
//).
// SetSleepBeforeWait(10 * time.Second).
// WaitWithContext(ctx)
//if err != nil {
// core.LogAndAddError(
// ctx,
// &resp.Diagnostics,
// createErr,
// fmt.Sprintf("Calling API: %v", err),
// )
// return
//}
createResp, err := r.client.CreateDatabaseRequest(ctx, projectId, region, instanceId).
CreateDatabaseRequestPayload(payLoad).
Execute()
@ -451,7 +427,9 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques
&resp.Diagnostics,
"Error deleting database",
fmt.Sprintf(
"Calling API: %v\nname: %s, region: %s, instanceId: %s", err, databaseName, region, instanceId))
"Calling API: %v\nname: %s, region: %s, instanceId: %s", err, databaseName, region, instanceId,
),
)
return
}
@ -468,7 +446,6 @@ func (r *databaseResource) ModifyPlan(
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return

View file

@ -247,7 +247,6 @@ func toCreatePayload(
conversion.StringValueToPointer(model.Version),
),
}, nil
}
func toUpdatePayload(

View file

@ -54,7 +54,7 @@ type InstanceResourceIdentityModel struct {
}
func (r *instanceResource) Metadata(
ctx context.Context,
_ context.Context,
req resource.MetadataRequest,
resp *resource.MetadataResponse,
) {
@ -64,7 +64,7 @@ func (r *instanceResource) Metadata(
//go:embed planModifiers.yaml
var modifiersFileByte []byte
func (r *instanceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
func (r *instanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
s := sqlserverflexalphaResGen.InstanceResourceSchema(ctx)
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
@ -147,7 +147,6 @@ func (r *instanceResource) ModifyPlan(
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return

View file

@ -288,8 +288,8 @@ func TestAccInstanceNoEncryption(t *testing.T) {
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_version"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.access_scope"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.acl"),
@ -389,8 +389,8 @@ func TestAccInstanceEncryption(t *testing.T) {
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_version"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.access_scope"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.acl"),

View file

@ -20,8 +20,6 @@ import (
var _ datasource.DataSource = (*userDataSource)(nil)
const errorPrefix = "[sqlserverflexalpha - User]"
func NewUserDataSource() datasource.DataSource {
return &userDataSource{}
}

View file

@ -20,7 +20,6 @@ import (
"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"
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"
sqlserverflexalphaWait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexalpha"
@ -59,7 +58,7 @@ type userResource struct {
providerData core.ProviderData
}
func (r *userResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
func (r *userResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_sqlserverflexalpha_user"
}
@ -118,7 +117,7 @@ var modifiersFileByte []byte
// Schema defines the schema for the resource.
func (r *userResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
s := sqlserverflexalphagen.UserResourceSchema(ctx)
s := sqlserverflexalphaResGen.UserResourceSchema(ctx)
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
if err != nil {
@ -470,7 +469,6 @@ func (r *userResource) Delete(
// Delete existing record set
_, err = sqlserverflexalphaWait.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

View file

@ -143,7 +143,6 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques
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.

View file

@ -36,10 +36,6 @@ var (
// Define errors
errDatabaseNotFound = errors.New("database not found")
// Error message constants
extractErrorSummary = "extracting failed"
extractErrorMessage = "Extracting identity data: %v"
)
func NewDatabaseResource() resource.Resource {
@ -430,7 +426,9 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques
&resp.Diagnostics,
"Error deleting database",
fmt.Sprintf(
"Calling API: %v\nname: %s, region: %s, instanceId: %s", err, databaseName, region, instanceId))
"Calling API: %v\nname: %s, region: %s, instanceId: %s", err, databaseName, region, instanceId,
),
)
return
}
@ -449,7 +447,6 @@ func (r *databaseResource) ModifyPlan(
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return
@ -559,45 +556,4 @@ func (r *databaseResource) ImportState(
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.Name.IsNull() && !model.Name.IsUnknown() {
databaseName = model.Name.ValueString()
} else {
if identity.DatabaseName.IsNull() || identity.DatabaseName.IsUnknown() {
return "", "", "", "", fmt.Errorf("database_name not found in config")
}
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
}
// extractIdentityData extracts essential identifiers from the resource model, falling back to the identity mode

View file

@ -236,7 +236,6 @@ func toCreatePayload(
conversion.StringValueToPointer(model.Version),
),
}, nil
}
func toUpdatePayload(

View file

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
sqlserverflexbetaPkgGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
sqlserverflexbetaRs "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance/resources_gen"
)
@ -28,11 +29,13 @@ func Test_handleDSEncryption(t *testing.T) {
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := handleDSEncryption(tt.args.m, tt.args.resp); !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleDSEncryption() = %v, want %v", got, tt.want)
}
})
t.Run(
tt.name, func(t *testing.T) {
if got := handleDSEncryption(t.Context(), tt.args.m, tt.args.resp); !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleDSEncryption() = %v, want %v", got, tt.want)
}
},
)
}
}
@ -86,11 +89,13 @@ func Test_handleEncryption(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := handleEncryption(tt.args.m, tt.args.resp); !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleEncryption() = %v, want %v", got, tt.want)
}
})
t.Run(
tt.name, func(t *testing.T) {
if got := handleEncryption(t.Context(), tt.args.m, tt.args.resp); !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleEncryption() = %v, want %v", got, tt.want)
}
},
)
}
}
@ -109,11 +114,18 @@ func Test_mapDataResponseToModel(t *testing.T) {
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := mapDataResponseToModel(tt.args.ctx, tt.args.resp, tt.args.m, tt.args.tfDiags); (err != nil) != tt.wantErr {
t.Errorf("mapDataResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
})
t.Run(
tt.name, func(t *testing.T) {
if err := mapDataResponseToModel(
tt.args.ctx,
tt.args.resp,
tt.args.m,
tt.args.tfDiags,
); (err != nil) != tt.wantErr {
t.Errorf("mapDataResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
},
)
}
}
@ -132,11 +144,18 @@ func Test_mapResponseToModel(t *testing.T) {
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := mapResponseToModel(tt.args.ctx, tt.args.resp, tt.args.m, tt.args.tfDiags); (err != nil) != tt.wantErr {
t.Errorf("mapResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
})
t.Run(
tt.name, func(t *testing.T) {
if err := mapResponseToModel(
tt.args.ctx,
tt.args.resp,
tt.args.m,
tt.args.tfDiags,
); (err != nil) != tt.wantErr {
t.Errorf("mapResponseToModel() error = %v, wantErr %v", err, tt.wantErr)
}
},
)
}
}
@ -208,19 +227,18 @@ func Test_toCreatePayload(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := toCreatePayload(tt.args.ctx, tt.args.model)
if (err != nil) != tt.wantErr {
t.Errorf("toCreatePayload() error = %v, wantErr %v", err, tt.wantErr)
return
}
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("model mismatch (-want +got):\n%s", diff)
}
//if !reflect.DeepEqual(got, tt.want) {
// t.Errorf("toCreatePayload() got = %v, want %v", got, tt.want)
//}
})
t.Run(
tt.name, func(t *testing.T) {
got, err := toCreatePayload(tt.args.ctx, tt.args.model)
if (err != nil) != tt.wantErr {
t.Errorf("toCreatePayload() error = %v, wantErr %v", err, tt.wantErr)
return
}
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("model mismatch (-want +got):\n%s", diff)
}
},
)
}
}
@ -239,15 +257,17 @@ func Test_toUpdatePayload(t *testing.T) {
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := toUpdatePayload(tt.args.ctx, tt.args.m, tt.args.resp)
if (err != nil) != tt.wantErr {
t.Errorf("toUpdatePayload() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("toUpdatePayload() got = %v, want %v", got, tt.want)
}
})
t.Run(
tt.name, func(t *testing.T) {
got, err := toUpdatePayload(tt.args.ctx, tt.args.m, tt.args.resp)
if (err != nil) != tt.wantErr {
t.Errorf("toUpdatePayload() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("toUpdatePayload() got = %v, want %v", got, tt.want)
}
},
)
}
}

View file

@ -54,7 +54,7 @@ type InstanceResourceIdentityModel struct {
}
func (r *instanceResource) Metadata(
ctx context.Context,
_ context.Context,
req resource.MetadataRequest,
resp *resource.MetadataResponse,
) {
@ -64,7 +64,7 @@ func (r *instanceResource) Metadata(
//go:embed planModifiers.yaml
var modifiersFileByte []byte
func (r *instanceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
func (r *instanceResource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
s := sqlserverflexbetaResGen.InstanceResourceSchema(ctx)
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
@ -147,7 +147,6 @@ func (r *instanceResource) ModifyPlan(
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return

View file

@ -349,8 +349,8 @@ func TestAccInstanceNoEncryption(t *testing.T) {
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_version"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.access_scope"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.acl"),
@ -450,8 +450,8 @@ func TestAccInstanceEncryption(t *testing.T) {
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_version"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
//resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.kek_key_ring_id"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "encryption.service_account"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.access_scope"),
// resource.TestCheckResourceAttrSet(resName("instance", data.TfName), "network.acl"),

View file

@ -20,8 +20,6 @@ import (
var _ datasource.DataSource = (*userDataSource)(nil)
const errorPrefix = "[Sqlserverflexbeta - User]"
func NewUserDataSource() datasource.DataSource {
return &userDataSource{}
}

View file

@ -20,7 +20,6 @@ import (
"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"
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"
@ -59,7 +58,7 @@ type userResource struct {
providerData core.ProviderData
}
func (r *userResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
func (r *userResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_sqlserverflexbeta_user"
}
@ -108,23 +107,23 @@ func (r *userResource) ModifyPlan(
}
//// TODO: verify if this is needed - START
//var planRoles []string
//diags := planModel.Roles.ElementsAs(ctx, &planRoles, false)
//resp.Diagnostics.Append(diags...)
//if diags.HasError() {
// var planRoles []string
// diags := planModel.Roles.ElementsAs(ctx, &planRoles, false)
// resp.Diagnostics.Append(diags...)
// if diags.HasError() {
// return
//}
//slices.Sort(planRoles)
//var roles []attr.Value
//for _, role := range planRoles {
// slices.Sort(planRoles)
// var roles []attr.Value
// for _, role := range planRoles {
// roles = append(roles, types.StringValue(string(role)))
//}
//rolesSet, diags := types.ListValue(types.StringType, roles)
//resp.Diagnostics.Append(diags...)
//if diags.HasError() {
// rolesSet, diags := types.ListValue(types.StringType, roles)
// resp.Diagnostics.Append(diags...)
// if diags.HasError() {
// return
//}
//planModel.Roles = rolesSet
// planModel.Roles = rolesSet
//// TODO: verify if this is needed - END
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
@ -138,7 +137,7 @@ 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)
s := sqlserverflexbetaResGen.UserResourceSchema(ctx)
fields, err := utils.ReadModifiersConfig(modifiersFileByte)
if err != nil {
@ -435,7 +434,12 @@ func (r *userResource) Update(
resp *resource.UpdateResponse,
) { // nolint:gocritic // function signature required by Terraform
// Update shouldn't be called
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", "an SQL server user can not be updated, only created")
core.LogAndAddError(
ctx,
&resp.Diagnostics,
"Error updating user",
"an SQL server user can not be updated, only created",
)
}
// Delete deletes the resource and removes the Terraform state on success.
@ -489,7 +493,6 @@ func (r *userResource) Delete(
// 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

View file

@ -108,7 +108,7 @@ func CreateInstanceWaitHandler(
)
if extendedTimeout < 3 {
maxWait += time.Minute * 5
extendedTimeout = extendedTimeout + 1
extendedTimeout++
if *s.Network.AccessScope == "SNA" {
ready := true
if s.Network == nil || s.Network.InstanceAddress == nil {
@ -228,7 +228,7 @@ func GetUserByIdWaitHandler(
if userId > math.MaxInt32 {
return false, nil, fmt.Errorf("userId value is too big for int32")
}
userId32 := int32(userId)
userId32 := int32(userId) //nolint:gosec // we need to convert databaseId to int32 because API expects int32
s, err := a.GetUserRequestExecute(ctx, projectId, region, instanceId, userId32)
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
@ -239,9 +239,11 @@ func GetUserByIdWaitHandler(
switch oapiErr.StatusCode {
case http.StatusBadGateway, http.StatusGatewayTimeout, http.StatusServiceUnavailable:
case http.StatusNotFound:
tflog.Warn(ctx, "api responded with status", map[string]interface{}{
"status": oapiErr.StatusCode,
})
tflog.Warn(
ctx, "api responded with status", map[string]interface{}{
"status": oapiErr.StatusCode,
},
)
return false, nil, nil
default:
return false, nil, err
@ -262,7 +264,7 @@ func GetDatabaseByIdWaitHandler(
) *wait.AsyncActionHandler[postgresflex.GetDatabaseResponse] {
handler := wait.New(
func() (waitFinished bool, response *postgresflex.GetDatabaseResponse, err error) {
dbId32 := int32(databaseId)
dbId32 := int32(databaseId) //nolint:gosec // we need to convert databaseId to int32 because API expects int32
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, dbId32)
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
@ -272,14 +274,18 @@ func GetDatabaseByIdWaitHandler(
}
switch oapiErr.StatusCode {
case http.StatusBadGateway, http.StatusGatewayTimeout, http.StatusServiceUnavailable:
tflog.Warn(ctx, "api responded with 50[2,3,4] status", map[string]interface{}{
"status": oapiErr.StatusCode,
})
tflog.Warn(
ctx, "api responded with 50[2,3,4] status", map[string]interface{}{
"status": oapiErr.StatusCode,
},
)
return false, nil, nil
case http.StatusNotFound:
tflog.Warn(ctx, "api responded with 404 status", map[string]interface{}{
"status": oapiErr.StatusCode,
})
tflog.Warn(
ctx, "api responded with 404 status", map[string]interface{}{
"status": oapiErr.StatusCode,
},
)
return false, nil, nil
default:
return false, nil, err

View file

@ -54,7 +54,12 @@ type APIClientInterface interface {
instanceId string,
) (*sqlserverflex.ListRolesResponse, error)
ListUsersRequest(ctx context.Context, projectId string, region string, instanceId string) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequestExecute(
ctx context.Context,
@ -256,7 +261,10 @@ func CreateDatabaseWaitHandler(
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("get database - could not convert error to oapierror.GenericOpenAPIError: %s", err.Error())
return false, nil, fmt.Errorf(
"get database - could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
@ -318,7 +326,10 @@ func WaitForUserWaitHandler(
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("Wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s", err.Error())
return false, nil, fmt.Errorf(
"wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err

View file

@ -116,7 +116,6 @@ func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
//stateSuccess := utils.Ptr(InstanceStateSuccess)
instanceId := utils.Ptr("foo")
tests := []struct {
desc string
@ -160,7 +159,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
// Storage: nil,
// Version: nil,
// },
//},
// },
{
desc: "create_failed",
instanceId: *instanceId,

View file

@ -54,7 +54,12 @@ type APIClientInterface interface {
instanceId string,
) (*sqlserverflex.ListRolesResponse, error)
ListUsersRequest(ctx context.Context, projectId string, region string, instanceId string) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) sqlserverflex.ApiListUsersRequestRequest
ListUsersRequestExecute(
ctx context.Context,
@ -162,9 +167,17 @@ func CreateInstanceWaitHandler(
}
return true, s, nil
case strings.ToLower(InstanceStateUnknown):
return true, nil, fmt.Errorf("create failed for instance %s with status %s", instanceId, InstanceStateUnknown)
return true, nil, fmt.Errorf(
"create failed for instance %s with status %s",
instanceId,
InstanceStateUnknown,
)
case strings.ToLower(InstanceStateFailed):
return true, nil, fmt.Errorf("create failed for instance %s with status %s", instanceId, InstanceStateFailed)
return true, nil, fmt.Errorf(
"create failed for instance %s with status %s",
instanceId,
InstanceStateFailed,
)
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
@ -268,7 +281,10 @@ func CreateDatabaseWaitHandler(
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("get database - could not convert error to oapierror.GenericOpenAPIError: %s", err.Error())
return false, nil, fmt.Errorf(
"get database - could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
@ -330,7 +346,10 @@ func WaitForUserWaitHandler(
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("Wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s", err.Error())
return false, nil, fmt.Errorf(
"wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err

View file

@ -116,7 +116,6 @@ func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
//stateSuccess := utils.Ptr(InstanceStateSuccess)
instanceId := utils.Ptr("foo")
tests := []struct {
desc string
@ -160,7 +159,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
// Storage: nil,
// Version: nil,
// },
//},
// },
{
desc: "create_failed",
instanceId: *instanceId,

View file

@ -46,6 +46,7 @@ var (
_ provider.Provider = &Provider{}
)
//nolint:unused // These constants are defined for future use in retry logic for HTTP requests, which is not yet implemented.
const (
// maxRetries is the maximum number of retries for a failed HTTP request.
maxRetries = 3
@ -123,6 +124,7 @@ type providerModel struct {
// Schema defines the provider-level schema for configuration data.
func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
//nolint:gosec // These are just descriptions, not actual credentials or sensitive information.
descriptions := map[string]string{
"credentials_path": "Path of JSON from where the credentials are read. Takes precedence over the env var `STACKIT_CREDENTIALS_PATH`. Default value is `~/.stackit/credentials.json`.",
"service_account_token": "Token used for authentication. If set, the token flow will be used to authenticate all operations.",
@ -489,7 +491,8 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
return
}
//roundTripper := core.NewRetryRoundTripper(
//nolint:gocritic // maybe later in the code
// roundTripper := core.NewRetryRoundTripper(
// baseRoundTripper,
// maxRetries,
// initialDelay,

View file

@ -12,11 +12,12 @@ import (
"time"
"github.com/golang-jwt/jwt/v5"
test "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/google/go-cmp/cmp"
test "github.com/hashicorp/terraform-plugin-testing/helper/resource" //nolint:staticcheck // used for acceptance testing
"github.com/jarcoal/httpmock"
"github.com/stackitcloud/stackit-sdk-go/core/clients"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stretchr/testify/require"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresFlexAlphaFlavor "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor"
@ -40,7 +41,7 @@ import (
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" //nolint:staticcheck // used for acceptance testing
)
//go:embed testdata/provider-credentials.tf
@ -67,12 +68,15 @@ func TestMshTest(t *testing.T) {
testutils.ActivateEnvironmentHttpMocks()
httpmock.RegisterResponder("POST", `https://service-account.api.stackit.cloud/token`,
func(req *http.Request) (*http.Response, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"foo": "bar",
"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
})
httpmock.RegisterResponder(
"POST", `https://service-account.api.stackit.cloud/token`,
func(_ *http.Request) (*http.Response, error) {
token := jwt.NewWithClaims(
jwt.SigningMethodHS256, jwt.MapClaims{
"foo": "bar",
"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
},
)
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte("mySecret"))
if err != nil {
@ -88,10 +92,13 @@ func TestMshTest(t *testing.T) {
}
return httpmock.NewJsonResponse(http.StatusOK, tR)
})
},
)
httpmock.RegisterResponder("GET", `https://postgres-flex-service.api.eu01.stackit.cloud/v3alpha1/projects/xyz-project-id/regions/eu01/flavors?page=1&size=25&sort=id.asc`,
func(req *http.Request) (*http.Response, error) {
httpmock.RegisterResponder(
"GET",
`https://postgres-flex-service.api.eu01.stackit.cloud/v3alpha1/projects/xyz-project-id/regions/eu01/flavors?page=1&size=25&sort=id.asc`,
func(_ *http.Request) (*http.Response, error) {
res := postgresflexalpha.GetFlavorsResponse{
Flavors: &[]postgresflexalpha.ListFlavors{
{
@ -120,15 +127,17 @@ func TestMshTest(t *testing.T) {
},
)
test.Test(t, test.TestCase{
IsUnitTest: true,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []test.TestStep{
{
ConfigVariables: map[string]config.Variable{
"project_id": config.StringVariable("xyz-project-id"),
},
Config: fmt.Sprintf(`
test.Test(
t, test.TestCase{
IsUnitTest: true,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []test.TestStep{
{
ConfigVariables: map[string]config.Variable{
"project_id": config.StringVariable("xyz-project-id"),
},
Config: fmt.Sprintf(
`
provider "stackitprivatepreview" {
default_region = "%[1]s"
service_account_key_path = "%[2]s"
@ -144,12 +153,13 @@ func TestMshTest(t *testing.T) {
node_type = "Single"
storage_class = "premium-perf2-stackit"
}`,
os.Getenv("TF_ACC_REGION"),
os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
),
os.Getenv("TF_ACC_REGION"),
os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
),
},
},
},
})
)
}
func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
@ -171,12 +181,24 @@ func TestUnitProviderHasChildDataSources_Basic(t *testing.T) {
sqlserverFlexBetaUser.NewUserDataSource(),
sqlserverFlexBetaFlavor.NewFlavorDataSource(),
}
datasources := stackit.New("testing")().(*stackit.Provider).DataSources(context.Background())
provider, ok := stackit.New("testing")().(*stackit.Provider)
if !ok {
t.Fatal("could not assert provider type")
}
datasources := provider.DataSources(context.Background())
if !reflect.DeepEqual(len(expectedDataSources), len(datasources)) {
for _, d := range datasources {
require.Containsf(t, expectedDataSources, d(), "Data source %+v was not expected", reflect.TypeOf(d()))
}
expectedMap := map[string]struct{}{}
for _, d := range expectedDataSources {
expectedMap[reflect.TypeOf(d).String()] = struct{}{}
}
actualMap := map[string]struct{}{}
for _, d := range datasources {
actualMap[reflect.TypeOf(d()).String()] = struct{}{}
}
if diff := cmp.Diff(expectedMap, actualMap); diff != "" {
t.Errorf("DataSources mismatch (-expected +actual):\n%s", diff)
}
}
@ -194,12 +216,24 @@ func TestUnitProviderHasChildResources_Basic(t *testing.T) {
sqlserverFlexBetaUser.NewUserResource(),
sqlserverflexBetaDatabase.NewDatabaseResource(),
}
resources := stackit.New("testing")().(*stackit.Provider).Resources(context.Background())
provider, ok := stackit.New("testing")().(*stackit.Provider)
if !ok {
t.Fatal("could not assert provider type")
}
resources := provider.Resources(context.Background())
if !reflect.DeepEqual(len(expectedResources), len(resources)) {
for _, d := range resources {
require.Containsf(t, expectedResources, d(), "Resource %+v was not expected", reflect.TypeOf(d()))
}
expectedMap := map[string]struct{}{}
for _, r := range expectedResources {
expectedMap[reflect.TypeOf(r).String()] = struct{}{}
}
actualMap := map[string]struct{}{}
for _, r := range resources {
actualMap[reflect.TypeOf(r()).String()] = struct{}{}
}
if diff := cmp.Diff(expectedMap, actualMap); diff != "" {
t.Errorf("Resources mismatch (-expected +actual):\n%s", diff)
}
}
@ -209,23 +243,25 @@ func TestAccEnvVarServiceAccountPathValid(t *testing.T) {
if v := os.Getenv(resource.EnvTfAcc); v == "" {
t.Skipf(
"Acceptance tests skipped unless env '%s' set",
resource.EnvTfAcc)
resource.EnvTfAcc,
)
return
}
// t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(true, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
},
},
},
})
)
}
func TestAccEnvVarServiceAccountPathInvalid(t *testing.T) {
@ -233,17 +269,19 @@ func TestAccEnvVarServiceAccountPathInvalid(t *testing.T) {
t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(false, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
ExpectError: regexp.MustCompile(`undefined response type, status code 401`),
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
ExpectError: regexp.MustCompile(`undefined response type, status code 401`),
},
},
},
})
)
}
func TestAccCredentialsFileValid(t *testing.T) {
@ -251,16 +289,18 @@ func TestAccCredentialsFileValid(t *testing.T) {
t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(true, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
},
},
},
})
)
}
func TestAccCredentialsFileInvalid(t *testing.T) {
@ -268,17 +308,19 @@ func TestAccCredentialsFileInvalid(t *testing.T) {
t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(false, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
ExpectError: regexp.MustCompile(`Jwt is not in(\r\n|\r|\n)the form of Header.Payload.Signature`),
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
PreConfig: func() { testutils.SetTemporaryHome(tempHomeFolder) },
ConfigVariables: testConfigProviderCredentials,
Config: providerCredentialConfig,
ExpectError: regexp.MustCompile(`Jwt is not in(\r\n|\r|\n)the form of Header.Payload.Signature`),
},
},
},
})
)
}
func TestAccProviderConfigureValidValues(t *testing.T) {
@ -287,21 +329,25 @@ func TestAccProviderConfigureValidValues(t *testing.T) {
if v := os.Getenv(resource.EnvTfAcc); v == "" {
t.Skipf(
"Acceptance tests skipped unless env '%s' set",
resource.EnvTfAcc)
resource.EnvTfAcc,
)
return
}
t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(true, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{ // valid provider attributes
ConfigVariables: testConfigProviderCredentials,
Config: providerValidAttributes,
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
// valid provider attributes
ConfigVariables: testConfigProviderCredentials,
Config: providerValidAttributes,
},
},
},
})
)
}
func TestAccProviderConfigureAnInvalidValue(t *testing.T) {
@ -310,21 +356,25 @@ func TestAccProviderConfigureAnInvalidValue(t *testing.T) {
if v := os.Getenv(resource.EnvTfAcc); v == "" {
t.Skipf(
"Acceptance tests skipped unless env '%s' set",
resource.EnvTfAcc)
resource.EnvTfAcc,
)
return
}
t.Setenv("STACKIT_CREDENTIALS_PATH", "")
tempHomeFolder := testutils.CreateTemporaryHome(true, t)
defer testutils.CleanupTemporaryHome(tempHomeFolder, t)
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{ // invalid test attribute should throw an error
ConfigVariables: testConfigProviderCredentials,
Config: providerInvalidAttribute,
ExpectError: regexp.MustCompile(`An argument named "test" is not expected here\.`),
resource.Test(
t, resource.TestCase{
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
// invalid test attribute should throw an error
ConfigVariables: testConfigProviderCredentials,
Config: providerInvalidAttribute,
ExpectError: regexp.MustCompile(`An argument named "test" is not expected here\.`),
},
},
},
})
)
}