package sqlserverflexbeta_test import ( "context" _ "embed" "errors" "fmt" "log" "net/http" "os" "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/oapierror" "github.com/stackitcloud/stackit-sdk-go/core/utils" "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core" wait "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/wait/sqlserverflexbeta" "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api" "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/internal/testutils" sqlserverflexbeta "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/instance" // 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_sqlserverflexbeta" 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 sqlserverflexbeta.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 UseFlavorId bool FlavorCpu int FlavorRam int Replicas int KekKeyID string KekKeyRingID string KekKeyVersion uint8 KekServiceAccount string PerformanceClass string Size uint32 ACLStrings []string AccessScope string RetentionDays uint32 Version string Users []User Databases []Database } type User struct { Name string ProjectID string Roles []string } type Database struct { Name string ProjectID string Owner string Collation string Compatibility 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: "4.16-Single", BackupSchedule: "0 0 * * *", UseEncryption: false, RetentionDays: 33, PerformanceClass: "premium-perf2-stackit", Size: 10, ACLStrings: []string{"0.0.0.0/0"}, AccessScope: "PUBLIC", Version: "2022", UseFlavorId: true, } } func TestAccInstance(t *testing.T) { exData := getExample() updNameData := exData updNameData.Name = "name-updated" updSizeData := exData updSizeData.Size = 25 testInstanceID := 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: testAccCheckSQLServerFlexDestroy, ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, Steps: []resource.TestStep{ // Create and verify { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "create and verify") }, // empty refresh plan ExpectNonEmptyPlan: false, Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", exData, ), ConfigStateChecks: []statecheck.StateCheck{ compareValuesSame.AddStateValue( testInstanceID, tfjsonpath.New("id"), ), statecheck.ExpectKnownValue( testInstanceID, tfjsonpath.New("is_deletable"), knownvalue.Bool(true), ), }, Check: defaultNoEncInstanceTestChecks(testInstanceID, exData), }, // Update name and verify { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "update name and verify") }, ExpectNonEmptyPlan: false, Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", updNameData, ), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectNonEmptyPlan(), }, }, Check: resource.ComposeTestCheckFunc( defaultNoEncInstanceTestChecks(testInstanceID, updNameData), ), }, // Expect empty plan after update { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "expect empty plan") }, ExpectNonEmptyPlan: false, Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", updNameData, ), }, // Update size and verify { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "update storage.size and verify") }, ExpectNonEmptyPlan: false, Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", updSizeData, ), Check: resource.ComposeTestCheckFunc( defaultNoEncInstanceTestChecks(testInstanceID, updSizeData), ), }, // Import test // test instance imports { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "import instance") }, ResourceName: testInstanceID, // ImportStateIdPrefix: "", // ImportStateVerifyIdentifierAttribute: "id", ImportStateIdFunc: getInstanceTestID(exData.TfName), ImportStateKind: resource.ImportCommandWithID, ImportState: true, ImportStateVerify: true, }, }, }) } func TestAccInstanceReApply(t *testing.T) { exData := getExample() testInstanceID := 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: testAccCheckSQLServerFlexDestroy, 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( testInstanceID, tfjsonpath.New("id"), ), statecheck.ExpectKnownValue( testInstanceID, tfjsonpath.New("is_deletable"), knownvalue.Bool(true), ), }, Check: defaultNoEncInstanceTestChecks(testInstanceID, exData), }, // Second apply should not have changes { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "second apply") }, ExpectNonEmptyPlan: false, ResourceName: testInstanceID, Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", exData, ), ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectEmptyPlan(), }, }, ConfigStateChecks: []statecheck.StateCheck{ compareValuesSame.AddStateValue( testInstanceID, tfjsonpath.New("id"), ), statecheck.ExpectKnownValue( testInstanceID, tfjsonpath.New("is_deletable"), knownvalue.Bool(true), ), }, }, // Refresh state test { PreConfig: func() { t.Logf("testing: %s - %s", t.Name(), "refresh state") }, RefreshState: true, }, }, }) } func TestAccInstanceNoEncryption(t *testing.T) { data := getExample() dbName := "testDb" userName := "testUser" data.Users = []User{ { Name: userName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Roles: []string{ "##STACKIT_DatabaseManager##", "##STACKIT_LoginManager##", "##STACKIT_ProcessManager##", "##STACKIT_SQLAgentManager##", "##STACKIT_SQLAgentUser##", "##STACKIT_ServerManager##", }, }, } data.Databases = []Database{ { Name: dbName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Owner: userName, }, } testInstanceID := testutils.ResStr(pfx, "instance", data.TfName) testDatabaseID := testutils.ResStr(pfx, "database", dbName) testUserID := testutils.ResStr(pfx, "user", userName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) t.Logf(" ... %s - %s", t.Name(), data.TfName) }, CheckDestroy: testAccCheckSQLServerFlexDestroy, ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, Steps: []resource.TestStep{ // Create and verify { Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", data, ), Check: resource.ComposeAggregateTestCheckFunc( defaultNoEncInstanceTestChecks(testInstanceID, data), // check user values are correct resource.TestCheckResourceAttr(testUserID, "username", userName), resource.TestCheckResourceAttr(testUserID, "roles.#", strconv.Itoa(len(data.Users[0].Roles))), // check database values are set resource.TestCheckResourceAttrSet(testDatabaseID, "id"), resource.TestCheckResourceAttrSet(testDatabaseID, "name"), resource.TestCheckResourceAttrSet(testDatabaseID, "owner"), resource.TestCheckResourceAttrSet(testDatabaseID, "compatibility"), resource.TestCheckResourceAttrSet(testDatabaseID, "collation"), // check database values are correct resource.TestCheckResourceAttr(testDatabaseID, "name", dbName), resource.TestCheckResourceAttr(testDatabaseID, "owner", userName), ), }, }, }) } func TestAccInstanceNoEncryptionWithFlavorObject(t *testing.T) { data := getExample() data.UseFlavorId = false data.FlavorID = "" data.FlavorCpu = 4 data.FlavorRam = 16 data.Replicas = 1 dbName := "testDb" userName := "testUser" data.Users = []User{ { Name: userName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Roles: []string{ "##STACKIT_DatabaseManager##", "##STACKIT_LoginManager##", "##STACKIT_ProcessManager##", "##STACKIT_SQLAgentManager##", "##STACKIT_SQLAgentUser##", "##STACKIT_ServerManager##", }, }, } data.Databases = []Database{ { Name: dbName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Owner: userName, }, } testInstanceID := testutils.ResStr(pfx, "instance", data.TfName) testDatabaseID := testutils.ResStr(pfx, "database", dbName) testUserID := testutils.ResStr(pfx, "user", userName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) t.Logf(" ... %s - %s", t.Name(), data.TfName) }, CheckDestroy: testAccCheckSQLServerFlexDestroy, ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, Steps: []resource.TestStep{ // Create and verify { Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", data, ), Check: resource.ComposeAggregateTestCheckFunc( defaultNoEncInstanceTestChecks(testInstanceID, data), // check user values are correct resource.TestCheckResourceAttr(testUserID, "username", userName), resource.TestCheckResourceAttr(testUserID, "roles.#", strconv.Itoa(len(data.Users[0].Roles))), // check database values are set resource.TestCheckResourceAttrSet(testDatabaseID, "id"), resource.TestCheckResourceAttrSet(testDatabaseID, "name"), resource.TestCheckResourceAttrSet(testDatabaseID, "owner"), resource.TestCheckResourceAttrSet(testDatabaseID, "compatibility"), resource.TestCheckResourceAttrSet(testDatabaseID, "collation"), // check database values are correct resource.TestCheckResourceAttr(testDatabaseID, "name", dbName), resource.TestCheckResourceAttr(testDatabaseID, "owner", userName), ), }, }, }) } func TestAccInstanceEncryption(t *testing.T) { data := getExample() dbName := "testDb" userName := "testUser" data.Users = []User{ { Name: userName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Roles: []string{"##STACKIT_DatabaseManager##", "##STACKIT_LoginManager##"}, }, } data.Databases = []Database{ { Name: dbName, ProjectID: os.Getenv("TF_ACC_PROJECT_ID"), Owner: userName, }, } data.UseEncryption = true data.KekKeyID = "fe039bcf-8d7b-431a-801d-9e81371a6b7b" data.KekKeyRingID = "6a2d95ab-3c4c-4963-a2bb-08d17a320e27" data.KekKeyVersion = 1 data.KekServiceAccount = "henselinm-u2v3ex1@sa.stackit.cloud" testInstanceID := testutils.ResStr(pfx, "instance", data.TfName) testDatabaseID := testutils.ResStr(pfx, "database", dbName) testUserID := testutils.ResStr(pfx, "user", userName) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) t.Logf(" ... %s - %s", t.Name(), data.TfName) }, CheckDestroy: testAccCheckSQLServerFlexDestroy, ProtoV6ProviderFactories: testutils.TestAccProtoV6ProviderFactories, Steps: []resource.TestStep{ // Create and verify { Config: testutils.StringFromTemplateMust( "testdata/instance_template.gompl", data, ), Check: resource.ComposeAggregateTestCheckFunc( defaultEncInstanceTestChecks(testInstanceID, data), // check user values are set resource.TestCheckResourceAttrSet(testUserID, "id"), resource.TestCheckResourceAttrSet(testUserID, "username"), // func(s *terraform.State) error { // return nil // }, // check user values are correct resource.TestCheckResourceAttr(testUserID, "username", userName), resource.TestCheckResourceAttr(testUserID, "roles.#", "2"), // check database values are set resource.TestCheckResourceAttrSet(testDatabaseID, "id"), resource.TestCheckResourceAttrSet(testDatabaseID, "name"), resource.TestCheckResourceAttrSet(testDatabaseID, "owner"), resource.TestCheckResourceAttrSet(testDatabaseID, "compatibility"), resource.TestCheckResourceAttrSet(testDatabaseID, "collation"), // check database values are correct resource.TestCheckResourceAttr(testDatabaseID, "name", dbName), resource.TestCheckResourceAttr(testDatabaseID, "owner", userName), ), }, }, }) } 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.TestCheckResourceAttrSet(testItemID, "flavor_id"), resource.TestCheckResourceAttr(testItemID, "flavor_id", data.FlavorID), resource.TestCheckResourceAttrSet(testItemID, "id"), resource.TestCheckResourceAttrSet(testItemID, "instance_id"), resource.TestCheckResourceAttrSet(testItemID, "edition"), 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, "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.class"), resource.TestCheckResourceAttr(testItemID, "storage.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 } } */ func testAccCheckSQLServerFlexDestroy(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 *v3beta1api.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 = v3beta1api.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, projectID, region, items[i].Id).Execute() if err != nil { return fmt.Errorf("deleting instance %s during CheckDestroy: %w", items[i].Id, err) } w := wait.DeleteInstanceWaitHandler( ctx, client.DefaultAPI, testutils.ProjectId, testutils.Region, items[i].Id, ) _, waitErr := w.SetTimeout(90 * time.Second).WaitWithContext(context.Background()) if waitErr != nil { var oapiErr *oapierror.GenericOpenAPIError isOapiErr := errors.As(waitErr, &oapiErr) if !isOapiErr { return fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError") } if oapiErr.StatusCode != http.StatusNotFound { return waitErr } } } } return nil }