Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dialect to spanner database #5799

Merged
merged 9 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions mmv1/products/spanner/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,14 @@ objects:
description: |
Fully qualified name of the KMS key to use to encrypt this database. This key must exist
in the same location as the Spanner Database.
- !ruby/object:Api::Type::Enum
name: 'databaseDialect'
description: |
The dialect of the Cloud Spanner Database.
If it is not provided, "GOOGLE_STANDARD_SQL" will be used.
Note: Databases that are created with POSTGRESQL dialect do not support
extra DDL statements in the `CreateDatabase` call. You must therefore re-apply
terraform with ddl on the same database after creation.
values:
- :GOOGLE_STANDARD_SQL
- :POSTGRESQL
7 changes: 7 additions & 0 deletions mmv1/products/spanner/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ overrides: !ruby/object:Overrides::ResourceOverrides
On older versions, it is strongly recommended to set `lifecycle { prevent_destroy = true }`
on databases in order to prevent accidental data loss. See [Terraform docs](https://www.terraform.io/docs/configuration/resources.html#prevent_destroy)
for more information on lifecycle parameters.

Note: Databases that are created with POSTGRESQL dialect do not support
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is gonna be a pretty bad experience for Terraform users as it's a strong expectation in the ecosystem that a single terraform apply will finish setting up your infrastructure in one go. It's your team's API, though, and if this is the UX you want we'll accept it. I will note, our team will not amend this ourselves if that's the chosen path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the known limitation for now that DDL statements are not part of create database call.
cc: @aseering

extra DDL statements in the `CreateDatabase` call. You must therefore re-apply
terraform with ddl on the same database after creation.

examples:
- !ruby/object:Provider::Terraform::Examples
name: "spanner_database_basic"
Expand Down Expand Up @@ -58,6 +63,8 @@ overrides: !ruby/object:Overrides::ResourceOverrides
ignore_read: true
state: !ruby/object:Overrides::Terraform::PropertyOverride
exclude: false
databaseDialect: !ruby/object:Overrides::Terraform::PropertyOverride
default_from_api: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
constants: 'templates/terraform/constants/spanner_database.go.erb'
encoder: templates/terraform/encoders/spanner_database.go.erb
Expand Down
3 changes: 3 additions & 0 deletions mmv1/templates/terraform/encoders/spanner_database.go.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
obj["createStatement"] = fmt.Sprintf("CREATE DATABASE `%s`", obj["name"])
if dialect, ok := obj["databaseDialect"]; ok && dialect == "POSTGRESQL" {
obj["createStatement"] = fmt.Sprintf("CREATE DATABASE %s", obj["name"])
}
delete(obj, "name")
delete(obj, "instance")
return obj, nil
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,90 @@ resource "google_spanner_database" "basic" {
`, instanceName, instanceName, databaseName)
}

func TestAccSpannerDatabase_postgres(t *testing.T) {
t.Parallel()

rnd := randString(t, 10)
instanceName := fmt.Sprintf("tf-test-%s", rnd)
databaseName := fmt.Sprintf("tfgen_%s", rnd)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSpannerDatabaseDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccSpannerDatabase_postgres(instanceName, databaseName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("google_spanner_database.basic_spangres", "state"),
),
},
{
// Test import with default Terraform ID
ResourceName: "google_spanner_database.basic_spangres",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ddl", "deletion_protection"},
},
{
Config: testAccSpannerDatabase_postgresUpdate(instanceName, databaseName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("google_spanner_database.basic_spangres", "state"),
),
},
{
// Test import with default Terraform ID
ResourceName: "google_spanner_database.basic_spangres",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ddl", "deletion_protection"},
},
},
})
}

func testAccSpannerDatabase_postgres(instanceName, databaseName string) string {
return fmt.Sprintf(`
resource "google_spanner_instance" "basic" {
name = "%s"
config = "regional-us-central1"
display_name = "%s-display"
num_nodes = 1
}

resource "google_spanner_database" "basic_spangres" {
instance = google_spanner_instance.basic.name
name = "%s_spangres"
database_dialect = "POSTGRESQL"
deletion_protection = false
}
`, instanceName, instanceName, databaseName)
}

func testAccSpannerDatabase_postgresUpdate(instanceName, databaseName string) string {
return fmt.Sprintf(`
resource "google_spanner_instance" "basic" {
name = "%s"
config = "regional-us-central1"
display_name = "%s-display"
num_nodes = 1
}

resource "google_spanner_database" "basic_spangres" {
instance = google_spanner_instance.basic.name
name = "%s_spangres"
database_dialect = "POSTGRESQL"
ddl = [
"CREATE TABLE t1 (t1 bigint NOT NULL PRIMARY KEY)",
"CREATE TABLE t2 (t2 bigint NOT NULL PRIMARY KEY)",
"CREATE TABLE t3 (t3 bigint NOT NULL PRIMARY KEY)",
"CREATE TABLE t4 (t4 bigint NOT NULL PRIMARY KEY)",
]
deletion_protection = false
}
`, instanceName, instanceName, databaseName)
}

// Unit Tests for type spannerDatabaseId
func TestDatabaseNameForApi(t *testing.T) {
id := spannerDatabaseId{
Expand Down Expand Up @@ -350,4 +434,4 @@ resource "google_project_service_identity" "ck_sa" {

`, context)
}
<% end -%>
<% end -%>