terraform-provider-stackitp.../stackit/internal/services/postgresflexalpha/postgresflex_acc_test.go
Marcel S. Henselin 746f7cdfbd
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 6s
TF Acceptance Tests Workflow / Acceptance Tests (pull_request) Failing after 4m51s
CI Workflow / Prepare GO cache (pull_request) Successful in 6m12s
CI Workflow / Code coverage report (pull_request) Has been cancelled
CI Workflow / Test readiness for publishing provider (pull_request) Has been cancelled
CI Workflow / CI run tests (pull_request) Has been cancelled
CI Workflow / CI run build and linting (pull_request) Has been cancelled
fix: remove identity from sqlserverbeta and postresflexalpha
2026-03-17 14:31:25 +01:00

990 lines
31 KiB
Go

package postgresflexalpha_test
import (
"context"
_ "embed"
"fmt"
"log"
"math"
"os"
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/hashicorp/terraform-plugin-testing/compare"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalphaInstance "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/postgresflexalpha"
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils"
// The fwresource import alias is so there is no collision
// with the more typical acceptance testing import:
// "github.com/hashicorp/terraform-plugin-testing/helper/resource"
fwresource "github.com/hashicorp/terraform-plugin-framework/resource"
)
const (
pfx = "stackitprivatepreview_postgresflexalpha"
dataPfx = "data.stackitprivatepreview_postgresflexalpha"
singleFlavorID = "2.4"
replicasFlavorID = "2.4-replica"
)
func TestInstanceResourceSchema(t *testing.T) {
// t.Parallel()
ctx := context.Background()
schemaRequest := fwresource.SchemaRequest{}
schemaResponse := &fwresource.SchemaResponse{}
// Instantiate the resource.Resource and call its Schema method
postgresflexalphaInstance.NewInstanceResource().Schema(ctx, schemaRequest, schemaResponse)
if schemaResponse.Diagnostics.HasError() {
t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
}
// Validate the schema
diagnostics := schemaResponse.Schema.ValidateImplementation(ctx)
if diagnostics.HasError() {
t.Fatalf("Schema validation diagnostics: %+v", diagnostics)
}
}
func TestMain(m *testing.M) {
testutils.Setup()
code := m.Run()
// shutdown()
os.Exit(code)
}
func testAccPreCheck(t *testing.T) {
if _, ok := os.LookupEnv("TF_ACC_PROJECT_ID"); !ok {
t.Fatalf("could not find env var TF_ACC_PROJECT_ID")
}
}
type resData struct {
ServiceAccountFilePath string
ProjectID string
Region string
Name string
TfName string
FlavorID string
BackupSchedule string
UseEncryption bool
KekKeyID string
KekKeyRingID string
KekKeyVersion uint8
KekServiceAccount string
PerformanceClass string
Replicas uint32
Size uint32
ACLStrings []string
AccessScope string
RetentionDays uint32
Version string
Users []User
Databases []Database
DataSourceTest bool
}
type User struct {
Name string
ProjectID string
Roles []string
}
type Database struct {
Name string
ProjectID string
Owner string
}
func getExample() resData {
name := acctest.RandomWithPrefix("tf-acc")
return resData{
Region: os.Getenv("TF_ACC_REGION"),
ServiceAccountFilePath: os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE"),
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Name: name,
TfName: name,
FlavorID: singleFlavorID,
BackupSchedule: "0 0 * * *",
UseEncryption: false,
RetentionDays: 33,
Replicas: 1,
PerformanceClass: "premium-perf2-stackit",
Size: 10,
ACLStrings: []string{"0.0.0.0/0"},
AccessScope: "PUBLIC",
Version: "17",
}
}
func TestAccInstance(t *testing.T) {
exData := getExample()
exData.Version = "16"
updNameData := exData
updNameData.Name = "name-updated"
updSizeData := exData
updSizeData.Size = 25
updBackupSched := updSizeData
// api should complain about more than one daily backup
updBackupSched.BackupSchedule = "30 3 * * *"
updNetACL := updBackupSched
updNetACL.ACLStrings = append(updNetACL.ACLStrings, "192.168.0.0/24")
updVersion := updNetACL
updVersion.Version = "17"
testItemID := testutils.ResStr(pfx, "instance", exData.TfName)
compareValuesSame := statecheck.CompareValue(compare.ValuesSame())
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... %s - %s", t.Name(), exData.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
PreConfig: func() {
t.Logf("testing: %s - %s", t.Name(), "create and verify")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
exData,
),
ConfigStateChecks: []statecheck.StateCheck{
compareValuesSame.AddStateValue(
testItemID,
tfjsonpath.New("id"),
),
statecheck.ExpectKnownValue(
testItemID,
tfjsonpath.New("is_deletable"),
knownvalue.Bool(true),
),
statecheck.ExpectKnownValue(
testItemID,
tfjsonpath.New("connection_info"),
knownvalue.MapExact(map[string]knownvalue.Check{
"write": knownvalue.MapExact(map[string]knownvalue.Check{
"host": knownvalue.StringRegexp(regexp.MustCompile("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}.postgresql.[a-z0-9]+.onstackit.cloud")),
"port": knownvalue.Int32Func(func(v int32) error {
if v < 0 {
return fmt.Errorf("value is negative")
}
if v <= 1024 {
return fmt.Errorf("value uses protected port range")
}
return nil
}),
}),
}),
),
},
Check: defaultNoEncInstanceTestChecks(testItemID, exData),
},
// Second apply should not have changes
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "second apply")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
exData,
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectEmptyPlan(),
},
},
ConfigStateChecks: []statecheck.StateCheck{
compareValuesSame.AddStateValue(
testItemID,
tfjsonpath.New("id"),
),
statecheck.ExpectKnownValue(
testItemID,
tfjsonpath.New("is_deletable"),
knownvalue.Bool(true),
),
},
},
// Refresh state test
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "refresh state")
},
RefreshState: true,
},
// Update name and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "update name")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updNameData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testItemID,
"name",
updNameData.Name,
),
),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectNonEmptyPlan(),
},
},
},
// Update size and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "update storage.size")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updSizeData,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testItemID,
"storage.size",
strconv.Itoa(int(updSizeData.Size)),
),
// network should contain 4 sub entries
resource.TestCheckResourceAttr(testItemID, "network.acl.#", "1"),
),
},
// Update backup schedule
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "update backup schedule")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updBackupSched,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testItemID,
"backup_schedule",
updBackupSched.BackupSchedule,
),
// network should contain 4 sub entries
resource.TestCheckResourceAttr(testItemID, "network.acl.#", "1"),
),
},
// Update network ACL
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "update network.acl")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updNetACL,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testItemID,
"backup_schedule",
updBackupSched.BackupSchedule,
),
// network should contain 4 sub entries
resource.TestCheckResourceAttr(testItemID, "network.acl.#", "2"),
),
},
// Update version
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "update version")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
updVersion,
),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
testItemID,
"version",
updVersion.Version,
),
),
},
// Import test
// test instance imports
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "import instance")
},
ResourceName: testItemID,
// ImportStateIdPrefix: "",
// ImportStateVerifyIdentifierAttribute: "id",
ImportStateIdFunc: getInstanceTestID(exData.TfName),
ImportStateKind: resource.ImportCommandWithID,
ImportState: true,
ImportStateVerify: true,
},
},
},
)
}
func TestAccInstanceHA(t *testing.T) {
data := getExample()
data.FlavorID = replicasFlavorID
data.Replicas = 3
testItemID := testutils.ResStr(pfx, "instance", data.TfName)
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... %s - %s", t.Name(), data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "create and verify")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: defaultNoEncInstanceTestChecks(testItemID, data),
},
},
},
)
}
func TestAccInstanceWithUsers(t *testing.T) {
data := getExample()
userName := "testUser"
data.Users = []User{
{
Name: userName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
testItemID := testutils.ResStr(pfx, "instance", data.TfName)
// TODO : implement check multiple users
testUserItemID := testutils.ResStr(pfx, "user", userName)
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... %s - %s", t.Name(), data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "create and verify")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
defaultNoEncInstanceTestChecks(testItemID, data),
resource.TestCheckResourceAttr(testUserItemID, "name", userName),
resource.TestCheckResourceAttrSet(testUserItemID, "id"),
resource.TestCheckResourceAttr(testUserItemID, "roles.#", "1"),
),
},
},
},
)
}
func TestAccInstanceWithDatabases(t *testing.T) {
data := getExample()
dbName := "testdb"
userName := "testUser"
data.Users = []User{
{
Name: userName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
data.Databases = []Database{
{
Name: dbName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
data.DataSourceTest = true
testItemID := testutils.ResStr(pfx, "instance", data.TfName)
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... %s - %s", t.Name(), data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "create and verify")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
defaultNoEncInstanceTestChecks(testItemID, data),
// TODO - extract also to functions
resource.TestCheckResourceAttr(testutils.ResStr(pfx, "user", userName), "name", userName),
resource.TestCheckResourceAttrSet(testutils.ResStr(pfx, "user", userName), "id"),
resource.TestCheckResourceAttrPair(
testItemID, "project_id",
testutils.ResStr(pfx, "user", userName), "project_id",
),
resource.TestCheckResourceAttrPair(
testItemID, "instance_id",
testutils.ResStr(pfx, "user", userName), "instance_id",
),
// TODO - extract also to functions
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.TestCheckResourceAttrPair(
testItemID, "project_id",
testutils.ResStr(pfx, "database", dbName), "project_id",
),
resource.TestCheckResourceAttrPair(
testItemID, "instance_id",
testutils.ResStr(pfx, "database", dbName), "instance_id",
),
),
},
// data source
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "datasource")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance data
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "instance", data.TfName),
"project_id",
data.ProjectID,
),
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "instance", data.TfName),
"name",
data.Name,
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "instance", data.TfName), "project_id",
testutils.ResStr(pfx, "instance", data.TfName), "project_id",
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "database", dbName), "instance_id",
testutils.ResStr(pfx, "instance", data.TfName), "instance_id",
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "user", userName), "instance_id",
testutils.ResStr(pfx, "instance", data.TfName), "instance_id",
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "user", userName), "instance_id",
testutils.ResStr(pfx, "user", userName), "instance_id",
),
// User data
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "user", userName),
"project_id",
data.ProjectID,
),
resource.TestCheckResourceAttrSet(
testutils.ResStr(dataPfx, "user", userName),
"user_id",
),
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "user", userName),
"name",
data.Users[0].Name,
),
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "user", userName),
"roles.#",
"1",
),
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "user", userName),
"roles.0",
data.Users[0].Roles[0],
),
// Database data
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "database", dbName),
"project_id",
data.ProjectID,
),
resource.TestCheckResourceAttr(
testutils.ResStr(dataPfx, "database", dbName),
"name",
dbName,
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "database", dbName),
"instance_id",
testutils.ResStr(pfx, "database", dbName),
"instance_id",
),
resource.TestCheckResourceAttrPair(
testutils.ResStr(dataPfx, "database", dbName),
"owner",
testutils.ResStr(dataPfx, "user", userName),
"name",
),
),
},
// test instance imports
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "import instance")
},
ResourceName: testItemID,
// ImportStateIdPrefix: "",
ImportStateVerifyIdentifierAttribute: "id",
ImportStateIdFunc: getInstanceTestID(data.TfName),
ImportStateKind: resource.ImportCommandWithID,
ImportState: true,
ImportStateVerify: true,
},
// test database imports
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "import database")
},
ResourceName: testutils.ResStr(pfx, "database", dbName),
// ImportStateIdPrefix: "",
// ImportStateVerifyIdentifierAttribute: "id",
ImportStateIdFunc: getDatabaseTestID(dbName),
ImportStateKind: resource.ImportCommandWithID,
ImportState: true,
ImportStateVerify: true,
},
// test user imports
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "import user")
},
ResourceName: testutils.ResStr(pfx, "user", userName),
// ImportStateIdPrefix: "",
// ImportStateVerifyIdentifierAttribute: "id",
ImportStateIdFunc: getUserTestID(userName),
ImportStateKind: resource.ImportCommandWithID,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"password"},
},
},
},
)
}
func TestAccEncryptedInstanceWithDatabases(t *testing.T) {
encKekKeyID, ok := os.LookupEnv("TF_ACC_KEK_KEY_ID")
if !ok || encKekKeyID == "" {
t.Skip("env var TF_ACC_KEK_KEY_ID needed for encryption test")
}
encKekKeyRingID, ok := os.LookupEnv("TF_ACC_KEK_KEY_RING_ID")
if !ok || encKekKeyRingID == "" {
t.Skip("env var TF_ACC_KEK_KEY_RING_ID needed for encryption test")
}
encKekKeyVersion, ok := os.LookupEnv("TF_ACC_KEK_KEY_VERSION")
if !ok || encKekKeyVersion == "" {
t.Skip("env var TF_ACC_KEK_KEY_VERSION needed for encryption test")
}
encSvcAcc, ok := os.LookupEnv("TF_ACC_KEK_SERVICE_ACCOUNT")
if !ok || encSvcAcc == "" {
t.Skip("env var TF_ACC_KEK_SERVICE_ACCOUNT needed for encryption test")
}
data := getExample()
data.UseEncryption = true
data.KekKeyID = encKekKeyID
data.KekKeyRingID = encKekKeyRingID
data.KekServiceAccount = encSvcAcc
encKekKeyVersionInt, err := strconv.Atoi(encKekKeyVersion)
if err != nil {
t.Errorf("error converting string to int")
}
if encKekKeyVersionInt > math.MaxUint8 {
t.Errorf("value too large to convert to uint8")
}
data.KekKeyVersion = uint8(encKekKeyVersionInt) //nolint:gosec // handled above
dbName := "testdb"
userName := "testUser"
data.Users = []User{
{
Name: userName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Roles: []string{"login"},
},
}
data.Databases = []Database{
{
Name: dbName,
ProjectID: os.Getenv("TF_ACC_PROJECT_ID"),
Owner: userName,
},
}
testItemID := testutils.ResStr(pfx, "instance", data.TfName)
resource.ParallelTest(
t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
t.Logf(" ... %s - %s", t.Name(), data.TfName)
},
CheckDestroy: testAccCheckPostgresFlexDestroy,
ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
// Create and verify
{
PreConfig: func() {
t.Logf(" ... %s - %s", t.Name(), "create and verify")
},
Config: testutils.StringFromTemplateMust(
"testdata/instance_template.gompl",
data,
),
Check: resource.ComposeAggregateTestCheckFunc(
defaultEncInstanceTestChecks(testItemID, data),
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 testAccCheckPostgresFlexDestroy(s *terraform.State) error {
testutils.Setup()
pID, ok := os.LookupEnv("TF_ACC_PROJECT_ID")
if !ok {
log.Fatalln("unable to read TF_ACC_PROJECT_ID")
}
ctx := context.Background()
var client *v3alpha1api.APIClient
var err error
var region, projectID string
region = testutils.Region
if region == "" {
region = "eu01"
}
projectID = pID
if projectID == "" {
return fmt.Errorf("projectID could not be determined in destroy function")
}
apiClientConfigOptions := []config.ConfigurationOption{
config.WithServiceAccountKeyPath(os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE")),
config.WithRegion(region),
}
if testutils.PostgresFlexCustomEndpoint != "" {
apiClientConfigOptions = append(
apiClientConfigOptions,
config.WithEndpoint(testutils.PostgresFlexCustomEndpoint),
)
}
client, err = v3alpha1api.NewAPIClient(apiClientConfigOptions...)
if err != nil {
log.Fatalln(err)
}
instancesToDestroy := []string{}
for _, rs := range s.RootModule().Resources {
if rs.Type != "stackitprivatepreview_postgresflexalpha_instance" &&
rs.Type != "stackitprivatepreview_postgresflexbeta_instance" {
continue
}
// instance terraform ID: = "[project_id],[region],[instance_id]"
instanceID := strings.Split(rs.Primary.ID, core.Separator)[2]
instancesToDestroy = append(instancesToDestroy, instanceID)
}
instancesResp, err := client.DefaultAPI.ListInstancesRequest(ctx, projectID, region).
Size(100).
Execute()
if err != nil {
return fmt.Errorf("getting instancesResp: %w", err)
}
items := instancesResp.GetInstances()
for i := range items {
if items[i].Id == "" {
continue
}
if utils.Contains(instancesToDestroy, items[i].Id) {
err := client.DefaultAPI.DeleteInstanceRequest(ctx, testutils.ProjectId, region, items[i].Id).Execute()
if err != nil {
return fmt.Errorf("deleting instance %s during CheckDestroy: %w", items[i].Id, err)
}
err = postgresflexalpha.DeleteInstanceWaitHandler(
ctx,
client.DefaultAPI,
testutils.ProjectId,
testutils.Region,
items[i].Id,
15*time.Minute,
10*time.Second,
)
if err != nil {
return fmt.Errorf("deleting instance %s during CheckDestroy: waiting for deletion %w", items[i].Id, err)
}
}
}
return nil
}
func defaultNoEncInstanceTestChecks(testItemID string, data resData) resource.TestCheckFunc {
return resource.ComposeAggregateTestCheckFunc(
defaultInstanceTestChecks(testItemID, data),
// check absent attr
resource.TestCheckNoResourceAttr(testItemID, "encryption"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_id"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_ring_id"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.kek_key_version"),
resource.TestCheckNoResourceAttr(testItemID, "encryption.service_account"),
)
}
func defaultEncInstanceTestChecks(testItemID string, data resData) resource.TestCheckFunc {
return resource.ComposeAggregateTestCheckFunc(
defaultInstanceTestChecks(testItemID, data),
// check absent attr
resource.TestCheckResourceAttr(testItemID, "encryption.%", "4"),
resource.TestCheckResourceAttrSet(testItemID, "encryption.kek_key_id"),
resource.TestCheckResourceAttr(testItemID, "encryption.kek_key_id", data.KekKeyID),
resource.TestCheckResourceAttrSet(testItemID, "encryption.kek_key_ring_id"),
resource.TestCheckResourceAttr(testItemID, "encryption.kek_key_ring_id", data.KekKeyRingID),
resource.TestCheckResourceAttrSet(testItemID, "encryption.kek_key_version"),
resource.TestCheckResourceAttr(testItemID, "encryption.kek_key_version", strconv.Itoa(int(data.KekKeyVersion))),
resource.TestCheckResourceAttrSet(testItemID, "encryption.service_account"),
resource.TestCheckResourceAttr(testItemID, "encryption.service_account", data.KekServiceAccount),
)
}
func defaultInstanceTestChecks(testItemID string, data resData) resource.TestCheckFunc {
// if AccessScope == SNA these are set
if data.AccessScope == "SNA" {
return resource.ComposeAggregateTestCheckFunc(
basicInstanceTestChecks(testItemID, data),
resource.TestCheckResourceAttrSet(testItemID, "network.instance_address"),
resource.TestCheckResourceAttrSet(testItemID, "network.router_address"),
)
}
// if AccessScope == PUBLIC these are empty - but they are set
return resource.ComposeAggregateTestCheckFunc(
basicInstanceTestChecks(testItemID, data),
resource.TestCheckResourceAttr(testItemID, "network.instance_address", ""),
resource.TestCheckResourceAttr(testItemID, "network.router_address", ""),
)
}
func basicInstanceTestChecks(testItemID string, data resData) resource.TestCheckFunc {
return resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(testItemID, "backup_schedule"),
resource.TestCheckResourceAttr(testItemID, "backup_schedule", data.BackupSchedule),
resource.TestCheckResourceAttr(testItemID, "connection_info.%", "1"),
resource.TestCheckResourceAttr(testItemID, "connection_info.write.%", "2"),
resource.TestCheckResourceAttrSet(testItemID, "connection_info.write.host"),
resource.TestCheckResourceAttrSet(testItemID, "connection_info.write.port"),
resource.TestCheckResourceAttrSet(testItemID, "flavor_id"),
resource.TestCheckResourceAttr(testItemID, "flavor_id", data.FlavorID),
resource.TestCheckResourceAttrSet(testItemID, "id"),
resource.TestCheckResourceAttrSet(testItemID, "instance_id"),
resource.TestCheckResourceAttrSet(testItemID, "is_deletable"),
resource.TestCheckResourceAttr(testItemID, "is_deletable", "true"),
resource.TestCheckResourceAttrSet(testItemID, "name"),
resource.TestCheckResourceAttr(testItemID, "name", data.Name),
// network params check
resource.TestCheckResourceAttr(testItemID, "network.%", "4"),
resource.TestCheckResourceAttrSet(testItemID, "network.access_scope"),
resource.TestCheckResourceAttr(testItemID, "network.access_scope", data.AccessScope),
// resource.TestCheckResourceAttrSet(testItemID, "network.acl"),
resource.TestCheckResourceAttr(testItemID, "network.acl.#", strconv.Itoa(len(data.ACLStrings))),
// instance_address and router_address are only checked in enc
resource.TestCheckResourceAttrSet(testItemID, "project_id"),
resource.TestCheckResourceAttr(testItemID, "project_id", data.ProjectID),
resource.TestCheckResourceAttrSet(testItemID, "region"),
resource.TestCheckResourceAttr(testItemID, "region", data.Region),
resource.TestCheckResourceAttrSet(testItemID, "replicas"),
resource.TestCheckResourceAttr(testItemID, "replicas", strconv.Itoa(int(data.Replicas))),
resource.TestCheckResourceAttrSet(testItemID, "retention_days"),
resource.TestCheckResourceAttr(testItemID, "retention_days", strconv.Itoa(int(data.RetentionDays))),
resource.TestCheckResourceAttrSet(testItemID, "status"),
resource.TestCheckResourceAttr(testItemID, "status", "READY"),
// storage params check
resource.TestCheckResourceAttr(testItemID, "storage.%", "2"),
resource.TestCheckResourceAttrSet(testItemID, "storage.performance_class"),
resource.TestCheckResourceAttr(testItemID, "storage.performance_class", data.PerformanceClass),
resource.TestCheckResourceAttrSet(testItemID, "storage.size"),
resource.TestCheckResourceAttr(testItemID, "storage.size", strconv.Itoa(int(data.Size))),
resource.TestCheckResourceAttrSet(testItemID, "version"),
resource.TestCheckResourceAttr(testItemID, "version", data.Version),
)
}
func getInstanceTestID(name string) func(s *terraform.State) (string, error) {
return func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources[testutils.ResStr(pfx, "instance", name)]
if !ok {
return "", fmt.Errorf("couldn't find resource stackitprivatepreview_postgresflexalpha_instance.%s", name)
}
projectID, ok := r.Primary.Attributes["project_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute project_id")
}
region, ok := r.Primary.Attributes["region"]
if !ok {
return "", fmt.Errorf("couldn't find attribute region")
}
instanceID, ok := r.Primary.Attributes["instance_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute instance_id")
}
return fmt.Sprintf("%s,%s,%s", projectID, region, instanceID), nil
}
}
func getDatabaseTestID(name string) func(s *terraform.State) (string, error) {
return func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources[testutils.ResStr(pfx, "database", name)]
if !ok {
return "", fmt.Errorf("couldn't find resource stackitprivatepreview_postgresflexalpha_instance.%s", name)
}
projectID, ok := r.Primary.Attributes["project_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute project_id")
}
region, ok := r.Primary.Attributes["region"]
if !ok {
return "", fmt.Errorf("couldn't find attribute region")
}
instanceID, ok := r.Primary.Attributes["instance_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute instance_id")
}
databaseID, ok := r.Primary.Attributes["database_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute database_id")
}
return fmt.Sprintf("%s,%s,%s,%s", projectID, region, instanceID, databaseID), nil
}
}
func getUserTestID(name string) func(s *terraform.State) (string, error) {
return func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources[testutils.ResStr(pfx, "user", name)]
if !ok {
return "", fmt.Errorf("couldn't find resource stackitprivatepreview_postgresflexalpha_instance.%s", name)
}
projectID, ok := r.Primary.Attributes["project_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute project_id")
}
region, ok := r.Primary.Attributes["region"]
if !ok {
return "", fmt.Errorf("couldn't find attribute region")
}
instanceID, ok := r.Primary.Attributes["instance_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute instance_id")
}
userID, ok := r.Primary.Attributes["user_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute user_id")
}
return fmt.Sprintf("%s,%s,%s,%s", projectID, region, instanceID, userID), nil
}
}