From 88aa46f1567046e16f69499e664eaa166cb2e463 Mon Sep 17 00:00:00 2001 From: Konstantin Tarkus Date: Sun, 4 Feb 2024 01:24:02 +0100 Subject: [PATCH] refactor(infra): environment-specific TF configurations --- .gitignore | 5 +- .vscode/settings.json | 3 + infra/.terraform.lock.hcl | 62 ------------- infra/README.md | 95 +++++++------------ infra/backend.tf | 12 --- infra/core/.terraform.lock.hcl | 64 +++++++++++++ infra/core/database.tf | 40 ++++++++ infra/core/iam.tf | 8 ++ infra/core/outputs.tf | 12 +++ infra/core/providers.tf | 10 ++ infra/core/storage.tf | 17 ++++ infra/core/terraform.tf | 29 ++++++ infra/core/variables.tf | 26 ++++++ infra/database.tf | 47 ---------- infra/outputs.tf | 4 - infra/providers.tf | 46 ---------- infra/server-preview/.terraform.lock.hcl | 41 +++++++++ infra/server-preview/database.tf | 12 +++ infra/server-preview/providers.tf | 8 ++ infra/server-preview/terraform.tf | 20 ++++ infra/server-preview/variables.tf | 32 +++++++ infra/server-prod/.terraform.lock.hcl | 22 +++++ infra/server-prod/database.tf | 12 +++ infra/server-prod/providers.tf | 8 ++ infra/server-prod/terraform.tf | 20 ++++ infra/server-prod/variables.tf | 32 +++++++ infra/server-test/.terraform.lock.hcl | 41 +++++++++ infra/server-test/database.tf | 12 +++ infra/server-test/providers.tf | 8 ++ infra/server-test/terraform.tf | 20 ++++ infra/server-test/variables.tf | 32 +++++++ infra/services.tf | 23 ----- infra/storage.tf | 41 --------- infra/variables.tf | 47 ---------- scripts/tf.js | 111 ----------------------- tsconfig.json | 6 +- 36 files changed, 570 insertions(+), 458 deletions(-) delete mode 100644 infra/.terraform.lock.hcl delete mode 100644 infra/backend.tf create mode 100644 infra/core/.terraform.lock.hcl create mode 100644 infra/core/database.tf create mode 100644 infra/core/iam.tf create mode 100644 infra/core/outputs.tf create mode 100644 infra/core/providers.tf create mode 100644 infra/core/storage.tf create mode 100644 infra/core/terraform.tf create mode 100644 infra/core/variables.tf delete mode 100644 infra/database.tf delete mode 100644 infra/outputs.tf delete mode 100644 infra/providers.tf create mode 100644 infra/server-preview/.terraform.lock.hcl create mode 100644 infra/server-preview/database.tf create mode 100644 infra/server-preview/providers.tf create mode 100644 infra/server-preview/terraform.tf create mode 100644 infra/server-preview/variables.tf create mode 100644 infra/server-prod/.terraform.lock.hcl create mode 100644 infra/server-prod/database.tf create mode 100644 infra/server-prod/providers.tf create mode 100644 infra/server-prod/terraform.tf create mode 100644 infra/server-prod/variables.tf create mode 100644 infra/server-test/.terraform.lock.hcl create mode 100644 infra/server-test/database.tf create mode 100644 infra/server-test/providers.tf create mode 100644 infra/server-test/terraform.tf create mode 100644 infra/server-test/variables.tf delete mode 100644 infra/services.tf delete mode 100644 infra/storage.tf delete mode 100644 infra/variables.tf delete mode 100644 scripts/tf.js diff --git a/.gitignore b/.gitignore index d2ff27d9..36d536b7 100644 --- a/.gitignore +++ b/.gitignore @@ -54,10 +54,13 @@ yarn-error.log* *.tfstate.* *.tfvars *.tfvars.json -.terraformrc override.tf +override.tf.json +*_override.tf +*_override.tf.json crash.log crash.*.log +.terraformrc # WebStorm .idea diff --git a/.vscode/settings.json b/.vscode/settings.json index e8574393..ead78582 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -35,14 +35,17 @@ "**/yarn.lock": true }, "terminal.integrated.env.linux": { + "TF_CLI_CONFIG_FILE": "${workspaceFolder}/.terraformrc", "CLOUDSDK_ACTIVE_CONFIG_NAME": "default", "CACHE_DIR": "${workspaceFolder}/.cache" }, "terminal.integrated.env.osx": { + "TF_CLI_CONFIG_FILE": "${workspaceFolder}/.terraformrc", "CLOUDSDK_ACTIVE_CONFIG_NAME": "default", "CACHE_DIR": "${workspaceFolder}/.cache" }, "terminal.integrated.env.windows": { + "TF_CLI_CONFIG_FILE": "${workspaceFolder}/.terraformrc", "CLOUDSDK_ACTIVE_CONFIG_NAME": "default", "CACHE_DIR": "${workspaceFolder}\\.cache" }, diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl deleted file mode 100644 index 0336dcb7..00000000 --- a/infra/.terraform.lock.hcl +++ /dev/null @@ -1,62 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/cloudflare/cloudflare" { - version = "3.7.0" - constraints = "~> 3.7" - hashes = [ - "h1:iSgLTS7GY60bFc8qsbKSW2SB/RkY7CgHSNlheyf4x5E=", - "zh:0461136530c8e8e9db339c92cf1b2dff28814e4c0930cced96c4597b6b6a9657", - "zh:09d97a2c0d0ea4f0f58147ea7651f4ed3ceab32a398afa930b90d2e9f105fdd5", - "zh:0a4431931840fb9d5eae4ad76bd95d7df9d3f4ce45f18c079c29a688b2b6d3b0", - "zh:15cd395ae642d90699f5012429431f2c45f650951d0d8319547d7b72c6d61b29", - "zh:30c332f736926376a2e7f0f82ab0d7d682aaefb3917e78faa4a12964cd850822", - "zh:33d9c4745c00034781c135f75543814858098c019dba8b586d3dc72fbe29b02b", - "zh:4029f0d0b53e98a92f3a64f1681dd8d2eca1a6ef534290330fba418a479ae156", - "zh:4d6aa87862debbf709c81d9687222111b7ef22ab1038fa99d84374aee675ec86", - "zh:865f52bcfcede282b2d64d91b6984bd33a75fc000e0d92a5dd027aca9fc3b48b", - "zh:8a04190962b7e78aa1356df75f699d1a96ba319d71dcbfbbc5cbe9afc71d849c", - "zh:9ce9c264c74b4a23bb67799356a82a409d39fbf752f83d29f38b8d866fa71a40", - "zh:d8866223c56e574efede5f1704194e158452b6ee7404addb91d0cc4be48586a5", - "zh:f6daad59ffad2741c84665fa7cbd7ae6d76931b21beff7b7a8be336cebbbfb26", - "zh:fc71c04b466b24d456bf6c0a434324e7ed6508c7c439e2ceb361bf961a077b97", - ] -} - -provider "registry.terraform.io/hashicorp/google" { - version = "4.8.0" - constraints = ">= 4.8.0" - hashes = [ - "h1:AipkQYzvwxYrjoNCqAU6vw2VGD/c+mt38isiDrbFHvU=", - "zh:08d1fbdaee6f9d615e09ab6244d5f8f1b76fd079fc4193822a9f5ac4344b3738", - "zh:27afa2e26921ca5b96e804b781792296e9a9d4ac533d6f87c3855ae68e28ef80", - "zh:2d1fe33d3c6daa85a9ba6608b99d9710c7fcd61199d249e353e82d5bf1a18280", - "zh:31b2c41dbe458d8b75068069bb05864027bd1b4a3f4c8e8b7cd7b9d1fe47be7b", - "zh:4001c5237a4fb383014b685077c12a0b9cdbac28dce0c707a9a4622d62ef06c9", - "zh:82c9ef3f72fa6a8fba163cff94b0f7fd0572724e991af5c7f389feaaf83298d8", - "zh:9524a6dc9d8b2cbcef53ca2c04e121899bb1947ff8d4f9569c3b01b1cb9f736a", - "zh:a33dcd5d8efef4dafaa331918c79b793be036420fc56c40bb3fb313fdb56db0d", - "zh:aa36241871cb5376c7ba8cb8b2ddbfc488c4231e5c0d10b2f421ffaa14c0b462", - "zh:cd2c1ffbab0c6e154ed2472edc2788bc2cb9db93848325e389a7157ebbb540de", - "zh:f350242dabb33035e2b49cd3e925c88c6bf4b73becfaff298d503e4c64e46271", - ] -} - -provider "registry.terraform.io/hashicorp/google-beta" { - version = "4.8.0" - constraints = ">= 3.43.0, ~> 4.8, < 5.0.0" - hashes = [ - "h1:FaZDwlIBM9TS6MSmIcjtK90s8spW5JB88OGJ6DGqz68=", - "zh:1925468fbb25bbde8710feb80dc52e9f0321304d8bb464873528afb446bd6e79", - "zh:256865f0d6251b671a9ca9fd92f8bfa576b250fcf3b85491b6e7e4f690e79ab2", - "zh:54aa3afd4865d348fe82ac59fe0d505d1b0ae74f7690f225302c59e1c2bd1b67", - "zh:660c4e18f4e330274140a1a971847b3f52435355dfffcecd21a98c3791d89a6c", - "zh:82d356bd597f7dbcf15b830d4180601b18d3bedfdd6dbe7518e06fcab6abe4fc", - "zh:9791a7751b9c2966d8234637e47e28ae6027a6833d88b684764c70501dcbb0f2", - "zh:a07e0856924d7346e099727077f8d1652393995dca04df093ed4238c6ec0df13", - "zh:ad18e7f0f7dc5a0bec74e7a1da2fec83185808cb8eaac048bfb88594e317c5ca", - "zh:b1eaff77e657065f8ffba4423e1c1bda2d0b5b370ce88a1c18e814c1f2db3889", - "zh:d73ac7b0410c357a1f99f6e599d970e72c6aab7b29eace673f843cdfe5819af7", - "zh:e069e2fbc2c404b903b75fb8e6cbf0b5bd2b9b06269a87979593ec0630be2b02", - ] -} diff --git a/infra/README.md b/infra/README.md index 6274283f..ff46f338 100644 --- a/infra/README.md +++ b/infra/README.md @@ -1,85 +1,54 @@ -# Cloud Infrastructure +# Terraform Cloud Project -The Google Cloud Platform (GCP) and Cloudflare infrastructure resources required -by the app and that can be bootstrapped via [Terraform](https://www.terraform.io/). +This folder contains the Terraform configurations for our project's infrastructure, managed through Terraform Cloud. The infrastructure is divided into multiple workspaces to handle different environments and shared resources. -## Requirements +## Directory Structure -- [Node.js](https://nodejs.org/en/) v18+ with [Yarn](https://yarnpkg.com/) package manager -- [Google Cloud SDK](https://cloud.google.com/sdk/docs/install) and [Terraform CLI](https://learn.hashicorp.com/tutorials/terraform/install-cli) -- Access to [Google Cloud Projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects) and [Terraform Cloud](https://cloud.hashicorp.com/products/terraform) workspaces +The repository is organized into the following directories, each corresponding to a specific Terraform Cloud workspace: -
- How to install Terraform CLI on macOS?
+- **[`/core`](./core/)** - This directory contains the Terraform configurations for the global/shared resources used across all environments. These may include VPCs, shared databases, IAM roles, etc. -```bash -$ brew tap hashicorp/tap -$ brew install hashicorp/tap/terraform -$ brew update -$ brew upgrade hashicorp/tap/terraform -$ yarn tf -version -``` +- **[`/server-prod`](./server-prod/)** - Contains the Terraform configurations for the production web server. This workspace should be configured with production-grade settings, ensuring high availability and security. -
+- **[`/server-test`](./server-test/)** - Holds the configurations for the testing/QA web server. This environment mirrors production closely and is used for final testing before deploying to production. -
- How to create Google Cloud Platform projects?
+- **[`/server-preview`](./server-preview/)** - This directory is for the preview web server, typically used for staging and pre-release reviews. It might contain configurations that are under testing or not yet approved for the testing environment. -Simply navigate to [Google Cloud Resource Manager](https://console.cloud.google.com/cloud-resource-manager) -and create two GCP projects for both `test` (QA) and `prod` (production) -environments, e.g. "example" and "example-test". +## Usage -Fore more information visit https://cloud.google.com/resource-manager/docs/creating-managing-projects
+### Prerequisites -
+- Terraform +- Access to the Terraform Cloud workspace -
- How to configure Terraform Cloud workspaces?
+### Setting Up Workspaces in Terraform Cloud -1. Sign in to [Terraform Cloud](https://cloud.hashicorp.com/products/terraform) dashboard. -2. Create or join an organization. -3. Create two workspaces — `app-test` and `app-prod` for test/QA and production environments. -4. In each of these workspaces create an environment variable called `GOOGLE_CREDENTIALS` with the value containing JSON key of a GCP [service account](https://cloud.google.com/iam/docs/service-accounts). Note, this GCP service account needs to have `Owner` or `Editor` + `Service Usage Admin` roles. +1. Log in to Terraform Cloud. +2. Create a workspace for each directory/environment. +3. Link each workspace to the corresponding directory in this repository. +4. Save Terraform API token to the `../.terraformrc` file. -For more information visit https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference
+### Working with Terraform -
+To work with Terraform configurations: -
- How to authenticate Terraform CLI in Terraform Cloud?
+1. Navigate to the appropriate directory (e.g., `cd server-prod`). +2. Initialize Terraform: `terraform init`. +3. Apply configurations: `terraform apply`. -1. Create a personal or team [API Token](https://learn.hashicorp.com/tutorials/terraform/cloud-login) via [Terraform Cloud](https://app.terraform.io/app/) dashboard → [Settings](https://app.terraform.io/app/settings/tokens). -2. Save API token to the `.terraformrc` file in root of the project: +Ensure that you are working in the correct workspace to avoid misconfigurations. -``` -credentials "app.terraform.io" { - token = "xxxxxx.atlasv1.zzzzzzzzzzzzz" -} -``` +### Contributions -**NOTE**: This would allow to using different Terraform credentials per software project if you want to.
+Please follow our contribution guidelines for making changes or adding new configurations. Ensure you test configurations in the test and preview environments before applying them to production. -
+## Support -## Getting Started +For any issues or questions related to this Terraform setup, please contact [@koistya](https://github.com/koistya) on our [Discord server](https://discord.com/invite/bSsv7XM). -- `yarn tf init -upgrade` — Initializes a Terraform workspace -- `yarn tf plan` — creates an execution plan -- `yarn tf apply` — executes the actions proposed by the `yarn tf plan` command +### References -**NOTE**: By default the `app-test` Terraform workspace is used. In order to use -the production workspace, set `TF_WORKSPACE` environment variable to `prod`. For -example: - -```bash -$ TF_WORKSPACE=prod tf plan -$ TF_WORKSPACE=prod tf apply -``` - -**NOTE**: You need to run Terraform commands via `yarn tf [...args]`. - -

- -

- -Fore more information visit https://learn.hashicorp.com/terraform +- https://learn.hashicorp.com/terraform +- https://cloud.google.com/docs/terraform/best-practices-for-terraform +- https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines +- https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference.html diff --git a/infra/backend.tf b/infra/backend.tf deleted file mode 100644 index b7529699..00000000 --- a/infra/backend.tf +++ /dev/null @@ -1,12 +0,0 @@ -# The block below configures Terraform to use the 'remote' backend with Terraform Cloud. -# For more information, see https://www.terraform.io/language/settings/backends/remote - -terraform { - backend "remote" { - organization = "example" - - workspaces { - prfix = "app-" - } - } -} diff --git a/infra/core/.terraform.lock.hcl b/infra/core/.terraform.lock.hcl new file mode 100644 index 00000000..0bb689e2 --- /dev/null +++ b/infra/core/.terraform.lock.hcl @@ -0,0 +1,64 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/cloudflare/cloudflare" { + version = "4.23.0" + constraints = "~> 4.23" + hashes = [ + "h1:Kn7JXfcIA+vYHZhXtWUxNJ7wJ62ICet3a93gyYez9/U=", + "zh:034aae9f29e51b008eb5ff62bcfea4078d92d74fd8eb6e0f1833395002bf483d", + "zh:0e4f72b52647791e34894c231c7d17b55c701fb4ff9d8aeb8355031378b20910", + "zh:248ecf3820a65870a8a811a90488a77a8fcc49ee6e3099734328912250c4145a", + "zh:750114d16fefb3ce6cfc81fc4d86ab3746062dccd3fc5556a6dff39d600d55f3", + "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", + "zh:8fe4b545d8c90eb55b75ede1bc5a6bb1483a00466364cd08b1096abddc52e34b", + "zh:ba203d96d07a313dd77933ff29d09110c1dc5100a44aa540c2c73ea280215c85", + "zh:be22358de9729068edc462985c2c99c4d49eec87c6662e75e7216962b0b47a12", + "zh:c55add4c66855191020b5ed61fe8561403eac9d3f55f343876f1f0a5e2ccf1bc", + "zh:c57034c34a10317715264b9455a74b53b2604a3cb206f2c5089ae61b5e8e18fa", + "zh:c95b026d652cb2f90b526cdc79dc22faa0789a049e55b5f2a41412ac45bca2ec", + "zh:ca49437e5462c060b64d0ebf7a7d1370f55139afdb6a23f032694d363b44243b", + "zh:d52788bd6ca087fa72ae9d22c09693c3f5ce5502a00e2c195bea5f420735006c", + "zh:e43da4d400951310020969bd5952483c05de824d67fdcdddc76ec9d97de0d18e", + "zh:ff150dddcbb0d623ff1948d1359fa956519f0672f832faedb121fc809e9c4c22", + ] +} + +provider "registry.terraform.io/hashicorp/google" { + version = "5.14.0" + constraints = "~> 5.14.0" + hashes = [ + "h1:T6EW5HOI1IrE4zHzQ/5kLyul+U2ByEaIgqMu4Ja7JFI=", + "zh:3927ef7417d9d8a56077e6655d76c99f4175f9746e39226a00ee0555f8c63f8f", + "zh:4b4f521f0779a1797047a8c531afda093aade934b4a49c080fe8d38680b3a52f", + "zh:7e880c5b72684fc8342e03180a1fbbec65c6afeb70511b9c16181d5e168269e6", + "zh:81a7f2efc30e698f476d3e240ee2d82f14eda374852059429fe808ad77b6addd", + "zh:826d4ea55b4afceefb332646f21c6b6dc590b39b16e8d9b5d4a4211beb91dc5e", + "zh:865600ef669fcdd4ae77515c3fd12565fab0f2a263fa2a6dae562f6fe68ed093", + "zh:8e933d1d10fd316e62340175667264f093e4d24457b63d5adf3c424cce22b495", + "zh:bf261924f7350074a355e5b9337f3a8054efb20d316e9085f2b5766dfb5126c4", + "zh:e28e67dcbd4bbd82798561baf86d3dd04f97e08bbf523dfb9f355564ef27d3d6", + "zh:f33cdd3117af8a15f33d375dbe398a5e558730cf6a7a145a479ab68e77572c12", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f913a0e0708391ccd26fc3458158cc1e10d68dc621bef3a1583328c61a77225d", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.0" + hashes = [ + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + ] +} diff --git a/infra/core/database.tf b/infra/core/database.tf new file mode 100644 index 00000000..089dcadd --- /dev/null +++ b/infra/core/database.tf @@ -0,0 +1,40 @@ +# Google Cloud SQL +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database + +resource "random_id" "db_name_suffix" { + byte_length = 4 +} + +resource "google_project_service" "compute" { + service = "compute.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_service" "sqladmin" { + service = "sqladmin.googleapis.com" + disable_on_destroy = false +} + +resource "google_sql_database_instance" "db" { + name = "db-${random_id.db_name_suffix.hex}" + database_version = "POSTGRES_15" + deletion_protection = false + + settings { + tier = "db-f1-micro" + + database_flags { + name = "cloudsql.iam_authentication" + value = "on" + } + } + + depends_on = [google_project_service.sqladmin] +} + +resource "google_sql_user" "developer" { + name = trimsuffix(google_service_account.developer.email, ".gserviceaccount.com") + instance = google_sql_database_instance.db.name + type = "CLOUD_IAM_SERVICE_ACCOUNT" + depends_on = [google_service_account.developer] +} diff --git a/infra/core/iam.tf b/infra/core/iam.tf new file mode 100644 index 00000000..7debc4cc --- /dev/null +++ b/infra/core/iam.tf @@ -0,0 +1,8 @@ +# Google Cloud Service Account +# https://cloud.google.com/compute/docs/access/service-accounts +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account + +resource "google_service_account" "developer" { + account_id = "developer" + display_name = "Developer" +} diff --git a/infra/core/outputs.tf b/infra/core/outputs.tf new file mode 100644 index 00000000..b2cd28e4 --- /dev/null +++ b/infra/core/outputs.tf @@ -0,0 +1,12 @@ +# Output Values +# https://developer.hashicorp.com/terraform/language/values/outputs + +output "db_instance_name" { + value = google_sql_database_instance.db.name + sensitive = false +} + +output "developer_service_account_email" { + value = google_service_account.developer.email + sensitive = false +} diff --git a/infra/core/providers.tf b/infra/core/providers.tf new file mode 100644 index 00000000..9f71f115 --- /dev/null +++ b/infra/core/providers.tf @@ -0,0 +1,10 @@ +# Provider Configuration +# https://developer.hashicorp.com/terraform/language/providers/configuration + +# Google Cloud Platform Provider +# https://registry.terraform.io/providers/hashicorp/google/latest/docs +provider "google" { + project = var.gcp_project + region = var.gcp_region + zone = var.gcp_zone +} diff --git a/infra/core/storage.tf b/infra/core/storage.tf new file mode 100644 index 00000000..833e5a81 --- /dev/null +++ b/infra/core/storage.tf @@ -0,0 +1,17 @@ +# Google Cloud Storage +# +# NOTE: The Google account under which the Terraform Cloud agents run must have +# the owner role on the target domain name in order to create Google Cloud +# Storage buckets using that domain name. You can update the list of owner +# members in the Google Search Console at the following URL: +# https://search.google.com/search-console/welcome?new_domain_name=example.com +# https://cloud.google.com/storage/docs/domain-name-verification + +resource "google_storage_bucket" "pkg" { + name = "pkg.${var.root_level_domain}" + location = "US" + force_destroy = false + + uniform_bucket_level_access = true + public_access_prevention = "enforced" +} diff --git a/infra/core/terraform.tf b/infra/core/terraform.tf new file mode 100644 index 00000000..8505fbfa --- /dev/null +++ b/infra/core/terraform.tf @@ -0,0 +1,29 @@ +# Terraform Cloud configuration for the core (shared) workspace +# https://developer.hashicorp.com/terraform/cli/cloud/settings + +terraform { + cloud { + organization = "example" + + workspaces { + project = "default" + name = "core" + } + } + + required_providers { + # Google Cloud Platform Provider + # https://registry.terraform.io/providers/hashicorp/google/latest/docs + google = { + source = "hashicorp/google" + version = "~> 5.14.0" + } + + # Cloudflare Provider + # https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 4.23" + } + } +} diff --git a/infra/core/variables.tf b/infra/core/variables.tf new file mode 100644 index 00000000..bf23dab8 --- /dev/null +++ b/infra/core/variables.tf @@ -0,0 +1,26 @@ +# Input Variables +# https://developer.hashicorp.com/terraform/language/values/variables + +variable "gcp_project" { + type = string + description = "Google Cloud Project ID" + default = "example" +} + +variable "gcp_region" { + type = string + description = "Google Cloud region" + default = "us-central1" +} + +variable "gcp_zone" { + type = string + description = "Google Cloud zone" + default = "us-central1-c" +} + +variable "root_level_domain" { + type = string + description = "The root-level domain for the app" + default = "example.com" +} diff --git a/infra/database.tf b/infra/database.tf deleted file mode 100644 index b377bef3..00000000 --- a/infra/database.tf +++ /dev/null @@ -1,47 +0,0 @@ -# Google Cloud SQL -# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database - -resource "google_sql_database" "default" { - name = var.database - instance = google_sql_database_instance.pg14.name - charset = "UTF8" - collation = "en_US.UTF8" - timeouts {} -} - -resource "google_sql_database_instance" "pg14" { - name = "pg14" - region = "us-central1" - database_version = "POSTGRES_14" - deletion_protection = true - - settings { - tier = "db-f1-micro" - - disk_size = 100 - disk_type = "PD_SSD" - - ip_configuration { - require_ssl = true - } - - backup_configuration { - enabled = true - location = "us" - start_time = "21:00" - - point_in_time_recovery_enabled = true - transaction_log_retention_days = 7 - - backup_retention_settings { - retained_backups = 7 - retention_unit = "COUNT" - } - } - - maintenance_window { - day = 7 - hour = 0 - } - } -} diff --git a/infra/outputs.tf b/infra/outputs.tf deleted file mode 100644 index 407f2d3f..00000000 --- a/infra/outputs.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "project_id" { - value = module.project-services.project_id - description = "The GCP project you want to enable APIs on" -} diff --git a/infra/providers.tf b/infra/providers.tf deleted file mode 100644 index 88a4d8a0..00000000 --- a/infra/providers.tf +++ /dev/null @@ -1,46 +0,0 @@ -# Terraform Providers -# https://registry.terraform.io/browse/providers - -terraform { - required_providers { - # Google Cloud Platform Provider - # https://registry.terraform.io/providers/hashicorp/google/latest/docs - # https://github.com/hashicorp/terraform-provider-google - google = { - source = "hashicorp/google" - version = "~> 4.8" - } - - # Google Cloud Platfrom Provider (beta) - # https://registry.terraform.io/providers/hashicorp/google/latest/docs - # https://github.com/hashicorp/terraform-provider-google-beta - google-beta = { - source = "hashicorp/google-beta" - version = "~> 4.8" - } - - # Cloudflare Provider - # https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs - # https://github.com/cloudflare/terraform-provider-cloudflare - cloudflare = { - source = "cloudflare/cloudflare" - version = "~> 3.7" - } - } -} - -provider "google" { - project = var.project - region = var.region - zone = var.zone -} - -provider "google-beta" { - project = var.project - region = var.region - zone = var.zone -} - -provider "cloudflare" { - api_token = var.cloudflare_api_token -} diff --git a/infra/server-preview/.terraform.lock.hcl b/infra/server-preview/.terraform.lock.hcl new file mode 100644 index 00000000..e79904df --- /dev/null +++ b/infra/server-preview/.terraform.lock.hcl @@ -0,0 +1,41 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/google" { + version = "5.14.0" + constraints = "~> 5.14.0" + hashes = [ + "h1:T6EW5HOI1IrE4zHzQ/5kLyul+U2ByEaIgqMu4Ja7JFI=", + "zh:3927ef7417d9d8a56077e6655d76c99f4175f9746e39226a00ee0555f8c63f8f", + "zh:4b4f521f0779a1797047a8c531afda093aade934b4a49c080fe8d38680b3a52f", + "zh:7e880c5b72684fc8342e03180a1fbbec65c6afeb70511b9c16181d5e168269e6", + "zh:81a7f2efc30e698f476d3e240ee2d82f14eda374852059429fe808ad77b6addd", + "zh:826d4ea55b4afceefb332646f21c6b6dc590b39b16e8d9b5d4a4211beb91dc5e", + "zh:865600ef669fcdd4ae77515c3fd12565fab0f2a263fa2a6dae562f6fe68ed093", + "zh:8e933d1d10fd316e62340175667264f093e4d24457b63d5adf3c424cce22b495", + "zh:bf261924f7350074a355e5b9337f3a8054efb20d316e9085f2b5766dfb5126c4", + "zh:e28e67dcbd4bbd82798561baf86d3dd04f97e08bbf523dfb9f355564ef27d3d6", + "zh:f33cdd3117af8a15f33d375dbe398a5e558730cf6a7a145a479ab68e77572c12", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f913a0e0708391ccd26fc3458158cc1e10d68dc621bef3a1583328c61a77225d", + ] +} + +provider "registry.terraform.io/hashicorp/tfe" { + version = "0.51.1" + hashes = [ + "h1:n7O1yooxtUk1G0T0jyrt5ItstX5fIPoSUqMibBHA6E0=", + "zh:08f5c2296a7eba39fb3b86cc9f294ac7a9ca06eee1dec44fbf14615523fd24d0", + "zh:46ea31b9ca5450d947c0b28b698aca6df97714e671f25a2e2c9ea3ba0e0d45a0", + "zh:6326962e8afda2da9c2724a465eee4ae12c514700ccfaead7be81c73d6d7f8cd", + "zh:649639793e0cbfe8732377052110441ae24b4a3b2e35126aab5d0b9da291ac9a", + "zh:8ca07718347273bbbc8a7c0f488da22efa38a67ec05b6db3bf97d01d9ba600c0", + "zh:a9065ad79c7a3d91ee1f7021edea02f92ace116830fa0857580dcd267643a016", + "zh:bc6014f7597b281ca9aa73fe91c9060f29311096a543c2cf794803920662edc4", + "zh:c48897ce5820983c1a94b6912317fbf4927b4eca9f550c7d5e1af40a4bc9fd5f", + "zh:ca32cc1543d65a1e418eaadccd0f00d6a626ff0b40d495e508b444d95b290ed0", + "zh:d179e1f38f789ebefb4cfce8148181999bd2e24f860b2e18cdaeca2b37fbe7f6", + "zh:d95ec293fa70e946b6cd657912b33155f8be3413e6128ed2bfa5a493f788e439", + "zh:fe9538fc1da16bbd675f33176ac3d2a20c264b5c7a14389c552a889f7a1c46e4", + ] +} diff --git a/infra/server-preview/database.tf b/infra/server-preview/database.tf new file mode 100644 index 00000000..4686774f --- /dev/null +++ b/infra/server-preview/database.tf @@ -0,0 +1,12 @@ +# Google CLoud SQL Database. +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database + +data "tfe_outputs" "core" { + organization = var.tfe_organization + workspace = "core" +} + +resource "google_sql_database" "db" { + name = var.db_name + instance = data.tfe_outputs.core.values.db_instance_name +} diff --git a/infra/server-preview/providers.tf b/infra/server-preview/providers.tf new file mode 100644 index 00000000..c5a0b45b --- /dev/null +++ b/infra/server-preview/providers.tf @@ -0,0 +1,8 @@ +# Provider Configuration +# https://developer.hashicorp.com/terraform/language/providers/configuration + +provider "google" { + project = var.gcp_project + region = var.gcp_region + zone = var.gcp_zone +} diff --git a/infra/server-preview/terraform.tf b/infra/server-preview/terraform.tf new file mode 100644 index 00000000..4c3ff6c2 --- /dev/null +++ b/infra/server-preview/terraform.tf @@ -0,0 +1,20 @@ +# Terraform Cloud configuration for the core (shared) workspace +# https://developer.hashicorp.com/terraform/cli/cloud/settings + +terraform { + cloud { + organization = "example" + + workspaces { + project = "default" + name = "server-preview" + } + } + + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.14.0" + } + } +} diff --git a/infra/server-preview/variables.tf b/infra/server-preview/variables.tf new file mode 100644 index 00000000..02233fb1 --- /dev/null +++ b/infra/server-preview/variables.tf @@ -0,0 +1,32 @@ +# Input Variables +# https://developer.hashicorp.com/terraform/language/values/variables + +variable "tfe_organization" { + type = string + description = "Terraform Cloud organization ID" + default = "example" +} + +variable "gcp_project" { + type = string + description = "Google Cloud Project ID" + default = "example" +} + +variable "gcp_region" { + type = string + description = "Google Cloud region" + default = "us-central1" +} + +variable "gcp_zone" { + type = string + description = "Google Cloud zone" + default = "us-central1-c" +} + +variable "db_name" { + type = string + description = "Database name" + default = "example-preview" +} diff --git a/infra/server-prod/.terraform.lock.hcl b/infra/server-prod/.terraform.lock.hcl new file mode 100644 index 00000000..aaf8f7e9 --- /dev/null +++ b/infra/server-prod/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/google" { + version = "5.14.0" + constraints = "~> 5.14.0" + hashes = [ + "h1:T6EW5HOI1IrE4zHzQ/5kLyul+U2ByEaIgqMu4Ja7JFI=", + "zh:3927ef7417d9d8a56077e6655d76c99f4175f9746e39226a00ee0555f8c63f8f", + "zh:4b4f521f0779a1797047a8c531afda093aade934b4a49c080fe8d38680b3a52f", + "zh:7e880c5b72684fc8342e03180a1fbbec65c6afeb70511b9c16181d5e168269e6", + "zh:81a7f2efc30e698f476d3e240ee2d82f14eda374852059429fe808ad77b6addd", + "zh:826d4ea55b4afceefb332646f21c6b6dc590b39b16e8d9b5d4a4211beb91dc5e", + "zh:865600ef669fcdd4ae77515c3fd12565fab0f2a263fa2a6dae562f6fe68ed093", + "zh:8e933d1d10fd316e62340175667264f093e4d24457b63d5adf3c424cce22b495", + "zh:bf261924f7350074a355e5b9337f3a8054efb20d316e9085f2b5766dfb5126c4", + "zh:e28e67dcbd4bbd82798561baf86d3dd04f97e08bbf523dfb9f355564ef27d3d6", + "zh:f33cdd3117af8a15f33d375dbe398a5e558730cf6a7a145a479ab68e77572c12", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f913a0e0708391ccd26fc3458158cc1e10d68dc621bef3a1583328c61a77225d", + ] +} diff --git a/infra/server-prod/database.tf b/infra/server-prod/database.tf new file mode 100644 index 00000000..4686774f --- /dev/null +++ b/infra/server-prod/database.tf @@ -0,0 +1,12 @@ +# Google CLoud SQL Database. +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database + +data "tfe_outputs" "core" { + organization = var.tfe_organization + workspace = "core" +} + +resource "google_sql_database" "db" { + name = var.db_name + instance = data.tfe_outputs.core.values.db_instance_name +} diff --git a/infra/server-prod/providers.tf b/infra/server-prod/providers.tf new file mode 100644 index 00000000..c5a0b45b --- /dev/null +++ b/infra/server-prod/providers.tf @@ -0,0 +1,8 @@ +# Provider Configuration +# https://developer.hashicorp.com/terraform/language/providers/configuration + +provider "google" { + project = var.gcp_project + region = var.gcp_region + zone = var.gcp_zone +} diff --git a/infra/server-prod/terraform.tf b/infra/server-prod/terraform.tf new file mode 100644 index 00000000..b5a47d58 --- /dev/null +++ b/infra/server-prod/terraform.tf @@ -0,0 +1,20 @@ +# Terraform Cloud configuration for the core (shared) workspace +# https://developer.hashicorp.com/terraform/cli/cloud/settings + +terraform { + cloud { + organization = "example" + + workspaces { + project = "default" + name = "server-prod" + } + } + + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.14.0" + } + } +} diff --git a/infra/server-prod/variables.tf b/infra/server-prod/variables.tf new file mode 100644 index 00000000..932ddf40 --- /dev/null +++ b/infra/server-prod/variables.tf @@ -0,0 +1,32 @@ +# Input Variables +# https://developer.hashicorp.com/terraform/language/values/variables + +variable "tfe_organization" { + type = string + description = "Terraform Cloud organization ID" + default = "example" +} + +variable "gcp_project" { + type = string + description = "Google Cloud Project ID" + default = "example" +} + +variable "gcp_region" { + type = string + description = "Google Cloud region" + default = "us-central1" +} + +variable "gcp_zone" { + type = string + description = "Google Cloud zone" + default = "us-central1-c" +} + +variable "db_name" { + type = string + description = "Database name" + default = "example" +} diff --git a/infra/server-test/.terraform.lock.hcl b/infra/server-test/.terraform.lock.hcl new file mode 100644 index 00000000..e79904df --- /dev/null +++ b/infra/server-test/.terraform.lock.hcl @@ -0,0 +1,41 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/google" { + version = "5.14.0" + constraints = "~> 5.14.0" + hashes = [ + "h1:T6EW5HOI1IrE4zHzQ/5kLyul+U2ByEaIgqMu4Ja7JFI=", + "zh:3927ef7417d9d8a56077e6655d76c99f4175f9746e39226a00ee0555f8c63f8f", + "zh:4b4f521f0779a1797047a8c531afda093aade934b4a49c080fe8d38680b3a52f", + "zh:7e880c5b72684fc8342e03180a1fbbec65c6afeb70511b9c16181d5e168269e6", + "zh:81a7f2efc30e698f476d3e240ee2d82f14eda374852059429fe808ad77b6addd", + "zh:826d4ea55b4afceefb332646f21c6b6dc590b39b16e8d9b5d4a4211beb91dc5e", + "zh:865600ef669fcdd4ae77515c3fd12565fab0f2a263fa2a6dae562f6fe68ed093", + "zh:8e933d1d10fd316e62340175667264f093e4d24457b63d5adf3c424cce22b495", + "zh:bf261924f7350074a355e5b9337f3a8054efb20d316e9085f2b5766dfb5126c4", + "zh:e28e67dcbd4bbd82798561baf86d3dd04f97e08bbf523dfb9f355564ef27d3d6", + "zh:f33cdd3117af8a15f33d375dbe398a5e558730cf6a7a145a479ab68e77572c12", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f913a0e0708391ccd26fc3458158cc1e10d68dc621bef3a1583328c61a77225d", + ] +} + +provider "registry.terraform.io/hashicorp/tfe" { + version = "0.51.1" + hashes = [ + "h1:n7O1yooxtUk1G0T0jyrt5ItstX5fIPoSUqMibBHA6E0=", + "zh:08f5c2296a7eba39fb3b86cc9f294ac7a9ca06eee1dec44fbf14615523fd24d0", + "zh:46ea31b9ca5450d947c0b28b698aca6df97714e671f25a2e2c9ea3ba0e0d45a0", + "zh:6326962e8afda2da9c2724a465eee4ae12c514700ccfaead7be81c73d6d7f8cd", + "zh:649639793e0cbfe8732377052110441ae24b4a3b2e35126aab5d0b9da291ac9a", + "zh:8ca07718347273bbbc8a7c0f488da22efa38a67ec05b6db3bf97d01d9ba600c0", + "zh:a9065ad79c7a3d91ee1f7021edea02f92ace116830fa0857580dcd267643a016", + "zh:bc6014f7597b281ca9aa73fe91c9060f29311096a543c2cf794803920662edc4", + "zh:c48897ce5820983c1a94b6912317fbf4927b4eca9f550c7d5e1af40a4bc9fd5f", + "zh:ca32cc1543d65a1e418eaadccd0f00d6a626ff0b40d495e508b444d95b290ed0", + "zh:d179e1f38f789ebefb4cfce8148181999bd2e24f860b2e18cdaeca2b37fbe7f6", + "zh:d95ec293fa70e946b6cd657912b33155f8be3413e6128ed2bfa5a493f788e439", + "zh:fe9538fc1da16bbd675f33176ac3d2a20c264b5c7a14389c552a889f7a1c46e4", + ] +} diff --git a/infra/server-test/database.tf b/infra/server-test/database.tf new file mode 100644 index 00000000..4686774f --- /dev/null +++ b/infra/server-test/database.tf @@ -0,0 +1,12 @@ +# Google CLoud SQL Database. +# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database + +data "tfe_outputs" "core" { + organization = var.tfe_organization + workspace = "core" +} + +resource "google_sql_database" "db" { + name = var.db_name + instance = data.tfe_outputs.core.values.db_instance_name +} diff --git a/infra/server-test/providers.tf b/infra/server-test/providers.tf new file mode 100644 index 00000000..c5a0b45b --- /dev/null +++ b/infra/server-test/providers.tf @@ -0,0 +1,8 @@ +# Provider Configuration +# https://developer.hashicorp.com/terraform/language/providers/configuration + +provider "google" { + project = var.gcp_project + region = var.gcp_region + zone = var.gcp_zone +} diff --git a/infra/server-test/terraform.tf b/infra/server-test/terraform.tf new file mode 100644 index 00000000..07fd7b89 --- /dev/null +++ b/infra/server-test/terraform.tf @@ -0,0 +1,20 @@ +# Terraform Cloud configuration for the core (shared) workspace +# https://developer.hashicorp.com/terraform/cli/cloud/settings + +terraform { + cloud { + organization = "example" + + workspaces { + project = "default" + name = "server-test" + } + } + + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.14.0" + } + } +} diff --git a/infra/server-test/variables.tf b/infra/server-test/variables.tf new file mode 100644 index 00000000..e74524f3 --- /dev/null +++ b/infra/server-test/variables.tf @@ -0,0 +1,32 @@ +# Input Variables +# https://developer.hashicorp.com/terraform/language/values/variables + +variable "tfe_organization" { + type = string + description = "Terraform Cloud organization ID" + default = "example" +} + +variable "gcp_project" { + type = string + description = "Google Cloud Project ID" + default = "example" +} + +variable "gcp_region" { + type = string + description = "Google Cloud region" + default = "us-central1" +} + +variable "gcp_zone" { + type = string + description = "Google Cloud zone" + default = "us-central1-c" +} + +variable "db_name" { + type = string + description = "Database name" + default = "example-test" +} diff --git a/infra/services.tf b/infra/services.tf deleted file mode 100644 index b511d72e..00000000 --- a/infra/services.tf +++ /dev/null @@ -1,23 +0,0 @@ -# Google Cloud Service APIs -# https://registry.terraform.io/modules/terraform-google-modules/project-factory/google/latest/submodules/project_services - -module "project-services" { - source = "terraform-google-modules/project-factory/google//modules/project_services" - version = "~> 11.3" - - project_id = var.project - - activate_apis = [ - "artifactregistry.googleapis.com", - "cloudfunctions.googleapis.com", - "cloudbuild.googleapis.com", - "eventarc.googleapis.com", - "run.googleapis.com", - "logging.googleapis.com", - "pubsub.googleapis.com" - ] - - enable_apis = true - disable_dependent_services = false - disable_services_on_destroy = false -} diff --git a/infra/storage.tf b/infra/storage.tf deleted file mode 100644 index f0b634fa..00000000 --- a/infra/storage.tf +++ /dev/null @@ -1,41 +0,0 @@ -// Google Cloud Storage -// https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket - -resource "google_storage_bucket" "storage" { - name = var.storage_bucket - location = "US" - force_destroy = false - - uniform_bucket_level_access = false -} - - -resource "google_storage_bucket" "upload" { - name = var.upload_bucket - location = "US-CENTRAL1" - force_destroy = false - - uniform_bucket_level_access = true - - cors { - max_age_seconds = 3600 - method = ["GET", "HEAD", "PUT", "OPTIONS"] - origin = ["*"] - response_header = ["Content-Type", "Access-Control-Allow-Origin"] - } - - retention_policy { - is_locked = false - retention_period = 86400 - } -} - -resource "google_storage_bucket" "cache" { - name = var.cache_bucket - location = "US-CENTRAL1" - force_destroy = false - - uniform_bucket_level_access = true - - timeouts {} -} diff --git a/infra/variables.tf b/infra/variables.tf deleted file mode 100644 index eca387be..00000000 --- a/infra/variables.tf +++ /dev/null @@ -1,47 +0,0 @@ -# Input Variables -# https://www.terraform.io/language/values/variables - -variable "project" { - description = "The GCP project name" -} - -variable "region" { - description = "The GCP region" -} - -variable "zone" { - description = "The GCP zone" -} - -variable "cloudflare_account_id" { - description = "Cloudflare Account ID" -} - -variable "cloudflare_zone_id" { - description = "Cloudflare Zone ID" -} - -variable "cloudflare_api_token" { - description = "Cloudflare API Token" - sensitive = true -} - -variable "database" { - description = "The database name" -} - -variable "database_password" { - description = "The root user password" -} - -variable "storage_bucket" { - description = "The name of the main storage bucket" -} - -variable "upload_bucket" { - description = "The name of the upload bucket" -} - -variable "cache_bucket" { - description = "The name of the cache bucket" -} diff --git a/scripts/tf.js b/scripts/tf.js deleted file mode 100644 index 1cf93229..00000000 --- a/scripts/tf.js +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-FileCopyrightText: 2014-present Kriasoft */ -/* SPDX-License-Identifier: MIT */ - -import chalk from "chalk"; -import spawn from "cross-spawn"; -import envars from "envars"; -import fs from "node:fs"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -// Load environment variables for the target Terraform workspace -// (GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_REGION, etc) -const TF_WORKSPACE = process.env.TF_WORKSPACE ?? "test"; -const envName = TF_WORKSPACE === "prod" ? "prod" : "test"; -const env = envars.config({ env: envName }); - -const { bold, red, blue } = chalk; -const cwd = path.join(fileURLToPath(import.meta.url), "../.."); -const TF_DATA_DIR = path.join(cwd, ".terraform"); -const TF_CLI_CONFIG_FILE = path.join(cwd, ".terraformrc"); - -// Show a friendly error when Terraform CLI was not found -process.on("uncaughtException", (/** @type {NodeJS.ErrnoException} */ err) => { - if (err.code === "ENOENT") { - console.error( - [ - red("╷ "), - red("│ ") + bold(`${red("Error:")} Terraform CLI not found`), - red("│ "), - red("│ ") + `For more information visit:`, - red("│ ") + - blue(`https://learn.hashicorp.com/tutorials/terraform/install-cli`), - red("╵ "), - ].join("\n"), - ); - process.exitCode = 1; - } else { - throw err; - } -}); - -// Create `.terraformrc` and `override.tf` files if don't exist -if (!fs.existsSync(TF_CLI_CONFIG_FILE)) { - fs.writeFileSync( - TF_CLI_CONFIG_FILE, - [ - `# Terraform Cloud Credentials`, - `# https://app.terraform.io/app/settings/tokens`, - ``, - `credentials "app.terraform.io" {`, - ` token = "xxxxxx.atlasv1.zzzzzzzzzzzzz"`, - `}`, - ].join("\n"), - "utf-8", - ); - - if (!fs.existsSync(path.join(cwd, "infra/override.tf"))) { - fs.writeFileSync( - path.join(cwd, "infra/override.tf"), - [ - `# Terraform Configuration Overrides`, - `# https://www.terraform.io/language/files/override`, - ``, - ].join("\n"), - "utf-8", - ); - } -} - -const args = process.argv.slice(2); - -// See `infra/variables.tf` -// https://www.terraform.io/language/values/variables -if (["plan", "apply", "import"].includes(args[0])) { - fs.writeFileSync( - path.join(cwd, "infra/.auto.tfvars.json"), - JSON.stringify( - { - project: env.GOOGLE_CLOUD_PROJECT, - region: env.GOOGLE_CLOUD_REGION, - zone: env.GOOGLE_CLOUD_ZONE, - cloudflare_account_id: env.CLOUDFLARE_ACCOUNT_ID, - cloudflare_zone_id: env.CLOUDFLARE_ZONE_ID, - cloudflare_api_token: env.CLOUDFLARE_API_TOKEN, - database: env.PGDATABASE, - database_password: env.PGPASSWORD, - storage_bucket: env.STORAGE_BUCKET, - upload_bucket: env.UPLOAD_BUCKET, - cache_bucket: env.CACHE_BUCKET, - }, - null, - " ", - ), - "utf-8", - ); -} - -// Use `/infra` as the root directory -if (args[0]?.match(/^[a-z]/)) { - args.splice(0, 0, `-chdir=infra`); -} - -// Spawn a Terraform CLI process -spawn("terraform", args, { - cwd, - // https://www.terraform.io/cli/config/environment-variables - env: { ...process.env, TF_DATA_DIR, TF_CLI_CONFIG_FILE, TF_WORKSPACE }, - stdio: "inherit", -}).on("exit", function (code) { - if (code) process.exitCode = code; -}); diff --git a/tsconfig.json b/tsconfig.json index dea021b6..58004d3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,8 @@ { "files": [], - "references": [{ "path": "./app" }, { "path": "./server" }], + "references": [ + { "path": "./app" }, + { "path": "./db" }, + { "path": "./server" }, + ], }