blob: 903c9ee63e9c1bcf547608b230eafe7127a8ba72 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package sql_test
import (
"errors"
"fmt"
"strconv"
"testing"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest"
)
func TestAccDataSourceSqlDatabases_basic(t *testing.T) {
t.Parallel()
context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}
acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccSqlDatabaseDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceSqlDatabases_basic(context),
Check: resource.ComposeTestCheckFunc(
checkDatabasesListDataSourceStateMatchesResourceStateWithIgnores(
"data.google_sql_databases.qa",
"google_sql_database.db1",
"google_sql_database.db2",
map[string]struct{}{
"deletion_policy": {},
"id": {},
},
),
),
},
},
})
}
func testAccDataSourceSqlDatabases_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_sql_database_instance" "main" {
name = "tf-test-instance-%{random_suffix}"
database_version = "POSTGRES_14"
region = "us-central1"
settings {
tier = "db-f1-micro"
}
deletion_protection = false
}
resource "google_sql_database" "db1"{
instance = google_sql_database_instance.main.name
name = "pg-db1"
}
resource "google_sql_database" "db2"{
instance = google_sql_database_instance.main.name
name = "pg-db2"
}
data "google_sql_databases" "qa" {
instance = google_sql_database_instance.main.name
depends_on = [
google_sql_database.db1,
google_sql_database.db2
]
}
`, context)
}
// This function checks data source state matches for resorceName database instance state
func checkDatabasesListDataSourceStateMatchesResourceStateWithIgnores(dataSourceName, resourceName, resourceName2 string, ignoreFields map[string]struct{}) func(*terraform.State) error {
return func(s *terraform.State) error {
ds, ok := s.RootModule().Resources[dataSourceName]
if !ok {
return fmt.Errorf("can't find %s in state", dataSourceName)
}
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("can't find %s in state", resourceName)
}
rs2, ok := s.RootModule().Resources[resourceName2]
if !ok {
return fmt.Errorf("can't find %s in state", resourceName2)
}
dsAttr := ds.Primary.Attributes
rsAttr := rs.Primary.Attributes
rsAttr2 := rs2.Primary.Attributes
err := checkDatabaseFieldsMatchForDataSourceStateAndResourceState(dsAttr, rsAttr, ignoreFields)
if err != nil {
return err
}
err = checkDatabaseFieldsMatchForDataSourceStateAndResourceState(dsAttr, rsAttr2, ignoreFields)
return err
}
}
// This function checks whether all the attributes of the database instance resource and the attributes of the datbase instance inside the data source list are the same
func checkDatabaseFieldsMatchForDataSourceStateAndResourceState(dsAttr, rsAttr map[string]string, ignoreFields map[string]struct{}) error {
totalInstances, err := strconv.Atoi(dsAttr["databases.#"])
if err != nil {
return errors.New("Couldn't convert length of instances list to integer")
}
index := "-1"
for i := 0; i < totalInstances; i++ {
if dsAttr["databases."+strconv.Itoa(i)+".name"] == rsAttr["name"] {
index = strconv.Itoa(i)
}
}
if index == "-1" {
return errors.New("The newly created instance is not found in the data source")
}
errMsg := ""
// Data sources are often derived from resources, so iterate over the resource fields to
// make sure all fields are accounted for in the data source.
// If a field exists in the data source but not in the resource, its expected value should
// be checked separately.
for k := range rsAttr {
if _, ok := ignoreFields[k]; ok {
continue
}
if k == "%" {
continue
}
if dsAttr["databases."+index+"."+k] != rsAttr[k] {
// ignore data sources where an empty list is being compared against a null list.
if k[len(k)-1:] == "#" && (dsAttr["databases."+index+"."+k] == "" || dsAttr["databases."+index+"."+k] == "0") && (rsAttr[k] == "" || rsAttr[k] == "0") {
continue
}
errMsg += fmt.Sprintf("%s is %s; want %s\n", k, dsAttr["databases."+index+"."+k], rsAttr[k])
}
}
if errMsg != "" {
return errors.New(errMsg)
}
return nil
}