From 8447f7e5ace9b6a68e5840ed3fb40fa50cd4abc7 Mon Sep 17 00:00:00 2001 From: Andrew Peabody Date: Tue, 28 May 2024 19:16:28 +0000 Subject: [PATCH] feat(appinfra): configurable envs --- .../accounts-contacts/envs/shared/main.tf | 8 +- .../envs/shared/variables.tf | 18 +-- .../accounts-userservice/envs/shared/main.tf | 8 +- .../envs/shared/variables.tf | 18 +-- .../cymbal-bank/frontend/envs/shared/main.tf | 8 +- .../frontend/envs/shared/variables.tf | 18 +-- .../ledger-balancereader/envs/shared/main.tf | 8 +- .../envs/shared/variables.tf | 18 +-- .../ledger-ledgerwriter/envs/shared/main.tf | 8 +- .../envs/shared/variables.tf | 18 +-- .../envs/shared/main.tf | 8 +- .../envs/shared/variables.tf | 18 +-- 5-appinfra/modules/cicd-pipeline/README.md | 4 +- .../cicd-pipeline/artifact-registry.tf | 2 +- .../modules/cicd-pipeline/cloud-deploy.tf | 6 +- 5-appinfra/modules/cicd-pipeline/locals.tf | 1 - 5-appinfra/modules/cicd-pipeline/pipelines.tf | 105 ++++-------------- .../cicd-pipeline/project-iam-bindings.tf | 6 +- 5-appinfra/modules/cicd-pipeline/variables.tf | 18 +-- test/integration/appinfra/appinfra_test.go | 42 +++---- .../integration/appsource/cymbal_bank_test.go | 20 ++-- 21 files changed, 110 insertions(+), 250 deletions(-) diff --git a/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/main.tf index 8c391e6a..8556d373 100644 --- a/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/accounts-contacts/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/main.tf index d47de591..fe28c731 100644 --- a/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/accounts-userservice/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/apps/cymbal-bank/frontend/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/frontend/envs/shared/main.tf index 91f32742..eb5aac8b 100644 --- a/5-appinfra/apps/cymbal-bank/frontend/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/frontend/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/frontend/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/frontend/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/frontend/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/frontend/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/main.tf index e2f0535a..6999a48b 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-balancereader/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/main.tf index 41bbe48d..eb4455b2 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-ledgerwriter/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/main.tf b/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/main.tf index 91983b39..553e2822 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/main.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/main.tf @@ -24,11 +24,9 @@ locals { module "app" { source = "../../../../../modules/cicd-pipeline" - project_id = var.project_id - region = var.region - cluster_membership_id_dev = var.cluster_membership_id_dev - cluster_membership_ids_nonprod = var.cluster_membership_ids_nonprod - cluster_membership_ids_prod = var.cluster_membership_ids_prod + project_id = var.project_id + region = var.region + env_cluster_membership_ids = var.env_cluster_membership_ids service = local.service_name repo_name = local.repo_name diff --git a/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/variables.tf b/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/variables.tf index e2264359..f07c41ae 100644 --- a/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/variables.tf +++ b/5-appinfra/apps/cymbal-bank/ledger-transactionhistory/envs/shared/variables.tf @@ -24,19 +24,11 @@ variable "region" { type = string } -variable "cluster_membership_id_dev" { - description = "Cluster fleet membership ID in development environment" - type = string -} - -variable "cluster_membership_ids_nonprod" { - description = "Cluster fleet membership IDs in nonprod environment" - type = list(string) -} - -variable "cluster_membership_ids_prod" { - description = "Cluster fleet membership IDs in prod environment" - type = list(string) +variable "env_cluster_membership_ids" { + description = "Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "buckets_force_destroy" { diff --git a/5-appinfra/modules/cicd-pipeline/README.md b/5-appinfra/modules/cicd-pipeline/README.md index 5d56f415..064a113b 100644 --- a/5-appinfra/modules/cicd-pipeline/README.md +++ b/5-appinfra/modules/cicd-pipeline/README.md @@ -6,9 +6,7 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | buckets\_force\_destroy | When deleting the bucket for storing CICD artifacts, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no | -| cluster\_membership\_id\_dev | Fleet membership ID for the cluster in development environment | `string` | n/a | yes | -| cluster\_membership\_ids\_nonprod | Fleet membership IDs for the cluster in non-production environment | `list(string)` | n/a | yes | -| cluster\_membership\_ids\_prod | Fleet membership IDs for the cluster in production environment | `list(string)` | n/a | yes | +| env\_cluster\_membership\_ids | Env Cluster Membership IDs |
map(object({
cluster_membership_ids = list(string)
}))
| n/a | yes | | project\_id | CI/CD project ID | `string` | n/a | yes | | region | CI/CD Region (e.g. us-central1) | `string` | n/a | yes | | repo\_branch | Branch to sync ACM configs from & trigger CICD if pushed to. | `string` | n/a | yes | diff --git a/5-appinfra/modules/cicd-pipeline/artifact-registry.tf b/5-appinfra/modules/cicd-pipeline/artifact-registry.tf index 086e4b37..b68ccd5d 100644 --- a/5-appinfra/modules/cicd-pipeline/artifact-registry.tf +++ b/5-appinfra/modules/cicd-pipeline/artifact-registry.tf @@ -17,7 +17,7 @@ resource "google_artifact_registry_repository" "container_registry" { repository_id = local.service_name location = var.region format = "docker" - description = "Bank of Anthos docker repository" + description = "${local.service_name} docker repository" project = var.project_id depends_on = [ diff --git a/5-appinfra/modules/cicd-pipeline/cloud-deploy.tf b/5-appinfra/modules/cicd-pipeline/cloud-deploy.tf index 46a2d177..ff16bcae 100644 --- a/5-appinfra/modules/cicd-pipeline/cloud-deploy.tf +++ b/5-appinfra/modules/cicd-pipeline/cloud-deploy.tf @@ -19,10 +19,10 @@ resource "google_clouddeploy_delivery_pipeline" "delivery-pipeline" { name = local.service_name serial_pipeline { dynamic "stages" { - for_each = { for idx, target in local.targets : idx => target } + for_each = google_clouddeploy_target.clouddeploy_targets content { - # TODO: use "production" profile once it works. - profiles = [stages.value.name == "${local.service_name}-dev" ? "development" : (startswith(stages.value.name, "${local.service_name}-nonprod") ? "staging" : "production")] + # TODO: use "production" profile once validated. + profiles = [endswith(stages.value.name, "-development") ? "development" : (endswith(stages.value.name, "-non-production") ? "staging" : "production")] target_id = stages.value.name } } diff --git a/5-appinfra/modules/cicd-pipeline/locals.tf b/5-appinfra/modules/cicd-pipeline/locals.tf index c718f54f..ca26028e 100644 --- a/5-appinfra/modules/cicd-pipeline/locals.tf +++ b/5-appinfra/modules/cicd-pipeline/locals.tf @@ -17,6 +17,5 @@ locals { service_name = reverse(split("-", var.service))[0] team_name = split("-", var.service)[0] service_clean = replace(var.service, "/", "-") - targets = [google_clouddeploy_target.development, google_clouddeploy_target.non_prod[0], google_clouddeploy_target.non_prod[1], google_clouddeploy_target.prod[0], google_clouddeploy_target.prod[1]] container_registry = google_artifact_registry_repository.container_registry } diff --git a/5-appinfra/modules/cicd-pipeline/pipelines.tf b/5-appinfra/modules/cicd-pipeline/pipelines.tf index 06d1777f..7c650dc0 100644 --- a/5-appinfra/modules/cicd-pipeline/pipelines.tf +++ b/5-appinfra/modules/cicd-pipeline/pipelines.tf @@ -26,50 +26,16 @@ resource "google_service_account" "cloud_deploy" { create_ignore_already_exists = true } -resource "google_clouddeploy_target" "development" { - # one CloudDeploy target per target defined in vars +resource "google_clouddeploy_target" "clouddeploy_targets" { + # one CloudDeploy target per cluster_membership_id defined in vars + for_each = merge([ + for key, value in var.env_cluster_membership_ids : { + for item in value.cluster_membership_ids : "${key}/${item}" => item + } + ]...) project = var.project_id - name = "${local.service_name}-dev" - location = var.region - - anthos_cluster { - membership = regex(local.fleet_membership_re, var.cluster_membership_id_dev)[0] - } - - execution_configs { - artifact_storage = "gs://${google_storage_bucket.delivery_artifacts_development.name}" - service_account = google_service_account.cloud_deploy.email - usages = [ - "RENDER", - "DEPLOY" - ] - } -} - -# GCS bucket used by Cloud Deploy for delivery artifact storage -resource "google_storage_bucket" "delivery_artifacts_development" { - project = var.project_id - name = "delivery-artifacts-development-${data.google_project.project.number}-${local.service_name}" - uniform_bucket_level_access = true - location = var.region - force_destroy = var.buckets_force_destroy -} - -# give CloudDeploy SA access to administrate to delivery artifact bucket -resource "google_storage_bucket_iam_member" "delivery_artifacts_development" { - bucket = google_storage_bucket.delivery_artifacts_development.name - - member = "serviceAccount:${google_service_account.cloud_deploy.email}" - role = "roles/storage.admin" -} - -resource "google_clouddeploy_target" "non_prod" { - # one CloudDeploy target per target defined in vars - for_each = { for i, v in var.cluster_membership_ids_nonprod : i => v } - - project = var.project_id - name = "${local.service_name}-nonprod-${each.key}" + name = trimprefix(regex(local.membership_re, each.value)[2], "cluster-") location = var.region anthos_cluster { @@ -77,66 +43,33 @@ resource "google_clouddeploy_target" "non_prod" { } execution_configs { - artifact_storage = "gs://${google_storage_bucket.delivery_artifacts_non_prod.name}" + artifact_storage = "gs://${google_storage_bucket.delivery_artifacts[split("/", each.key)[0]].name}" service_account = google_service_account.cloud_deploy.email usages = [ "RENDER", "DEPLOY" ] } -} - -# GCS bucket used by Cloud Deploy for delivery artifact storage -resource "google_storage_bucket" "delivery_artifacts_non_prod" { - project = var.project_id - name = "delivery-artifacts-non-prod-${data.google_project.project.number}-${local.service_name}" - uniform_bucket_level_access = true - location = var.region - force_destroy = var.buckets_force_destroy -} - -# give CloudDeploy SA access to administrate to delivery artifact bucket -resource "google_storage_bucket_iam_member" "delivery_artifacts_non_prod" { - bucket = google_storage_bucket.delivery_artifacts_non_prod.name - - member = "serviceAccount:${google_service_account.cloud_deploy.email}" - role = "roles/storage.admin" -} - -resource "google_clouddeploy_target" "prod" { - # one CloudDeploy target per target defined in vars - for_each = { for i, v in var.cluster_membership_ids_prod : i => v } - - project = var.project_id - name = "${local.service_name}-prod-${each.key}" - location = var.region - - anthos_cluster { - membership = regex(local.fleet_membership_re, each.value)[0] - } - execution_configs { - artifact_storage = "gs://${google_storage_bucket.delivery_artifacts_prod.name}" - service_account = google_service_account.cloud_deploy.email - usages = [ - "RENDER", - "DEPLOY" - ] - } + depends_on = [google_storage_bucket.delivery_artifacts] } # GCS bucket used by Cloud Deploy for delivery artifact storage -resource "google_storage_bucket" "delivery_artifacts_prod" { +resource "google_storage_bucket" "delivery_artifacts" { + for_each = var.env_cluster_membership_ids + project = var.project_id - name = "delivery-artifacts-prod-${data.google_project.project.number}-${local.service_name}" + name = "artifacts-${each.key}-${data.google_project.project.number}-${local.service_name}" uniform_bucket_level_access = true - location = var.region + location = regex(local.membership_re, each.value.cluster_membership_ids[0])[1] force_destroy = var.buckets_force_destroy } # give CloudDeploy SA access to administrate to delivery artifact bucket -resource "google_storage_bucket_iam_member" "delivery_artifacts_prod" { - bucket = google_storage_bucket.delivery_artifacts_prod.name +resource "google_storage_bucket_iam_member" "delivery_artifacts" { + for_each = var.env_cluster_membership_ids + + bucket = google_storage_bucket.delivery_artifacts[each.key].name member = "serviceAccount:${google_service_account.cloud_deploy.email}" role = "roles/storage.admin" diff --git a/5-appinfra/modules/cicd-pipeline/project-iam-bindings.tf b/5-appinfra/modules/cicd-pipeline/project-iam-bindings.tf index 76892c06..af422f25 100644 --- a/5-appinfra/modules/cicd-pipeline/project-iam-bindings.tf +++ b/5-appinfra/modules/cicd-pipeline/project-iam-bindings.tf @@ -15,7 +15,11 @@ locals { cloud_build_sas = ["serviceAccount:${google_service_account.cloud_build.email}"] # cloud build service accounts used for CI membership_re = "projects/([^/]*)/locations/([^/]*)/memberships/([^/]*)$" - gke_projects = [regex(local.membership_re, var.cluster_membership_id_dev)[0], regex(local.membership_re, var.cluster_membership_ids_nonprod[0])[0], regex(local.membership_re, var.cluster_membership_ids_prod[0])[0]] + gke_projects = distinct(flatten([ + for _, value in var.env_cluster_membership_ids : [ + for item in value.cluster_membership_ids : regex(local.membership_re, item)[0] + ] + ])) } # authoritative project-iam-bindings to increase reproducibility diff --git a/5-appinfra/modules/cicd-pipeline/variables.tf b/5-appinfra/modules/cicd-pipeline/variables.tf index b9c21b65..4f177c35 100644 --- a/5-appinfra/modules/cicd-pipeline/variables.tf +++ b/5-appinfra/modules/cicd-pipeline/variables.tf @@ -22,19 +22,11 @@ variable "region" { description = "CI/CD Region (e.g. us-central1)" } -variable "cluster_membership_id_dev" { - type = string - description = "Fleet membership ID for the cluster in development environment" -} - -variable "cluster_membership_ids_nonprod" { - type = list(string) - description = "Fleet membership IDs for the cluster in non-production environment" -} - -variable "cluster_membership_ids_prod" { - type = list(string) - description = "Fleet membership IDs for the cluster in production environment" +variable "env_cluster_membership_ids" { + description = "Env Cluster Membership IDs" + type = map(object({ + cluster_membership_ids = list(string) + })) } variable "service" { diff --git a/test/integration/appinfra/appinfra_test.go b/test/integration/appinfra/appinfra_test.go index 5d18db61..248c8c0e 100644 --- a/test/integration/appinfra/appinfra_test.go +++ b/test/integration/appinfra/appinfra_test.go @@ -30,9 +30,12 @@ import ( // TOOD: Update to a single parallel TestAppInfra test // https://github.com/GoogleCloudPlatform/terraform-google-enterprise-application/pull/107 func TestAppInfra(t *testing.T) { - multitenant := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/development")) - multitenant_nonprod := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/non-production")) - multitenant_prod := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/production")) + env_cluster_membership_ids := make(map[string]map[string][]string, 0) + for _, envName := range testutils.EnvNames { + env_cluster_membership_ids[envName] = make(map[string][]string, 0) + multitenant := tft.NewTFBlueprintTest(t, tft.WithTFDir(fmt.Sprintf("../../../2-multitenant/envs/%s", envName))) + env_cluster_membership_ids[envName]["cluster_membership_ids"] = testutils.GetBptOutputStrSlice(multitenant, "cluster_membership_ids") + } type ServiceInfos struct { ApplicationName string @@ -46,7 +49,7 @@ func TestAppInfra(t *testing.T) { splitServiceName []string ) servicesInfoMap := make(map[string]ServiceInfos) - region := testutils.GetBptOutputStrSlice(multitenant, "cluster_regions")[0] + region := "us-central1" // TODO: Move to terraform.tfvars? for appName, serviceNames := range testutils.ServicesNames { appName := appName @@ -72,9 +75,7 @@ func TestAppInfra(t *testing.T) { vars := map[string]interface{}{ "project_id": servicesInfoMap[fullServiceName].ProjectID, "region": region, - "cluster_membership_id_dev": testutils.GetBptOutputStrSlice(multitenant, "cluster_membership_ids")[0], - "cluster_membership_ids_nonprod": testutils.GetBptOutputStrSlice(multitenant_nonprod, "cluster_membership_ids"), - "cluster_membership_ids_prod": testutils.GetBptOutputStrSlice(multitenant_prod, "cluster_membership_ids"), + "env_cluster_membership_ids": env_cluster_membership_ids, "buckets_force_destroy": "true", } @@ -138,12 +139,6 @@ func TestAppInfra(t *testing.T) { fmt.Sprintf("release-source-development-%s-%s", servicesInfoMap[fullServiceName].ServiceName, projectNumber), } - pipelinebucketNames := []string{ - fmt.Sprintf("delivery-artifacts-development-%s-%s", projectNumber, servicesInfoMap[fullServiceName].ServiceName), - fmt.Sprintf("delivery-artifacts-non-prod-%s-%s", projectNumber, servicesInfoMap[fullServiceName].ServiceName), - fmt.Sprintf("delivery-artifacts-prod-%s-%s", projectNumber, servicesInfoMap[fullServiceName].ServiceName), - } - for _, bucketName := range cloudBuildBucketNames { bucketOp := gcloud.Runf(t, "storage buckets describe gs://%s --project %s", bucketName, servicesInfoMap[fullServiceName].ProjectID) assert.True(bucketOp.Get("uniform_bucket_level_access").Bool(), fmt.Sprintf("Bucket %s should have uniform access level.", bucketName)) @@ -157,7 +152,9 @@ func TestAppInfra(t *testing.T) { assert.Subset(bucketSaListMembers, []string{fmt.Sprintf("serviceAccount:%s", ciServiceAccountEmail)}, fmt.Sprintf("Bucket %s should have storage.admin role for SA %s.", bucketName, ciServiceAccountEmail)) } - for _, bucketName := range pipelinebucketNames { + for env := range env_cluster_membership_ids { + bucketName :=fmt.Sprintf("artifacts-%s-%s-%s", env, projectNumber, servicesInfoMap[fullServiceName].ServiceName) + bucketOp := gcloud.Runf(t, "storage buckets describe gs://%s --project %s", bucketName, servicesInfoMap[fullServiceName].ProjectID) assert.True(bucketOp.Get("uniform_bucket_level_access").Bool(), fmt.Sprintf("Bucket %s should have uniform access level.", bucketName)) assert.Equal(strings.ToUpper(region), bucketOp.Get("location").String(), fmt.Sprintf("Bucket should be at location %s", region)) @@ -225,19 +222,16 @@ func TestAppInfra(t *testing.T) { projectRoles = testutils.GetResultFieldStrSlice(filtered, "bindings.role") assert.Subset(projectRoles, cbSARoles, fmt.Sprintf("Service Account %s should have %v roles at project %s.", ciServiceAccountEmail, cbSARoles, servicesInfoMap[fullServiceName].ProjectID)) - cloudDeployTargets := []string{ - fmt.Sprintf("%s-dev", servicesInfoMap[fullServiceName].ServiceName), - } - for i := range testutils.GetBptOutputStrSlice(multitenant_nonprod, "cluster_membership_ids") { - cloudDeployTargets = append(cloudDeployTargets, fmt.Sprintf("%s-nonprod-%d", servicesInfoMap[fullServiceName].ServiceName, i)) - } - - for i := range testutils.GetBptOutputStrSlice(multitenant_prod, "cluster_membership_ids") { - cloudDeployTargets = append(cloudDeployTargets, fmt.Sprintf("%s-prod-%d", servicesInfoMap[fullServiceName].ServiceName, i)) + cloudDeployTargets := make([]string, 0) + for _, v := range env_cluster_membership_ids { + for _, cluster_membership_id := range v["cluster_membership_ids"] { + cluster_membership_id := strings.Split(cluster_membership_id, "/") + cloudDeployTargets = append(cloudDeployTargets, cluster_membership_id[len(cluster_membership_id)-1]) + } } for _, targetName := range cloudDeployTargets { - deployTargetOp := gcloud.Runf(t, "deploy targets describe %s --project %s --region %s --flatten Target", targetName, servicesInfoMap[fullServiceName].ProjectID, region).Array()[0] + deployTargetOp := gcloud.Runf(t, "deploy targets describe %s --project %s --region %s --flatten Target", strings.TrimPrefix(targetName, "cluster-"), servicesInfoMap[fullServiceName].ProjectID, region).Array()[0] assert.Equal(cloudDeployServiceAccountEmail, deployTargetOp.Get("executionConfigs").Array()[0].Get("serviceAccount").String(), fmt.Sprintf("cloud deploy target %s should have service account %s", targetName, cloudDeployServiceAccountEmail)) } diff --git a/test/integration/appsource/cymbal_bank_test.go b/test/integration/appsource/cymbal_bank_test.go index a71bacfe..1ce806b4 100644 --- a/test/integration/appsource/cymbal_bank_test.go +++ b/test/integration/appsource/cymbal_bank_test.go @@ -35,10 +35,12 @@ import ( func TestSourceCymbalBank(t *testing.T) { - // TODO: switch to an array based on ENVs - multitenant := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/development")) - multitenant_nonprod := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/non-production")) - multitenant_prod := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../../2-multitenant/envs/production")) + env_cluster_membership_ids := make(map[string]map[string][]string, 0) + for _, envName := range testutils.EnvNames { + env_cluster_membership_ids[envName] = make(map[string][]string, 0) + multitenant := tft.NewTFBlueprintTest(t, tft.WithTFDir(fmt.Sprintf("../../../2-multitenant/envs/%s", envName))) + env_cluster_membership_ids[envName]["cluster_membership_ids"] = testutils.GetBptOutputStrSlice(multitenant, "cluster_membership_ids") + } type ServiceInfos struct { ProjectID string @@ -50,7 +52,7 @@ func TestSourceCymbalBank(t *testing.T) { suffixServiceName string splitServiceName []string ) - region := testutils.GetBptOutputStrSlice(multitenant, "cluster_regions")[0] + region := "us-central1" // TODO: Plumb output from appInfra servicesInfoMap := make(map[string]ServiceInfos) for appName, serviceNames := range testutils.ServicesNames { @@ -81,14 +83,11 @@ func TestSourceCymbalBank(t *testing.T) { tmpDirApp := t.TempDir() dbFrom := fmt.Sprintf("%s/%s-db/k8s/overlays/development/%s-db.yaml", appSourcePath, servicesInfoMap[serviceName].TeamName, servicesInfoMap[serviceName].TeamName) dbTo := fmt.Sprintf("%s/src/%s/%s-db/k8s/overlays/development/%s-db.yaml", tmpDirApp, servicesInfoMap[serviceName].TeamName, servicesInfoMap[serviceName].TeamName, servicesInfoMap[serviceName].TeamName) - prodTarget := "dev" vars := map[string]interface{}{ "project_id": servicesInfoMap[serviceName].ProjectID, "region": region, - "cluster_membership_id_dev": testutils.GetBptOutputStrSlice(multitenant, "cluster_membership_ids")[0], - "cluster_membership_ids_nonprod": testutils.GetBptOutputStrSlice(multitenant_nonprod, "cluster_membership_ids"), - "cluster_membership_ids_prod": testutils.GetBptOutputStrSlice(multitenant_prod, "cluster_membership_ids"), + "env_cluster_membership_ids": env_cluster_membership_ids, "buckets_force_destroy": "true", } @@ -189,7 +188,8 @@ func TestSourceCymbalBank(t *testing.T) { t.Fatal("Failed to find the release.") } releaseName := releases[0].Get("name") - rolloutListCmd := fmt.Sprintf("deploy rollouts list --project=%s --delivery-pipeline=%s --region=%s --release=%s --filter targetId=%s-%s", servicesInfoMap[serviceName].ProjectID, servicesInfoMap[serviceName].ServiceName, region, releaseName, servicesInfoMap[serviceName].ServiceName, prodTarget) + targetId := "cluster-us-central1-development" //TODO: convert to loop using env_cluster_membership_ids + rolloutListCmd := fmt.Sprintf("deploy rollouts list --project=%s --delivery-pipeline=%s --region=%s --release=%s --filter targetId=%s", servicesInfoMap[serviceName].ProjectID, servicesInfoMap[serviceName].ServiceName, region, releaseName, targetId) // Poll CD rollouts until rollout is successful pollCloudDeploy := func(cmd string) func() (bool, error) { return func() (bool, error) {