diff --git a/.terraform-version b/.terraform-version index e25d8d9..88c5fb8 100644 --- a/.terraform-version +++ b/.terraform-version @@ -1 +1 @@ -1.1.5 +1.4.0 diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index 71c2182..c361878 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -2,39 +2,47 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/google" { - version = "4.9.0" - constraints = ">= 3.70.0" + version = "4.56.0" + constraints = ">= 4.56.0" hashes = [ - "h1:jXDs/S5zmRBl+dNDWIndVy/47ReLDEqOAHPbXOlhEMo=", - "zh:10887917815293d6ad26cc3784c766de4dfa2fa6b2c8b994de4f4b7b3bc31653", - "zh:343037e5ec514ac02bfacc200acb648861b04ee9024bed5bf72d13583d10783d", - "zh:40eaf3e06e44e2278ba64fc161e96b1bd05508f599ce12e1f094a924839d34a6", - "zh:5178f1043fa24a38602833aed72db5023f4183833e1fdb78bb1584a05ff53030", - "zh:616889b78ee00ee69d749f7848d63246de200f17efeebfaaf28dbe3f49ec6362", - "zh:695f6de8659d17f65a3317b9810cdc1c12738648b1b87dcf7eca90ebc019d889", - "zh:6e98efe69bff66120cfd0911eea4d20f7b17c62eed909e12098e46efb8f86e5a", - "zh:78f6615113f8fd0fb28f7b58102c55db42e7251463650e0410ec2d6f8877141c", - "zh:8a2f45c2f7e4c4077b720d6b98d5ee26347e97b6d2ee12489cca14d42fef2f36", - "zh:db1a462b72047342d5b35587953a3db30a4af248100e1db9eddc0ebb4b7c9a07", - "zh:fa64449c0efa1340077c860003059762e735b4d2a376d9ece90c174ad8d238c0", + "h1:4imu4dyDf1a38ZmbCesKSVt17hSwoT0GxFUbmFpguag=", + "h1:AdHrCF1qGCHKw0ufyoKZfmhblGh2tvop/E1iHgqcJCI=", + "h1:pztPDTMJS6lVSA40QjsAReXpkqY+JTuCRsVWZYVWUwY=", + "h1:u8Za5GMFOP/ppSrPVUd/fNldtIrfGlOZ87I/kf8qUyk=", + "zh:048cb773c8bf12cde5c5d68c0e8f649ccc12aaadd9347b7dfebc05f8d34ee93e", + "zh:29e75cdeb7dee16e4aa894ce04f493c467595fd5dcd393a14892c50b3b5d14d1", + "zh:3263a8fd040806005695534d4ec6c4d6a0bfc16d23e215196c81fd13eb85b1c5", + "zh:3cd0f16051929005494a2fa0b49e1092c542a73a11c47507ab29ab216a3828cf", + "zh:48ba3b1a1de0b01b00a4566019123d8547f43248572f869b526dc19f9725d798", + "zh:7c81ec67c6790eab69cdbccd5ff403f7e8123db5ae672656e69f94ee90ddc2e7", + "zh:908a59489aba855f386cf4f0fa8a2fa0b3c0dea44225994dfdf1ad69b3127b36", + "zh:da5d8c3300e9f8010c52e527fc7690d8541c4601fecc62f14b12a41e8cfb8962", + "zh:e689d4438009de0124eb35635ffa9d141f3549e7bf7c1cc69435cfa21aa7ea64", + "zh:f4299cd782acfcd17758635330dd05be78a78dd8af611bce3960fb9925b83c3d", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:fb33c4a59ca00762838d8e0718300d16e2ca749eeeb17c51eef52a1267649313", ] } provider "registry.terraform.io/hashicorp/tfe" { - version = "0.28.1" - constraints = ">= 0.25.0" + version = "0.42.0" + constraints = ">= 0.42.0" hashes = [ - "h1:PgumMb80c9XrmvGUES/B3jq7lUkT+b3Oxf1SC+3Ieg0=", - "zh:2c3f6ead7ff5111d2a7747a1167732a7caf6ed1a31e1d15046b54b2f3921aa6f", - "zh:3044820f0bfb5207a87554c7fdf71f3ef08d0dd0c47be1ff855ce3c02f1cf54a", - "zh:328896547cc04fc50df76b5980147e758947a56d498246884ede1fed5f4f6f81", - "zh:3cbe144ecfdf37fd965728ba18b42d0fca8d582d3c367d4f5f06d244271878c7", - "zh:785ec32ab9ede8895e99b8388eaebc13f56f2d14ce94ba2ac5a8b4c265a10432", - "zh:7b64f051f8d49b05746c9108375e7c9298dea5407b06223ed485301b7a608b01", - "zh:a714c4d45bf5a7436feb0376c03e894430553f94bd2bcdc3b9e86486c8b393b8", - "zh:b978c565712f3de3b19989b8a00085bb71325030007ebc69fa9c180d68a135f5", - "zh:eddc6920e530dc17fdb4a1f221215bd612d956322aeabca75bcb9f28294a5e07", - "zh:fc6fb285f116f4110e339a7bd8c4e3a99292db0efbd3aacb7c6c27cf69f3052c", - "zh:fe584a4edb9c3518a520c92cf5cc37fe58d28e469b650de7be3e6bd3be921ff1", + "h1:0UzD5hSvQwxqHF95GnRomK/RLDsfFMFZNMnYhy/v1L0=", + "h1:8tJPGfmoGsb0eYl6DA0rNQO27CPZ2AfB1fC9pXbyiTA=", + "h1:Cjr9qAdG3MQ2LCn4ahyjcvj77NNRgCD2V5AGrwZKIdg=", + "h1:UxD4cC+sqKDOS/8/ho/RhWGkgVEj3G5ct9EoZ14yvDY=", + "zh:0e06ad824ee82a6fdccf35a31558daefa289309b8b95c2795a8c7459126260dc", + "zh:3d5b868aa4f542783fbcdcfdeef504b5c57c2f3029d2d01ebab3edb72c55ec9e", + "zh:4c7fc474354ad83a5f86ae76975c173c936b1173098babf130e9f1ecba082a20", + "zh:5badc509eeec6e519026b290aa13d1cb33f544668c3db3264b449e7163cdd12c", + "zh:7799e46fdeaef52eca86ce08a08fc7871c6c3ab4ce191798c155c560d4fe1a98", + "zh:77a96c58c73fa1b96c3e82784b3a7b1eb1cb8837d422f53750339938ecbfdeb7", + "zh:a1def78f9ce1cf2125c46aad06fca91f863758831e5250fcca5d151864ddb527", + "zh:d13765f743cdd054383eae193fbe4b5f768778529e00fa95619b4a0f1e14917a", + "zh:d462082a2b702a38caaf68fd6bb9dcea3cd7a804f8270d6fac891ce23a216cdc", + "zh:d95ec293fa70e946b6cd657912b33155f8be3413e6128ed2bfa5a493f788e439", + "zh:f30c96b0188b4061fb1f3a1fdb4805356e9ce2218172091d2b336c6f4cb7af93", + "zh:faeacff1ec88e5882725e589e14ef4c78b70a176ac17ad5912e35727a37ab519", ] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9d47f67..fcd2f52 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,6 @@ { "recommendations": [ + "hashicorp.hcl", "hashicorp.terraform", ] } diff --git a/README.md b/README.md index cdd3173..09a752c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This repo demonstrates how to create a Cloud SQL DB with a private IP address only, and connect to it with [Cloud SQL Proxy](https://cloud.google.com/sql/docs/postgres/sql-proxy). The full explanation of how this works can be found in [this blog post](https://medium.com/@ryanboehning/how-to-deploy-a-cloud-sql-db-with-a-private-ip-only-using-terraform-e184b08eca64). -Terraform v1.0.0 or higher is required. +Terraform v1.4.0 or higher is required. ## How To Use @@ -40,5 +40,5 @@ Terraform v1.0.0 or higher is required. CLOUD_SQL_PROXY_IP=$(terraform output proxy_ip) # psql into your private db - ssh -t @$CLOUD_SQL_PROXY_IP docker run --rm --network=host -it postgres:14-alpine psql -U postgres -h localhost + ssh -t @$CLOUD_SQL_PROXY_IP docker container run --rm --network=host -it postgres:alpine psql -U postgres -h localhost ``` diff --git a/backend.tf b/backend.tf index d32e086..2c907df 100644 --- a/backend.tf +++ b/backend.tf @@ -1,5 +1,5 @@ terraform { - backend "remote" { + cloud { organization = "studybeast-org" workspaces { name = "private-ip-cloud-sql-db" diff --git a/main.tf b/main.tf index dbb47e0..39124df 100644 --- a/main.tf +++ b/main.tf @@ -21,7 +21,7 @@ module "db" { # because we've configured private services access. We need to explicitly # specify the dependency here. For details, see the note in the docs here: # https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#private-ip-instance - db_depends_on = module.vpc.private_vpc_connection + db_depends_on = [module.vpc.private_vpc_connection] } module "dbproxy" { diff --git a/modules/db/main.tf b/modules/db/main.tf index 583f11b..147a073 100644 --- a/modules/db/main.tf +++ b/modules/db/main.tf @@ -8,7 +8,7 @@ resource "google_sql_database" "main" { resource "google_sql_database_instance" "main_primary" { name = "main-primary" database_version = "POSTGRES_14" - depends_on = [var.db_depends_on] + depends_on = var.db_depends_on settings { tier = var.instance_type diff --git a/modules/db/variables.tf b/modules/db/variables.tf index 74d097d..2b8cd39 100644 --- a/modules/db/variables.tf +++ b/modules/db/variables.tf @@ -1,8 +1,8 @@ // db module variable "db_depends_on" { - description = "A single resource that the database instance depends on" - type = any + description = "Resources that the database instance depends on" + type = list(any) } variable "disk_size" { diff --git a/modules/dbproxy/main.tf b/modules/dbproxy/main.tf index a52af2f..13a42be 100644 --- a/modules/dbproxy/main.tf +++ b/modules/dbproxy/main.tf @@ -32,10 +32,13 @@ resource "google_compute_instance" "db_proxy" { enable-oslogin = "TRUE" } - metadata_startup_script = templatefile("${path.module}/run_cloud_sql_proxy.tpl", { - "db_instance_name" = var.db_instance_name, - "service_account_key" = module.serviceaccount.private_key, - }) + metadata_startup_script = <<-EOT + #!/bin/bash + set -euo pipefail + + docker container run --pull always --rm -p 127.0.0.1:5432:5432 gcr.io/cloudsql-docker/gce-proxy:latest \ + /cloud-sql-proxy --json-credentials=${module.serviceaccount.private_key} --private-ip '${var.db_instance_name}:postgres?address=0.0.0.0' + EOT network_interface { network = var.vpc_name diff --git a/modules/dbproxy/run_cloud_sql_proxy.tpl b/modules/dbproxy/run_cloud_sql_proxy.tpl deleted file mode 100644 index 7ce696e..0000000 --- a/modules/dbproxy/run_cloud_sql_proxy.tpl +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# We write the key to /var because it's one of the few directories that A) is -# writeable, and B) persists between reboots. B is important because GCP will -# automatically reboot the server if it goes down. We don't want to lose the -# key after a reboot. -echo '${service_account_key}' >/var/svc_account_key.json -chmod 444 /var/svc_account_key.json - -# TODO: delete this line and add the `--pull=always` flag to `docker run` -docker pull gcr.io/cloudsql-docker/gce-proxy:latest - -# -p 127.0.0.1:5432:3306 -- cloud_sql_proxy exposes port 3306 on the container, even for Postgres. -# We map 3306 in the container to 5432 on the host. '127.0.0.1' means -# that you can only connect to host port 5432 over localhost. -# -v /var/svc_account_key.json:/key.json:ro -- The file provisioner will copy the service account key file to /key.json -# on the host. We will mount it read-only into the container at the -# same path. -# -ip_address_types=PRIVATE -- The proxy should only try to connect to the db's private IP. -# -instances=${db_instance_name}=tcp:0.0.0.0:3306 -- The instance name will be something like 'my-project:us-central1:my-db'. -# The proxy should accept incoming TCP connections on port 3306. -docker run --rm -p 127.0.0.1:5432:3306 -v /var/svc_account_key.json:/key.json:ro gcr.io/cloudsql-docker/gce-proxy:latest /cloud_sql_proxy -credential_file=/key.json -ip_address_types=PRIVATE -instances=${db_instance_name}=tcp:0.0.0.0:3306 diff --git a/variables.tf b/variables.tf index dde7a99..2d830c4 100644 --- a/variables.tf +++ b/variables.tf @@ -2,24 +2,75 @@ variable "db_password" { description = "The Postgres password" type = string sensitive = true + + validation { + condition = length(var.db_password) > 16 + error_message = "The db_password must be at least 16 characters long." + } } variable "db_username" { description = "The Postgres username" - type = string + type = string + + validation { + condition = length(var.db_username) > 0 + error_message = "The db_username must be at least 1 character long." + } } variable "gcp_project_name" { description = "The name of the GCP project where the db and Cloud SQL Proxy will be created" - type = string + type = string } variable "gcp_region" { description = "The GCP region where the db and Cloud SQL Proxy will be created" - type = string + type = string + + validation { + condition = contains([ + "asia-east1", + "asia-east2", + "asia-northeast1", + "asia-northeast2", + "asia-northeast3", + "asia-south1", + "asia-south2", + "asia-southeast1", + "asia-southeast2", + "australia-southeast1", + "australia-southeast2", + "europe-central2", + "europe-north1", + "europe-southwest1", + "europe-west1", + "europe-west2", + "europe-west3", + "europe-west4", + "europe-west6", + "europe-west8", + "europe-west9", + "me-west1", + "northamerica-northeast1", + "northamerica-northeast2", + "southamerica-east1", + "southamerica-west1", + "us-central1", + "us-east1", + "us-east4", + "us-east5", + "us-south1", + "us-west1", + "us-west2", + "us-west3", + "us-west4", + ], var.gcp_region) + error_message = "Your gcp_region is not on our list of supported regions." + } } variable "gcp_zone" { description = "The GCP availability zone where the db and Cloud SQL Proxy will be created" - type = string + type = string } diff --git a/versions.tf b/versions.tf index 5eb53b4..983dff5 100644 --- a/versions.tf +++ b/versions.tf @@ -1,14 +1,14 @@ terraform { - required_version = ">= 1.0.0" + required_version = ">= 1.4.0" required_providers { tfe = { source = "hashicorp/tfe" - version = ">= 0.25.0" + version = ">= 0.42.0" } google = { source = "hashicorp/google" - version = ">= 3.70.0" + version = ">= 4.56.0" } } }