From c00b14be387ce01b396c74b04128b711f6ad8c05 Mon Sep 17 00:00:00 2001 From: Ian Howell Date: Fri, 10 Jan 2025 10:44:54 +0000 Subject: [PATCH] Import search-api-v2 TFC workspace creation code from search-v2-infrastructure --- .../modules/search-api-v2/README.md | 9 + .../modules/search-api-v2/main.tf | 117 +++++++++++ .../modules/search-api-v2/variables.tf | 44 +++++ .../tfc-configuration/search-api-v2.tf | 181 ++++++++++++++++++ 4 files changed, 351 insertions(+) create mode 100644 terraform/deployments/tfc-configuration/modules/search-api-v2/README.md create mode 100644 terraform/deployments/tfc-configuration/modules/search-api-v2/main.tf create mode 100644 terraform/deployments/tfc-configuration/modules/search-api-v2/variables.tf create mode 100644 terraform/deployments/tfc-configuration/search-api-v2.tf diff --git a/terraform/deployments/tfc-configuration/modules/search-api-v2/README.md b/terraform/deployments/tfc-configuration/modules/search-api-v2/README.md new file mode 100644 index 000000000..603b40b4c --- /dev/null +++ b/terraform/deployments/tfc-configuration/modules/search-api-v2/README.md @@ -0,0 +1,9 @@ +# Search API V2 Terraform Cloud Module + +This module has been migrated into this repo from `search-v2-infrastructure/terraform/meta/modules/environment` as part of a project to bring it in line with current standard practices for infrastructure. It is called from `govuk-infrastructure/terraform/deployments/tfc-configuration/search-api-v2.tf` to create the following workspaces in Terraform Cloud: + +- search-api-v2-integration +- search-api-v2-staging +- search-api-v2-production + +The original module created resources for GCP as well as TFC, so a decision was made to split them out to conform more closely with standard practices, and to have them created separately. As all the resources already existed, import blocks have been used in `search-api-v2.tf` so that the infrastructure did not get duplicated. In it's old format, any updates had to be run manually from a laptop so the main benefit of this migration is that changes to this code should now get applied automatically. diff --git a/terraform/deployments/tfc-configuration/modules/search-api-v2/main.tf b/terraform/deployments/tfc-configuration/modules/search-api-v2/main.tf new file mode 100644 index 000000000..67a219450 --- /dev/null +++ b/terraform/deployments/tfc-configuration/modules/search-api-v2/main.tf @@ -0,0 +1,117 @@ +locals { + display_name = title(var.name) +} + +data "tfe_oauth_client" "github" { + organization = var.tfc_organization_name + service_provider = "github" +} + +resource "tfe_workspace" "environment_workspace" { + name = "search-api-v2-${var.name}" + project_id = var.tfc_project.id + description = "Provisions search-api-v2 Discovery Engine resources for the ${local.display_name} environment" + tag_names = ["govuk", "search-api-v2", "search-api-v2-environment", var.name] + + source_name = "search-v2-infrastructure meta module" + source_url = "https://github.com/alphagov/search-v2-infrastructure/tree/main/terraform/meta" + + working_directory = "terraform/deployments/search-api-v2" + terraform_version = "~> 1.7.5" + + # Only auto apply if there is no workspace defined that we need to wait for (in which case a + # trigger will determine when to apply this workspace) + auto_apply = var.upstream_environment_name == null + auto_apply_run_trigger = var.upstream_environment_name != null + + file_triggers_enabled = true + trigger_patterns = [ + "/terraform/deployments/search-api-v2/**/*.tf", + "/terraform/deployments/search-api-v2/**/files/**/*", + ] + + vcs_repo { + identifier = "alphagov/govuk-infrastructure" + branch = "main" + oauth_token_id = data.tfe_oauth_client.github.oauth_token_id + } +} + +resource "tfe_workspace_settings" "environment_workspace_settings" { + workspace_id = tfe_workspace.environment_workspace.id + + execution_mode = "remote" +} + +# Only relevant for the run trigger, if we have an upstream workspace to wait for +data "tfe_workspace" "upstream_workspace" { + count = var.upstream_environment_name != null ? 1 : 0 + + name = "search-api-v2-${var.upstream_environment_name}" +} + +resource "tfe_run_trigger" "apply_after_upstream_workspace" { + count = length(data.tfe_workspace.upstream_workspace) + + workspace_id = tfe_workspace.environment_workspace.id + sourceable_id = data.tfe_workspace.upstream_workspace[0].id +} + +data "tfe_variable_set" "aws_credentials" { + name = "aws-credentials-${var.name}" +} + +resource "tfe_workspace_variable_set" "aws_workspace_credentials" { + variable_set_id = data.tfe_variable_set.aws_credentials.id + workspace_id = tfe_workspace.environment_workspace.id +} + +resource "tfe_variable" "gcp_project_id" { + workspace_id = tfe_workspace.environment_workspace.id + category = "terraform" + description = "The GCP project ID for the ${local.display_name} environment" + + key = "gcp_project_id" + value = var.google_project_id + sensitive = false +} + +resource "tfe_variable" "gcp_project_number" { + workspace_id = tfe_workspace.environment_workspace.id + category = "terraform" + description = "The GCP project number for the ${local.display_name} environment" + + key = "gcp_project_number" + value = var.google_project_number + sensitive = false +} + +resource "tfe_variable" "enable_gcp_provider_auth" { + workspace_id = tfe_workspace.environment_workspace.id + + key = "TFC_GCP_PROVIDER_AUTH" + value = "true" + category = "env" + + description = "Enable Workload Identity Federation on GCP" +} + +resource "tfe_variable" "tfc_gcp_workload_provider_name" { + workspace_id = tfe_workspace.environment_workspace.id + + key = "TFC_GCP_WORKLOAD_PROVIDER_NAME" + value = var.google_workload_provider_name + category = "env" + + description = "The workload provider name to authenticate against on GCP" +} + +resource "tfe_variable" "tfc_gcp_service_account_email" { + workspace_id = tfe_workspace.environment_workspace.id + + key = "TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL" + value = var.google_service_account_email + category = "env" + + description = "The GCP service account email runs will use to authenticate" +} diff --git a/terraform/deployments/tfc-configuration/modules/search-api-v2/variables.tf b/terraform/deployments/tfc-configuration/modules/search-api-v2/variables.tf new file mode 100644 index 000000000..b5eca4f6f --- /dev/null +++ b/terraform/deployments/tfc-configuration/modules/search-api-v2/variables.tf @@ -0,0 +1,44 @@ +variable "name" { + type = string + description = "A short name for this environment (used in resource IDs)" +} + +variable "tfc_project" { + type = object({ + id = string + name = string + }) + description = "The Terraform Cloud/Enterprise project to create workspaces under" +} + +variable "upstream_environment_name" { + type = string + description = "The name of the upstream environment, if any (used to wait for a successful apply on a 'lower' environment before applying this one)" + default = null +} + +variable "tfc_organization_name" { + type = string + description = "The name of the Terraform Cloud/Enterprise organization to use" + default = "govuk" +} + +variable "google_project_id" { + description = "The GCP project ID for the environment" + type = string +} + +variable "google_project_number" { + description = "The GCP project number for the environment" + type = string +} + +variable "google_workload_provider_name" { + description = "The workload provider name to authenticate against on GCP" + type = string +} + +variable "google_service_account_email" { + description = "The GCP service account email runs will use to authenticate" + type = string +} diff --git a/terraform/deployments/tfc-configuration/search-api-v2.tf b/terraform/deployments/tfc-configuration/search-api-v2.tf new file mode 100644 index 000000000..bcae41165 --- /dev/null +++ b/terraform/deployments/tfc-configuration/search-api-v2.tf @@ -0,0 +1,181 @@ +# Import resource tfe_project.project from search-v2-infrastructure/terraform/meta/main.tf + +import { + to = tfe_project.project + id = "prj-yufbkwoTkNMxibBF" +} + +resource "tfe_project" "project" { + name = "govuk-search-api-v2" +} + +# Start of importing of all integration module components: +import { + to = module.environment_integration.tfe_workspace.environment_workspace + id = "ws-W1w2WqqJTUgUANQk" +} + +import { + to = module.environment_integration.tfe_workspace_settings.environment_workspace_settings + id = "ws-W1w2WqqJTUgUANQk" +} + +import { + to = module.environment_integration.tfe_variable.gcp_project_id + id = "govuk/search-api-v2-integration/var-qjn2CZNVCi3TfsNK" +} + +import { + to = module.environment_integration.tfe_variable.gcp_project_number + id = "govuk/search-api-v2-integration/var-6DsTGzoksKdz2JYa" +} + +import { + to = module.environment_integration.tfe_variable.tfc_gcp_workload_provider_name + id = "govuk/search-api-v2-integration/var-vuG2JaRMjM5dKt7E" +} + +import { + to = module.environment_integration.tfe_variable.tfc_gcp_service_account_email + id = "govuk/search-api-v2-integration/var-h5BGU7G7p1bZGc6h" +} + +import { + to = module.environment_integration.tfe_variable.enable_gcp_provider_auth + id = "govuk/search-api-v2-integration/var-bDjR8sGVpSHABWDL" +} + +import { + to = module.environment_integration.tfe_workspace_variable_set.aws_workspace_credentials + id = "govuk/search-api-v2-integration/aws-credentials-integration" +} + +# Main integration module +module "environment_integration" { + source = "./modules/search-api-v2" + + name = "integration" + google_project_id = "search-api-v2-integration" + google_project_number = "780375417592" + google_workload_provider_name = "projects/780375417592/locations/global/workloadIdentityPools/terraform-cloud-id-pool/providers/terraform-cloud-provider-oidc" + google_service_account_email = "tfc-service-account@search-api-v2-integration.iam.gserviceaccount.com" + tfc_project = tfe_project.project +} + +# Start of importing of all staging module components: +import { + to = module.environment_staging.tfe_workspace.environment_workspace + id = "ws-2DJbN6rFF1GiQ2s7" +} + +import { + to = module.environment_staging.tfe_workspace_settings.environment_workspace_settings + id = "ws-2DJbN6rFF1GiQ2s7" +} + +import { + to = module.environment_staging.tfe_variable.gcp_project_id + id = "govuk/search-api-v2-staging/var-ZmvL1uXqHArMxPw3" +} + +import { + to = module.environment_staging.tfe_variable.gcp_project_number + id = "govuk/search-api-v2-staging/var-aetSjjum4DHzhGmu" +} + +import { + to = module.environment_staging.tfe_variable.tfc_gcp_workload_provider_name + id = "govuk/search-api-v2-staging/var-UfY6Uy72VEXPo2rs" +} + +import { + to = module.environment_staging.tfe_variable.tfc_gcp_service_account_email + id = "govuk/search-api-v2-staging/var-XMYzyrTAGcp5utGo" +} + +import { + to = module.environment_staging.tfe_variable.enable_gcp_provider_auth + id = "govuk/search-api-v2-staging/var-t39cxvLdqxU5m9sK" +} + +import { + to = module.environment_staging.tfe_workspace_variable_set.aws_workspace_credentials + id = "govuk/search-api-v2-staging/aws-credentials-staging" +} + +import { + to = module.environment_staging.tfe_run_trigger.apply_after_upstream_workspace[0] + id = "rt-MrZrhrnX5Ui29A49" +} + +# Main staging module +module "environment_staging" { + source = "./modules/search-api-v2" + + name = "staging" + upstream_environment_name = "integration" + google_project_id = "search-api-v2-staging" + google_project_number = "773027887517" + google_workload_provider_name = "projects/773027887517/locations/global/workloadIdentityPools/terraform-cloud-id-pool/providers/terraform-cloud-provider-oidc" + google_service_account_email = "tfc-service-account@search-api-v2-staging.iam.gserviceaccount.com" + tfc_project = tfe_project.project +} + +# Start of importing of all production module components: +import { + to = module.environment_production.tfe_workspace.environment_workspace + id = "ws-7Asw8cAriLJZoBd7" +} + +import { + to = module.environment_production.tfe_workspace_settings.environment_workspace_settings + id = "ws-7Asw8cAriLJZoBd7" +} + +import { + to = module.environment_production.tfe_variable.gcp_project_id + id = "govuk/search-api-v2-production/var-YwH1fj9uqGThY3cN" +} + +import { + to = module.environment_production.tfe_variable.gcp_project_number + id = "govuk/search-api-v2-production/var-WZx1xngdtrtxGBWF" +} + +import { + to = module.environment_production.tfe_variable.tfc_gcp_workload_provider_name + id = "govuk/search-api-v2-production/var-LZURSLZMqbRtT7nU" +} + +import { + to = module.environment_production.tfe_variable.tfc_gcp_service_account_email + id = "govuk/search-api-v2-production/var-z1PcdEQR4rKccKb9" +} + +import { + to = module.environment_production.tfe_variable.enable_gcp_provider_auth + id = "govuk/search-api-v2-production/var-fQVEseaF1ByPjLDJ" +} + +import { + to = module.environment_production.tfe_workspace_variable_set.aws_workspace_credentials + id = "govuk/search-api-v2-production/aws-credentials-production" +} + +import { + to = module.environment_production.tfe_run_trigger.apply_after_upstream_workspace[0] + id = "rt-uR7ws5qAzQovR8v1" +} + +# Main production module +module "environment_production" { + source = "./modules/search-api-v2" + + name = "production" + upstream_environment_name = "staging" + google_project_id = "search-api-v2-production" + google_project_number = "931453572747" + google_workload_provider_name = "projects/931453572747/locations/global/workloadIdentityPools/terraform-cloud-id-pool/providers/terraform-cloud-provider-oidc" + google_service_account_email = "tfc-service-account@search-api-v2-production.iam.gserviceaccount.com" + tfc_project = tfe_project.project +}