From 999d74bc81800aecaadef44e339b4f5238d93398 Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Tue, 25 Jun 2024 13:42:57 +0200 Subject: [PATCH 1/6] adjust mission 3061 for QAS --- .../mission_3061/step1/main.tf | 36 +++++++- .../mission_3061/step1/outputs.tf | 81 ++++++++++++++++- .../mission_3061/step1/provider.tf | 6 +- .../mission_3061/step1/variables.tf | 88 ++++++++++++++++++- .../mission_3061/step2/main.tf | 3 +- .../mission_3061/step2/variables.tf | 11 ++- 6 files changed, 214 insertions(+), 11 deletions(-) diff --git a/released/discovery_center/mission_3061/step1/main.tf b/released/discovery_center/mission_3061/step1/main.tf index 6ed9739e..05c054c2 100644 --- a/released/discovery_center/mission_3061/step1/main.tf +++ b/released/discovery_center/mission_3061/step1/main.tf @@ -1,10 +1,13 @@ ### # Setup of names based on variables ### +resource "random_uuid" "uuid" {} + locals { - subaccount_name = "${var.subaccount_prefix}-${var.abap_sid}" - subaccount_domain = lower("${var.subaccount_prefix}-${var.abap_sid}") - subaccount_cf_org = "CF-${var.subaccount_prefix}-${var.abap_sid}" + random_uuid = random_uuid.uuid.result + subaccount_domain = lower("${var.subaccount_prefix}-${var.abap_sid}-${local.random_uuid}") + subaccount_name = var.subaccount_name != "" ? var.subaccount_name : "${var.subaccount_prefix}-${var.abap_sid}" + subaccount_cf_org = substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) } ### @@ -98,3 +101,30 @@ resource "btp_subaccount_trust_configuration" "subaccount_trust_abap" { subaccount_id = btp_subaccount.abap_subaccount.id identity_provider = var.custom_idp } + +resource "local_file" "output_vars_step1" { + count = var.create_tfvars_file_for_next_stage ? 1 : 0 + content = <<-EOT + origin = "${var.origin}" + + cf_api_url = "${jsondecode(btp_subaccount_environment_instance.cf_abap.labels)["API Endpoint"]}" + cf_org_id = "${btp_subaccount_environment_instance.cf_abap.platform_id}" + + cf_org_auditors = ${jsonencode(var.cf_org_auditors)} + cf_org_billing_managers = ${jsonencode(var.cf_org_billing_managers)} + cf_org_managers = ${jsonencode(var.cf_org_managers)} + cf_space_auditors = ${jsonencode(var.cf_space_auditors)} + cf_space_developers = ${jsonencode(var.cf_space_developers)} + cf_space_managers = ${jsonencode(var.cf_space_managers)} + + abap_sid = "${var.abap_sid}" + abap_si_plan = "${var.abap_si_plan}" + abap_compute_unit_quota = ${jsonencode(var.abap_compute_unit_quota)} + hana_compute_unit_quota = ${jsonencode(var.hana_compute_unit_quota)} + abap_admin_email = "${var.abap_admin_email}" + abap_admin = ${jsonencode(var.abap_admin)} + abap_is_development_allowed = ${var.abap_is_development_allowed} + + EOT + filename = "../step2/terraform.tfvars" +} diff --git a/released/discovery_center/mission_3061/step1/outputs.tf b/released/discovery_center/mission_3061/step1/outputs.tf index 04ba074d..f39c48c3 100644 --- a/released/discovery_center/mission_3061/step1/outputs.tf +++ b/released/discovery_center/mission_3061/step1/outputs.tf @@ -8,22 +8,97 @@ output "subaccount_name" { description = "The name of the subaccount." } -output "cloudfoundry_org_name" { +output "cf_org_name" { value = local.subaccount_cf_org description = "The name of the Cloud Foundry org connected to the subaccount." } -output "cloudfoundry_org_id" { +output "cf_org_id" { value = btp_subaccount_environment_instance.cf_abap.platform_id description = "The ID of the Cloud Foundry org connected to the subaccount." } -output "cloudfoundry_api_url" { +output "cf_api_url" { value = lookup(jsondecode(btp_subaccount_environment_instance.cf_abap.labels), "API Endpoint", "not found") description = "API endpoint of the Cloud Foundry environment." } +output "cf_landscape_label" { + value = btp_subaccount_environment_instance.cf_abap.landscape_label + description = "Landscape label of the Cloud Foundry environment." +} + +output "cf_space_name" { + value = var.cf_space_name + description = "The name of the Cloud Foundry space." +} + output "abap_sid" { value = var.abap_sid description = "SID of the ABAP system." +} + +output "abap_compute_unit_quota" { + value = var.abap_compute_unit_quota + description = "The amount of ABAP compute units to be assigned to the subaccount." +} + +output "hana_compute_unit_quota" { + value = var.hana_compute_unit_quota + description = "The amount of ABAP compute units to be assigned to the subaccount." +} + +output "origin" { + value = var.origin + description = "The identity provider for the UAA user." +} + +output "cf_org_managers" { + value = var.cf_org_managers + description = "List of Cloud Foundry org managers." +} + +output "cf_org_billing_managers" { + value = var.cf_org_billing_managers + description = "List of Cloud Foundry org billing managers." +} + +output "cf_org_auditors" { + value = var.cf_org_auditors + description = "List of Cloud Foundry org auditors." +} + +output "cf_space_managers" { + value = var.cf_space_managers + description = "List of managers for the Cloud Foundry space." +} + +output "cf_space_developers" { + value = var.cf_space_developers + description = "List of developers for the Cloud Foundry space." +} + +output "cf_space_auditors" { + value = var.cf_space_auditors + description = "The list of Cloud Foundry space auditors." +} + +output "abap_si_plan" { + value = var.abap_si_plan + description = "Plan for the service instance of ABAP." +} + +output "abap_admin_email" { + value = var.abap_admin_email + description = "Email of the ABAP Administrator." +} + +output "abap_admin" { + value = var.abap_admin + description = "Email of the ABAP Administrator." +} + +output "abap_is_development_allowed" { + value = var.abap_is_development_allowed + description = "Flag to define if development on the ABAP system is allowed." } \ No newline at end of file diff --git a/released/discovery_center/mission_3061/step1/provider.tf b/released/discovery_center/mission_3061/step1/provider.tf index f9791033..a81510b5 100644 --- a/released/discovery_center/mission_3061/step1/provider.tf +++ b/released/discovery_center/mission_3061/step1/provider.tf @@ -12,5 +12,9 @@ terraform { # Please checkout documentation on how best to authenticate against SAP BTP # via the Terraform provider for SAP BTP provider "btp" { - globalaccount = var.globalaccount + # Comment out the idp in case you need it to connect to your global account + # ------------------------------------------------------------------------- + idp = var.custom_idp + globalaccount = var.globalaccount + cli_server_url = var.cli_server_url } diff --git a/released/discovery_center/mission_3061/step1/variables.tf b/released/discovery_center/mission_3061/step1/variables.tf index 19c60a16..ee7bf637 100644 --- a/released/discovery_center/mission_3061/step1/variables.tf +++ b/released/discovery_center/mission_3061/step1/variables.tf @@ -6,6 +6,19 @@ variable "globalaccount" { variable "subaccount_prefix" { type = string description = "The prefix for the subaccount name and subdomain." + default = "ABAP-" +} + +variable "subaccount_name" { + type = string + description = "The name for the subaccount." + default = "" +} + +variable "cli_server_url" { + type = string + description = "The BTP CLI server URL." + default = "https://cli.btp.cloud.sap" } variable "region" { @@ -26,9 +39,52 @@ variable "cf_landscape_label" { default = "" } +variable "cf_space_name" { + type = string + description = "The name of the Cloud Foundry space." + default = "dev" +} + +variable "cf_org_managers" { + type = list(string) + description = "List of Cloud Foundry org managers." + default = [] +} + +variable "cf_org_billing_managers" { + type = list(string) + description = "List of Cloud Foundry org billing managers." + default = [] +} + +variable "cf_org_auditors" { + type = list(string) + description = "List of Cloud Foundry org auditors." + default = [] +} + +variable "cf_space_managers" { + type = list(string) + description = "List of managers for the Cloud Foundry space." + default = [] +} + +variable "cf_space_developers" { + type = list(string) + description = "List of developers for the Cloud Foundry space." + default = [] +} + +variable "cf_space_auditors" { + type = list(string) + description = "The list of Cloud Foundry space auditors." + default = [] +} + variable "abap_sid" { type = string - description = "The system ID (SID) of the ABAP system." + description = "The system ID (SID) of the ABAP system. It must consist of exactly three alphanumeric characters. Only uppercase letters are allowed. The first character must be a letter (not a digit). The ID does not have to be technically unique." + default = "A01" } variable "abap_si_plan" { @@ -49,7 +105,37 @@ variable "hana_compute_unit_quota" { default = 2 } +variable "abap_admin_email" { + type = string + description = "Email of the ABAP Administrator." + default = "" +} + +variable "abap_admin" { + type = list(string) + description = "Email of the ABAP Administrator." + default = [] +} + +variable "abap_is_development_allowed" { + type = bool + description = "Flag to define if development on the ABAP system is allowed." + default = true +} + variable "custom_idp" { type = string description = "Name of custom IDP to be used for the subaccount" } + +variable "origin" { + type = string + description = "The identity provider for the UAA user." + default = "sap.ids" +} + +variable "create_tfvars_file_for_next_stage" { + type = bool + description = "Switch to enable the creation of the tfvars file for the next step." + default = false +} diff --git a/released/discovery_center/mission_3061/step2/main.tf b/released/discovery_center/mission_3061/step2/main.tf index ad2fabc1..b40d94f9 100644 --- a/released/discovery_center/mission_3061/step2/main.tf +++ b/released/discovery_center/mission_3061/step2/main.tf @@ -3,6 +3,7 @@ ### locals { abap_service_instance_name = "abap-${var.abap_sid}" + abap_admin_email = var.abap_admin_email != "" ? var.abap_admin_email : var.abap_admin[0] } ### @@ -82,7 +83,7 @@ resource "cloudfoundry_service_instance" "abap_si" { service_plan = data.cloudfoundry_service.abap_service_plans.service_plans[var.abap_si_plan] type = "managed" parameters = jsonencode({ - admin_email = "${var.abap_admin_email}" + admin_email = "${local.abap_admin_email}" is_development_allowed = "${var.abap_is_development_allowed}" sapsystemname = "${var.abap_sid}" size_of_runtime = "${var.abap_compute_unit_quota}" diff --git a/released/discovery_center/mission_3061/step2/variables.tf b/released/discovery_center/mission_3061/step2/variables.tf index f494c88a..cf5090fe 100644 --- a/released/discovery_center/mission_3061/step2/variables.tf +++ b/released/discovery_center/mission_3061/step2/variables.tf @@ -1,10 +1,10 @@ -variable "cloudfoundry_api_url" { +variable "cf_api_url" { type = string description = "The API endpoint of the Cloud Foundry environment." } -variable "cloudfoundry_org_id" { +variable "cf_org_id" { type = string description = "The Cloud Foundry landscape (format example eu10-004)." } @@ -71,6 +71,13 @@ variable "abap_si_plan" { variable "abap_admin_email" { type = string description = "Email of the ABAP Administrator." + default = "" +} + +variable "abap_admin" { + type = list(string) + description = "Email of the ABAP Administrator." + default = [] } variable "abap_is_development_allowed" { From 446a872b1bf597e706227bf1f49b946c68f21ce5 Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Fri, 28 Jun 2024 13:22:37 +0200 Subject: [PATCH 2/6] add validation --- .../mission_3061/step1/locals.tf | 3 ++ .../mission_3061/step1/main.tf | 10 ++-- .../mission_3061/step1/outputs.tf | 4 +- .../mission_3061/step1/provider.tf | 2 +- .../mission_3061/step1/variables.tf | 38 +++++++++++++- .../mission_3061/step2/locals.tf | 3 ++ .../mission_3061/step2/variables.tf | 50 ++++++++++++++++--- 7 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 released/discovery_center/mission_3061/step1/locals.tf create mode 100644 released/discovery_center/mission_3061/step2/locals.tf diff --git a/released/discovery_center/mission_3061/step1/locals.tf b/released/discovery_center/mission_3061/step1/locals.tf new file mode 100644 index 00000000..8ccdfeb6 --- /dev/null +++ b/released/discovery_center/mission_3061/step1/locals.tf @@ -0,0 +1,3 @@ +locals { + service_name__abap = "abap" +} \ No newline at end of file diff --git a/released/discovery_center/mission_3061/step1/main.tf b/released/discovery_center/mission_3061/step1/main.tf index 05c054c2..171fbaca 100644 --- a/released/discovery_center/mission_3061/step1/main.tf +++ b/released/discovery_center/mission_3061/step1/main.tf @@ -25,20 +25,20 @@ resource "btp_subaccount" "abap_subaccount" { ### resource "btp_subaccount_entitlement" "abap__service_instance_plan" { subaccount_id = btp_subaccount.abap_subaccount.id - service_name = "abap" - plan_name = var.abap_si_plan + service_name = local.service_name__abap + plan_name = var.service_plan__abap } resource "btp_subaccount_entitlement" "abap__abap_compute_unit" { subaccount_id = btp_subaccount.abap_subaccount.id - service_name = "abap" + service_name = local.service_name__abap plan_name = "abap_compute_unit" amount = var.abap_compute_unit_quota } resource "btp_subaccount_entitlement" "abap__hana_compute_unit" { subaccount_id = btp_subaccount.abap_subaccount.id - service_name = "abap" + service_name = local.service_name__abap plan_name = "hana_compute_unit" amount = var.hana_compute_unit_quota } @@ -118,7 +118,7 @@ resource "local_file" "output_vars_step1" { cf_space_managers = ${jsonencode(var.cf_space_managers)} abap_sid = "${var.abap_sid}" - abap_si_plan = "${var.abap_si_plan}" + service_plan__abap = "${var.service_plan__abap}" abap_compute_unit_quota = ${jsonencode(var.abap_compute_unit_quota)} hana_compute_unit_quota = ${jsonencode(var.hana_compute_unit_quota)} abap_admin_email = "${var.abap_admin_email}" diff --git a/released/discovery_center/mission_3061/step1/outputs.tf b/released/discovery_center/mission_3061/step1/outputs.tf index f39c48c3..f2d6e1e3 100644 --- a/released/discovery_center/mission_3061/step1/outputs.tf +++ b/released/discovery_center/mission_3061/step1/outputs.tf @@ -83,8 +83,8 @@ output "cf_space_auditors" { description = "The list of Cloud Foundry space auditors." } -output "abap_si_plan" { - value = var.abap_si_plan +output "service_plan__abap" { + value = var.service_plan__abap description = "Plan for the service instance of ABAP." } diff --git a/released/discovery_center/mission_3061/step1/provider.tf b/released/discovery_center/mission_3061/step1/provider.tf index a81510b5..7f2d5d43 100644 --- a/released/discovery_center/mission_3061/step1/provider.tf +++ b/released/discovery_center/mission_3061/step1/provider.tf @@ -14,7 +14,7 @@ terraform { provider "btp" { # Comment out the idp in case you need it to connect to your global account # ------------------------------------------------------------------------- - idp = var.custom_idp + # idp = var.custom_idp globalaccount = var.globalaccount cli_server_url = var.cli_server_url } diff --git a/released/discovery_center/mission_3061/step1/variables.tf b/released/discovery_center/mission_3061/step1/variables.tf index ee7bf637..b12bf771 100644 --- a/released/discovery_center/mission_3061/step1/variables.tf +++ b/released/discovery_center/mission_3061/step1/variables.tf @@ -49,36 +49,72 @@ variable "cf_org_managers" { type = list(string) description = "List of Cloud Foundry org managers." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_org_billing_managers" { type = list(string) description = "List of Cloud Foundry org billing managers." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_org_auditors" { type = list(string) description = "List of Cloud Foundry org auditors." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_managers" { type = list(string) description = "List of managers for the Cloud Foundry space." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_developers" { type = list(string) description = "List of developers for the Cloud Foundry space." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_auditors" { type = list(string) description = "The list of Cloud Foundry space auditors." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "abap_sid" { @@ -87,7 +123,7 @@ variable "abap_sid" { default = "A01" } -variable "abap_si_plan" { +variable "service_plan__abap" { type = string description = "Plan for the service instance of ABAP." default = "standard" diff --git a/released/discovery_center/mission_3061/step2/locals.tf b/released/discovery_center/mission_3061/step2/locals.tf new file mode 100644 index 00000000..8ccdfeb6 --- /dev/null +++ b/released/discovery_center/mission_3061/step2/locals.tf @@ -0,0 +1,3 @@ +locals { + service_name__abap = "abap" +} \ No newline at end of file diff --git a/released/discovery_center/mission_3061/step2/variables.tf b/released/discovery_center/mission_3061/step2/variables.tf index cf5090fe..39e60f77 100644 --- a/released/discovery_center/mission_3061/step2/variables.tf +++ b/released/discovery_center/mission_3061/step2/variables.tf @@ -19,42 +19,78 @@ variable "cf_org_managers" { type = list(string) description = "List of Cloud Foundry org managers." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the Cloud Foundry org managers." + } } variable "cf_org_billing_managers" { type = list(string) description = "List of Cloud Foundry org billing managers." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_org_auditors" { type = list(string) description = "List of Cloud Foundry org auditors." default = [] -} - -variable "cf_space_name" { - type = string - description = "The name of the Cloud Foundry space." - default = "dev" + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_managers" { type = list(string) description = "List of managers for the Cloud Foundry space." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_developers" { type = list(string) description = "List of developers for the Cloud Foundry space." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } } variable "cf_space_auditors" { type = list(string) description = "The list of Cloud Foundry space auditors." default = [] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + error_message = "Please enter a valid email address for the subaccount admins." + } +} + +variable "cf_space_name" { + type = string + description = "The name of the Cloud Foundry space." + default = "dev" } variable "abap_sid" { @@ -62,7 +98,7 @@ variable "abap_sid" { description = "The system ID (SID) of the ABAP system." } -variable "abap_si_plan" { +variable "service_plan__abap" { type = string description = "Plan for the service instance of ABAP." default = "standard" From a4e4d01cf4b7b9f33a0d3a2b65dc4e8f2533f5ea Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Tue, 2 Jul 2024 10:24:29 +0200 Subject: [PATCH 3/6] minor fixes --- .../discovery_center/mission_3061/step1/locals.tf | 2 +- released/discovery_center/mission_3061/step1/main.tf | 4 ++-- .../discovery_center/mission_3061/step1/outputs.tf | 9 ++------- .../discovery_center/mission_3061/step1/variables.tf | 12 ++++++------ .../discovery_center/mission_3061/step2/README.md | 2 +- .../discovery_center/mission_3061/step2/locals.tf | 2 +- released/discovery_center/mission_3061/step2/main.tf | 5 ++--- .../discovery_center/mission_3061/step2/variables.tf | 6 ------ 8 files changed, 15 insertions(+), 27 deletions(-) diff --git a/released/discovery_center/mission_3061/step1/locals.tf b/released/discovery_center/mission_3061/step1/locals.tf index 8ccdfeb6..64cbcab2 100644 --- a/released/discovery_center/mission_3061/step1/locals.tf +++ b/released/discovery_center/mission_3061/step1/locals.tf @@ -1,3 +1,3 @@ locals { service_name__abap = "abap" -} \ No newline at end of file +} diff --git a/released/discovery_center/mission_3061/step1/main.tf b/released/discovery_center/mission_3061/step1/main.tf index 171fbaca..343ebd69 100644 --- a/released/discovery_center/mission_3061/step1/main.tf +++ b/released/discovery_center/mission_3061/step1/main.tf @@ -8,6 +8,7 @@ locals { subaccount_domain = lower("${var.subaccount_prefix}-${var.abap_sid}-${local.random_uuid}") subaccount_name = var.subaccount_name != "" ? var.subaccount_name : "${var.subaccount_prefix}-${var.abap_sid}" subaccount_cf_org = substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) + abap_admin_email = var.abap_admin_email != "" ? var.abap_admin_email : (length(var.qas_abap_admin) > 0 ? var.qas_abap_admin[0] : "") } ### @@ -121,8 +122,7 @@ resource "local_file" "output_vars_step1" { service_plan__abap = "${var.service_plan__abap}" abap_compute_unit_quota = ${jsonencode(var.abap_compute_unit_quota)} hana_compute_unit_quota = ${jsonencode(var.hana_compute_unit_quota)} - abap_admin_email = "${var.abap_admin_email}" - abap_admin = ${jsonencode(var.abap_admin)} + abap_admin_email = "${local.abap_admin_email}" abap_is_development_allowed = ${var.abap_is_development_allowed} EOT diff --git a/released/discovery_center/mission_3061/step1/outputs.tf b/released/discovery_center/mission_3061/step1/outputs.tf index f2d6e1e3..503177b4 100644 --- a/released/discovery_center/mission_3061/step1/outputs.tf +++ b/released/discovery_center/mission_3061/step1/outputs.tf @@ -89,16 +89,11 @@ output "service_plan__abap" { } output "abap_admin_email" { - value = var.abap_admin_email - description = "Email of the ABAP Administrator." -} - -output "abap_admin" { - value = var.abap_admin + value = local.abap_admin_email description = "Email of the ABAP Administrator." } output "abap_is_development_allowed" { value = var.abap_is_development_allowed description = "Flag to define if development on the ABAP system is allowed." -} \ No newline at end of file +} diff --git a/released/discovery_center/mission_3061/step1/variables.tf b/released/discovery_center/mission_3061/step1/variables.tf index 0de7b2cf..306acd61 100644 --- a/released/discovery_center/mission_3061/step1/variables.tf +++ b/released/discovery_center/mission_3061/step1/variables.tf @@ -152,12 +152,6 @@ variable "abap_admin_email" { default = "" } -variable "abap_admin" { - type = list(string) - description = "Email of the ABAP Administrator." - default = [] -} - variable "abap_is_development_allowed" { type = bool description = "Flag to define if development on the ABAP system is allowed." @@ -180,3 +174,9 @@ variable "create_tfvars_file_for_next_stage" { description = "Switch to enable the creation of the tfvars file for the next step." default = false } + +variable "qas_abap_admin" { + type = list(string) + description = "Email of the ABAP Administrator." + default = [] +} diff --git a/released/discovery_center/mission_3061/step2/README.md b/released/discovery_center/mission_3061/step2/README.md index afc695b8..36fdf2e1 100644 --- a/released/discovery_center/mission_3061/step2/README.md +++ b/released/discovery_center/mission_3061/step2/README.md @@ -6,7 +6,7 @@ This directory contains the setup of an ABAP environment from scratch namely a n This directory contains the configuration for the second step of the setup namely: -- the assignment of Cloud FOundry org roles +- the assignment of Cloud Foundry org roles - a new Cloud Foundry space - the assignment of Cloud Foundry space roles - the ABAP environment (service instance) diff --git a/released/discovery_center/mission_3061/step2/locals.tf b/released/discovery_center/mission_3061/step2/locals.tf index 8ccdfeb6..64cbcab2 100644 --- a/released/discovery_center/mission_3061/step2/locals.tf +++ b/released/discovery_center/mission_3061/step2/locals.tf @@ -1,3 +1,3 @@ locals { service_name__abap = "abap" -} \ No newline at end of file +} diff --git a/released/discovery_center/mission_3061/step2/main.tf b/released/discovery_center/mission_3061/step2/main.tf index c1091e48..8da13813 100644 --- a/released/discovery_center/mission_3061/step2/main.tf +++ b/released/discovery_center/mission_3061/step2/main.tf @@ -3,7 +3,6 @@ ### locals { abap_service_instance_name = "abap-${var.abap_sid}" - abap_admin_email = var.abap_admin_email != "" ? var.abap_admin_email : var.abap_admin[0] } ### @@ -80,10 +79,10 @@ data "cloudfoundry_service" "abap_service_plans" { resource "cloudfoundry_service_instance" "abap_si" { name = local.abap_service_instance_name space = cloudfoundry_space.abap_space.id - service_plan = data.cloudfoundry_service.abap_service_plans.service_plans[var.abap_si_plan] + service_plan = data.cloudfoundry_service.abap_service_plans.service_plans[var.service_plan__abap] type = "managed" parameters = jsonencode({ - admin_email = "${local.abap_admin_email}" + admin_email = "${var.abap_admin_email}" is_development_allowed = "${var.abap_is_development_allowed}" sapsystemname = "${var.abap_sid}" size_of_runtime = "${var.abap_compute_unit_quota}" diff --git a/released/discovery_center/mission_3061/step2/variables.tf b/released/discovery_center/mission_3061/step2/variables.tf index 378bbe3c..8ac39ec6 100644 --- a/released/discovery_center/mission_3061/step2/variables.tf +++ b/released/discovery_center/mission_3061/step2/variables.tf @@ -115,12 +115,6 @@ variable "abap_admin_email" { default = "" } -variable "abap_admin" { - type = list(string) - description = "Email of the ABAP Administrator." - default = [] -} - variable "abap_is_development_allowed" { type = bool description = "Flag to define if development on the ABAP system is allowed." From 8aeb184c4eac4fb1def85b34e45700d55e9bc362 Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Tue, 2 Jul 2024 10:52:25 +0200 Subject: [PATCH 4/6] fix validations --- .../discovery_center/mission_3061/step1/variables.tf | 12 ++++++------ .../discovery_center/mission_3061/step2/variables.tf | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/released/discovery_center/mission_3061/step1/variables.tf b/released/discovery_center/mission_3061/step1/variables.tf index 306acd61..8e07936c 100644 --- a/released/discovery_center/mission_3061/step1/variables.tf +++ b/released/discovery_center/mission_3061/step1/variables.tf @@ -52,7 +52,7 @@ variable "cf_org_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_managers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -64,7 +64,7 @@ variable "cf_org_billing_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_billing_managers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -76,7 +76,7 @@ variable "cf_org_auditors" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_auditors) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -88,7 +88,7 @@ variable "cf_space_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_managers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -100,7 +100,7 @@ variable "cf_space_developers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_developers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -112,7 +112,7 @@ variable "cf_space_auditors" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_auditors) error_message = "Please enter a valid email address for the subaccount admins." } } diff --git a/released/discovery_center/mission_3061/step2/variables.tf b/released/discovery_center/mission_3061/step2/variables.tf index 8ac39ec6..129733cf 100644 --- a/released/discovery_center/mission_3061/step2/variables.tf +++ b/released/discovery_center/mission_3061/step2/variables.tf @@ -22,7 +22,7 @@ variable "cf_org_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_managers) error_message = "Please enter a valid email address for the Cloud Foundry org managers." } } @@ -34,7 +34,7 @@ variable "cf_org_billing_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_billing_managers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -46,7 +46,7 @@ variable "cf_org_auditors" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_auditors) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -58,7 +58,7 @@ variable "cf_space_managers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_managers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -70,7 +70,7 @@ variable "cf_space_developers" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_developers) error_message = "Please enter a valid email address for the subaccount admins." } } @@ -82,7 +82,7 @@ variable "cf_space_auditors" { # add validation to check if admins contains a list of valid email addresses validation { - condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_admins) + condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_auditors) error_message = "Please enter a valid email address for the subaccount admins." } } From 4744df8c5d8963c273a7310e790d97182f182567 Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Tue, 2 Jul 2024 15:44:42 +0200 Subject: [PATCH 5/6] add dependency --- released/discovery_center/mission_3061/step2/main.tf | 1 + released/discovery_center/mission_3061/step2/provider.tf | 3 +++ 2 files changed, 4 insertions(+) diff --git a/released/discovery_center/mission_3061/step2/main.tf b/released/discovery_center/mission_3061/step2/main.tf index 8da13813..61c0891d 100644 --- a/released/discovery_center/mission_3061/step2/main.tf +++ b/released/discovery_center/mission_3061/step2/main.tf @@ -77,6 +77,7 @@ data "cloudfoundry_service" "abap_service_plans" { } resource "cloudfoundry_service_instance" "abap_si" { + depends_on = [ cloudfoundry_space_role.space_managers, cloudfoundry_space_role.space_developers ] name = local.abap_service_instance_name space = cloudfoundry_space.abap_space.id service_plan = data.cloudfoundry_service.abap_service_plans.service_plans[var.service_plan__abap] diff --git a/released/discovery_center/mission_3061/step2/provider.tf b/released/discovery_center/mission_3061/step2/provider.tf index 70b91d16..1b8fc117 100644 --- a/released/discovery_center/mission_3061/step2/provider.tf +++ b/released/discovery_center/mission_3061/step2/provider.tf @@ -9,5 +9,8 @@ terraform { # This will only work if we know the region in advance provider "cloudfoundry" { + # Comment out the origin in case you need it to connect to your CF environment + # ---------------------------------------------------------------------------- + # origin = var.origin api_url = var.cf_api_url } From b6a92465a8075abdb8e4079486e2d437435e497c Mon Sep 17 00:00:00 2001 From: Markus Balsam Date: Tue, 2 Jul 2024 16:05:36 +0200 Subject: [PATCH 6/6] fix formatting --- .../discovery_center/mission_3061/step1/main.tf | 10 +++++----- .../discovery_center/mission_3061/step1/outputs.tf | 2 +- .../mission_3061/step1/variables.tf | 14 +++++++------- .../discovery_center/mission_3061/step2/main.tf | 2 +- .../mission_3061/step2/variables.tf | 12 ++++++------ 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/released/discovery_center/mission_3061/step1/main.tf b/released/discovery_center/mission_3061/step1/main.tf index 343ebd69..d5fdd960 100644 --- a/released/discovery_center/mission_3061/step1/main.tf +++ b/released/discovery_center/mission_3061/step1/main.tf @@ -4,11 +4,11 @@ resource "random_uuid" "uuid" {} locals { - random_uuid = random_uuid.uuid.result - subaccount_domain = lower("${var.subaccount_prefix}-${var.abap_sid}-${local.random_uuid}") - subaccount_name = var.subaccount_name != "" ? var.subaccount_name : "${var.subaccount_prefix}-${var.abap_sid}" - subaccount_cf_org = substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) - abap_admin_email = var.abap_admin_email != "" ? var.abap_admin_email : (length(var.qas_abap_admin) > 0 ? var.qas_abap_admin[0] : "") + random_uuid = random_uuid.uuid.result + subaccount_domain = lower("${var.subaccount_prefix}-${var.abap_sid}-${local.random_uuid}") + subaccount_name = var.subaccount_name != "" ? var.subaccount_name : "${var.subaccount_prefix}-${var.abap_sid}" + subaccount_cf_org = substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) + abap_admin_email = var.abap_admin_email != "" ? var.abap_admin_email : (length(var.qas_abap_admin) > 0 ? var.qas_abap_admin[0] : "") } ### diff --git a/released/discovery_center/mission_3061/step1/outputs.tf b/released/discovery_center/mission_3061/step1/outputs.tf index 503177b4..748ec0ff 100644 --- a/released/discovery_center/mission_3061/step1/outputs.tf +++ b/released/discovery_center/mission_3061/step1/outputs.tf @@ -39,7 +39,7 @@ output "abap_sid" { } output "abap_compute_unit_quota" { - value = var.abap_compute_unit_quota + value = var.abap_compute_unit_quota description = "The amount of ABAP compute units to be assigned to the subaccount." } diff --git a/released/discovery_center/mission_3061/step1/variables.tf b/released/discovery_center/mission_3061/step1/variables.tf index 8e07936c..8ee80fdc 100644 --- a/released/discovery_center/mission_3061/step1/variables.tf +++ b/released/discovery_center/mission_3061/step1/variables.tf @@ -49,7 +49,7 @@ variable "cf_org_managers" { type = list(string) description = "List of Cloud Foundry org managers." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_managers) @@ -61,7 +61,7 @@ variable "cf_org_billing_managers" { type = list(string) description = "List of Cloud Foundry org billing managers." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_billing_managers) @@ -73,7 +73,7 @@ variable "cf_org_auditors" { type = list(string) description = "List of Cloud Foundry org auditors." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_auditors) @@ -85,7 +85,7 @@ variable "cf_space_managers" { type = list(string) description = "List of managers for the Cloud Foundry space." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_managers) @@ -97,7 +97,7 @@ variable "cf_space_developers" { type = list(string) description = "List of developers for the Cloud Foundry space." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_developers) @@ -109,7 +109,7 @@ variable "cf_space_auditors" { type = list(string) description = "The list of Cloud Foundry space auditors." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_auditors) @@ -125,7 +125,7 @@ variable "abap_sid" { condition = can(regex("^[A-Z][A-Z0-9]{2}$", var.abap_sid)) error_message = "Please provide a valid system ID (SID). It must consist of exactly three alphanumeric characters. Only uppercase letters are allowed. The first character must be a letter (not a digit). The ID does not have to be technically unique." } - default = "A01" + default = "A01" } variable "service_plan__abap" { diff --git a/released/discovery_center/mission_3061/step2/main.tf b/released/discovery_center/mission_3061/step2/main.tf index 61c0891d..051794c3 100644 --- a/released/discovery_center/mission_3061/step2/main.tf +++ b/released/discovery_center/mission_3061/step2/main.tf @@ -77,7 +77,7 @@ data "cloudfoundry_service" "abap_service_plans" { } resource "cloudfoundry_service_instance" "abap_si" { - depends_on = [ cloudfoundry_space_role.space_managers, cloudfoundry_space_role.space_developers ] + depends_on = [cloudfoundry_space_role.space_managers, cloudfoundry_space_role.space_developers] name = local.abap_service_instance_name space = cloudfoundry_space.abap_space.id service_plan = data.cloudfoundry_service.abap_service_plans.service_plans[var.service_plan__abap] diff --git a/released/discovery_center/mission_3061/step2/variables.tf b/released/discovery_center/mission_3061/step2/variables.tf index 129733cf..48e7deb7 100644 --- a/released/discovery_center/mission_3061/step2/variables.tf +++ b/released/discovery_center/mission_3061/step2/variables.tf @@ -19,7 +19,7 @@ variable "cf_org_managers" { type = list(string) description = "List of Cloud Foundry org managers." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_managers) @@ -31,7 +31,7 @@ variable "cf_org_billing_managers" { type = list(string) description = "List of Cloud Foundry org billing managers." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_billing_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_billing_managers) @@ -43,7 +43,7 @@ variable "cf_org_auditors" { type = list(string) description = "List of Cloud Foundry org auditors." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_org_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_auditors) @@ -55,7 +55,7 @@ variable "cf_space_managers" { type = list(string) description = "List of managers for the Cloud Foundry space." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_managers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_managers) @@ -67,7 +67,7 @@ variable "cf_space_developers" { type = list(string) description = "List of developers for the Cloud Foundry space." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_developers) @@ -79,7 +79,7 @@ variable "cf_space_auditors" { type = list(string) description = "The list of Cloud Foundry space auditors." default = [] - + # add validation to check if admins contains a list of valid email addresses validation { condition = length([for email in var.cf_space_auditors : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_space_auditors)