diff --git a/released/discovery_center/mission_3501/README.md b/released/discovery_center/mission_3501/README.md new file mode 100644 index 00000000..b39d69cb --- /dev/null +++ b/released/discovery_center/mission_3501/README.md @@ -0,0 +1,32 @@ +# Discovery Center Mission: Enhance core ERP business processes with resilient applications on SAP BTP (3501) + +## Overview + +This sample shows how to create a landscape for the Discovery Center Mission - [Enhance core ERP business processes with resilient applications on SAP BTP](https://discovery-center.cloud.sap/missiondetail/3501/) + +## Content of setup + +The setup comprises the following resources: + +- Creation of the SAP BTP subaccount +- Entitlements of services +- Subscriptions to applications +- Role collection assignments to users +- Creation of CF environments +- Management of users and roles on org and space level + +## Deploying the resources + +To deploy the resources you must: + +1. Export environment variables BTP_USERNAME, BTP_PASSWORD, CF_USER, and CF_PASSWORD with your username and password for the custom IdP of your global account. + +2. Change the variables in the `samples.tfvars` file in the main folder to meet your requirements + + > ⚠ NOTE: You should pay attention **specifically** to the users defined in the samples.tfvars whether they already exist in your SAP BTP accounts. Otherwise you might get error messages like e.g. `Error: The user could not be found: jane.doe@test.com`. + +3. Execute the apply.sh script. + +4. Verify e.g., in BTP cockpit that a new subaccount with a integration suite, SAP Business Application Studio, CF environment instance and a CF space have been created. + +5. Clean up by running the destroy.sh script. \ No newline at end of file diff --git a/released/discovery_center/mission_3501/apply.sh b/released/discovery_center/mission_3501/apply.sh new file mode 100755 index 00000000..fb333585 --- /dev/null +++ b/released/discovery_center/mission_3501/apply.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +cd step1 + +terraform init +terraform apply -var-file='../samples.tfvars' -auto-approve +terraform output > ../step2/step1vars.tfvars + +cd ../step2 + +terraform init +terraform apply -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_3501/destroy.sh b/released/discovery_center/mission_3501/destroy.sh new file mode 100755 index 00000000..c149b746 --- /dev/null +++ b/released/discovery_center/mission_3501/destroy.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +cd step2 + +terraform destroy -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve +rm step1vars.tfvars + +cd ../step1 + +terraform destroy -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_3501/samples.tfvars b/released/discovery_center/mission_3501/samples.tfvars new file mode 100644 index 00000000..66d600f8 --- /dev/null +++ b/released/discovery_center/mission_3501/samples.tfvars @@ -0,0 +1,28 @@ +globalaccount = "myglobalaccount" +region = "us10" +subaccount_name = "Discovery Center mission - 3501" +cf_org_name = "cf-environment" + +subaccount_admins = ["john.doe@sap.com"] +subaccount_service_admins = ["john.doe@sap.com"] + +appstudio_developers = ["john.doe@sap.com"] +appstudio_admins = ["john.doe@sap.com"] +cloudconnector_admins = ["john.doe@sap.com"] +conn_dest_admins = ["john.doe@sap.com"] + +cf_space_developers = ["john.doe@sap.com"] +cf_space_managers = ["john.doe@sap.com"] +cf_org_admins = ["john.doe@sap.com"] +cf_org_users = ["john.doe@sap.com"] + +hana_system_password = "Abc12345" +hana_cloud_admins = ["john.doe@sap.com"] + +event_mesh_admins = ["john.doe@sap.com"] +event_mesh_developers = ["john.doe@sap.com"] + +workzone_se_administrators = ["john.doe@sap.com"] +cicd_service_admins = ["john.doe@sap.com"] +tms_admins = ["john.doe@sap.com"] +tms_import_operators = ["john.doe@sap.com"] diff --git a/released/discovery_center/mission_3501/step1/locals.tf b/released/discovery_center/mission_3501/step1/locals.tf new file mode 100644 index 00000000..90bebd94 --- /dev/null +++ b/released/discovery_center/mission_3501/step1/locals.tf @@ -0,0 +1,5 @@ +locals { + service__sap_business_app_studio = "sapappstudio" + service_name__hana_cloud_tools = "hana-cloud-tools" + service_name__build_workzone = "SAPLaunchpad" +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step1/main.tf b/released/discovery_center/mission_3501/step1/main.tf new file mode 100644 index 00000000..569cf3e2 --- /dev/null +++ b/released/discovery_center/mission_3501/step1/main.tf @@ -0,0 +1,412 @@ +############################################################################################### +# Setup of names in accordance to naming convention +############################################################################################### +resource "random_uuid" "uuid" {} + +locals { + random_uuid = random_uuid.uuid.result + project_subaccount_domain = lower(replace("mission-3501-${local.random_uuid}", "_", "-")) + project_subaccount_cf_org = substr(replace("${local.project_subaccount_domain}", "-", ""), 0, 32) +} + +############################################################################################### +# Creation of subaccount +############################################################################################### +resource "btp_subaccount" "project" { + count = var.subaccount_id == "" ? 1 : 0 + + name = var.subaccount_name + subdomain = local.project_subaccount_domain + region = lower(var.region) + usage = "USED_FOR_PRODUCTION" +} + +data "btp_subaccount" "project" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.project[0].id +} + +############################################################################################### +# Assignment of users as sub account administrators +############################################################################################### +resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { + for_each = toset("${var.subaccount_admins}") + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Subaccount Administrator" + user_name = each.value +} + +############################################################################################### +# Assignment of users as sub account service administrators +############################################################################################### +resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { + for_each = toset("${var.subaccount_service_admins}") + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Subaccount Service Administrator" + user_name = each.value +} + +###################################################################### +# Extract list of CF landscape labels from environments +###################################################################### +data "btp_subaccount_environments" "all" { + subaccount_id = data.btp_subaccount.project.id +} + +locals { + cf_landscape_labels = [ + for env in data.btp_subaccount_environments.all.values : env.landscape_label + if env.environment_type == "cloudfoundry" + ] +} + + +###################################################################### +# Creation of Cloud Foundry environment +###################################################################### +resource "btp_subaccount_environment_instance" "cloudfoundry" { + subaccount_id = data.btp_subaccount.project.id + name = var.cf_org_name + environment_type = "cloudfoundry" + service_name = "cloudfoundry" + plan_name = "standard" + landscape_label = local.cf_landscape_labels[0] + parameters = jsonencode({ + instance_name = local.project_subaccount_cf_org + }) +} + +###################################################################### +# Entitlement of all general services +###################################################################### +resource "btp_subaccount_entitlement" "genentitlements" { + for_each = { + for index, entitlement in var.entitlements : + index => entitlement + } + subaccount_id = data.btp_subaccount.project.id + service_name = each.value.service_name + plan_name = each.value.plan_name +} + +# ###################################################################### +# # Create app subscription to SAP Business APplication Studio +# ###################################################################### + +resource "btp_subaccount_entitlement" "bas" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio +} + +# Create app subscription to busineass applicaiton stuido +resource "btp_subaccount_subscription" "bas" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio + depends_on = [btp_subaccount_entitlement.bas] +} + +resource "btp_subaccount_role_collection_assignment" "bas_dev" { + depends_on = [btp_subaccount_subscription.bas] + for_each = toset(var.appstudio_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Business_Application_Studio_Developer" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "bas_admn" { + depends_on = [btp_subaccount_subscription.bas] + for_each = toset(var.appstudio_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Business_Application_Studio_Administrator" + user_name = each.value +} + +###################################################################### +# Assign other Role Collection +###################################################################### + +resource "btp_subaccount_role_collection_assignment" "cloud_conn_admn" { + depends_on = [btp_subaccount_entitlement.genentitlements] + for_each = toset(var.cloudconnector_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Cloud Connector Administrator" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { + depends_on = [btp_subaccount_entitlement.genentitlements] + for_each = toset(var.conn_dest_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Connectivity and Destination Administrator" + user_name = each.value +} + +# ------------------------------------------------------------------------------------------------------ +# Entitle subaccount for usage of SAP HANA Cloud tools +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_entitlement" "hana_cloud_tools" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__hana_cloud_tools + plan_name = "tools" +} + +resource "btp_subaccount_subscription" "hana_cloud_tools" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service_name__hana_cloud_tools + plan_name = "tools" + depends_on = [btp_subaccount_entitlement.hana_cloud_tools] +} + +# Assign users to Role Collection: SAP HANA Cloud Administrator +resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { + for_each = toset(var.hana_cloud_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "SAP HANA Cloud Administrator" + user_name = each.value + depends_on = [btp_subaccount_subscription.hana_cloud_tools] +} + +# ------------------------------------------------------------------------------------------------------ +# Entitle subaccount for usage of SAP HANA Cloud +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_entitlement" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + service_name = "hana-cloud" + plan_name = "hana" +} + +# Get plan for SAP HANA Cloud +data "btp_subaccount_service_plan" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + offering_name = "hana-cloud" + name = "hana" + depends_on = [btp_subaccount_entitlement.hana_cloud] +} + +resource "btp_subaccount_service_instance" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + serviceplan_id = data.btp_subaccount_service_plan.hana_cloud.id + name = "my-hana-cloud-instance" + depends_on = [btp_subaccount_entitlement.hana_cloud] + parameters = jsonencode( + { + "data" : { + "memory" : 32, + "edition" : "cloud", + "systempassword" : "${var.hana_system_password}", + "additionalWorkers" : 0, + "disasterRecoveryMode" : "no_disaster_recovery", + "enabledservices" : { + "docstore" : false, + "dpserver" : true, + "scriptserver" : false + }, + "requestedOperation" : {}, + "serviceStopped" : false, + "slaLevel" : "standard", + "storage" : 120, + "vcpu" : 2, + "whitelistIPs" : ["0.0.0.0/0"] + } + }) + + timeouts = { + create = "45m" + update = "45m" + delete = "45m" + } +} + +# Create service binding to SAP HANA Cloud service +resource "btp_subaccount_service_binding" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + service_instance_id = btp_subaccount_service_instance.hana_cloud.id + name = "hana-cloud-key" +} + +###################################################################### +# Event Mesh +###################################################################### +resource "btp_subaccount_entitlement" "event_mesh" { + subaccount_id = data.btp_subaccount.project.id + service_name = "enterprise-messaging" + plan_name = "default" +} + +resource "btp_subaccount_entitlement" "event_mesh_application" { + subaccount_id = data.btp_subaccount.project.id + service_name = "enterprise-messaging-hub" + plan_name = "standard" +} + +resource "btp_subaccount_subscription" "event_mesh_application" { + subaccount_id = data.btp_subaccount.project.id + app_name = "enterprise-messaging-hub" + plan_name = "standard" + depends_on = [btp_subaccount_entitlement.event_mesh_application] +} + +resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { + depends_on = [btp_subaccount_entitlement.event_mesh_application] + for_each = toset(var.event_mesh_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Enterprise Messaging Administrator" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { + depends_on = [btp_subaccount_entitlement.event_mesh_application] + for_each = toset(var.event_mesh_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Enterprise Messaging Developer" + user_name = each.value +} + +###################################################################### +# CI CD +###################################################################### +resource "btp_subaccount_entitlement" "cicd" { + subaccount_id = data.btp_subaccount.project.id + service_name = "cicd-app" + plan_name = "default" +} + +resource "btp_subaccount_subscription" "cicd" { + subaccount_id = data.btp_subaccount.project.id + app_name = "cicd-app" + plan_name = "default" + depends_on = [btp_subaccount_entitlement.cicd] +} + +# assign users to role collection - CICD Service Administrator +resource "btp_subaccount_role_collection_assignment" "cicd_service_admin" { + depends_on = [btp_subaccount_subscription.cicd] + for_each = toset(var.cicd_service_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "CICD Service Administrator" + user_name = each.value +} + +###################################################################### +# alm-ts +###################################################################### +resource "btp_subaccount_entitlement" "alm_ts" { + subaccount_id = data.btp_subaccount.project.id + service_name = "alm-ts" + plan_name = "standard" +} + +resource "btp_subaccount_subscription" "alm_ts" { + subaccount_id = data.btp_subaccount.project.id + app_name = "alm-ts" + plan_name = "standard" + depends_on = [btp_subaccount_entitlement.alm_ts] +} + +data "btp_subaccount_roles" "all" { + subaccount_id = data.btp_subaccount.project.id + depends_on = [btp_subaccount_subscription.alm_ts] +} + +# Create the role collection - admin +resource "btp_subaccount_role_collection" "alm_ts_admin" { + subaccount_id = data.btp_subaccount.project.id + name = "TMS Admin" + depends_on = [data.btp_subaccount_roles.all] + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["Administrator"], role.name) && contains(["alm-ts"], role.app_name) + ] +} +# Assign users to the role collection - admin +resource "btp_subaccount_role_collection_assignment" "alm_ts_admin" { + depends_on = [btp_subaccount_role_collection.alm_ts_admin] + for_each = toset(var.tms_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "TMS Admin" + user_name = each.value +} + +# Create the role collection - import operator +resource "btp_subaccount_role_collection" "alm_ts_import_operator" { + subaccount_id = data.btp_subaccount.project.id + name = "TMS Import Operator" + + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["ImportOperator"], role.name) && contains(["alm-ts"], role.app_name) + ] +} + +# Assign users to the role collection - import operator +resource "btp_subaccount_role_collection_assignment" "alm_ts_import_operator" { + depends_on = [btp_subaccount_role_collection.alm_ts_import_operator] + for_each = toset(var.tms_import_operators) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "TMS Import Operator" + user_name = each.value +} + +###################################################################### +# autoscaler +###################################################################### +resource "btp_subaccount_entitlement" "autoscaler" { + subaccount_id = data.btp_subaccount.project.id + service_name = "autoscaler" + plan_name = "standard" +} + +###################################################################### +# alert-notification +###################################################################### +resource "btp_subaccount_entitlement" "alert_notification" { + subaccount_id = data.btp_subaccount.project.id + service_name = "alert-notification" + plan_name = "standard" +} + + +###################################################################### +# application-logs +###################################################################### +resource "btp_subaccount_entitlement" "app_logs" { + subaccount_id = data.btp_subaccount.project.id + service_name = "application-logs" + plan_name = "lite" +} + +############################################################################################### +# Prepare and setup app: SAP Build Workzone, standard edition +############################################################################################### +# Entitle subaccount for usage of app destination SAP Build Workzone, standard edition +resource "btp_subaccount_entitlement" "build_workzone" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__build_workzone + plan_name = var.service_plan__build_workzone + amount = var.service_plan__build_workzone == "free" ? 1 : null +} + +# Create app subscription to SAP Build Workzone, standard edition (depends on entitlement) +resource "btp_subaccount_subscription" "build_workzone" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service_name__build_workzone + plan_name = var.service_plan__build_workzone + depends_on = [btp_subaccount_entitlement.build_workzone] +} + +# Assign users to Role Collection: Launchpad_Admin (SAP Build Workzone, standard edition) +resource "btp_subaccount_role_collection_assignment" "launchpad_admin" { + for_each = toset("${var.workzone_se_administrators}") + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Launchpad_Admin" + user_name = each.value + depends_on = [btp_subaccount_subscription.build_workzone] +} + diff --git a/released/discovery_center/mission_3501/step1/output.tf b/released/discovery_center/mission_3501/step1/output.tf new file mode 100644 index 00000000..56f90f7b --- /dev/null +++ b/released/discovery_center/mission_3501/step1/output.tf @@ -0,0 +1,15 @@ +output "cf_landscape_label" { + value = btp_subaccount_environment_instance.cloudfoundry.landscape_label +} + +output "cf_api_url" { + value = jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"] +} + +output "cf_org_id" { + value = btp_subaccount_environment_instance.cloudfoundry.platform_id +} + +output "subaccount_id" { + value = data.btp_subaccount.project.id +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step1/provider.tf b/released/discovery_center/mission_3501/step1/provider.tf new file mode 100644 index 00000000..f4e6f577 --- /dev/null +++ b/released/discovery_center/mission_3501/step1/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + btp = { + source = "SAP/btp" + version = "1.4.0" + } + } +} + +###################################################################### +# Configure BTP provider +###################################################################### +provider "btp" { + cli_server_url = var.cli_server_url + globalaccount = var.globalaccount +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step1/variables.tf b/released/discovery_center/mission_3501/step1/variables.tf new file mode 100644 index 00000000..395d0f00 --- /dev/null +++ b/released/discovery_center/mission_3501/step1/variables.tf @@ -0,0 +1,276 @@ +###################################################################### +# Customer account setup +###################################################################### +# subaccount +variable "globalaccount" { + type = string + description = "The globalaccount subdomain." + default = "yourglobalaccount" +} + +variable "subaccount_id" { + type = string + description = "The subaccount ID." + default = "" +} + +# subaccount +variable "subaccount_name" { + type = string + description = "The subaccount name." + default = "UC - Deliver Connected Experiences with a single view of Material Availability" +} + +# cf org name +variable "cf_org_name" { + type = string + description = "Cloud Foundry Org Name" + default = "cloud-foundry" +} + +# Region +variable "region" { + type = string + description = "The region where the project account shall be created in." + default = "us10" +} + +# CLI server +variable "cli_server_url" { + type = string + description = "The BTP CLI server URL." + default = "https://cli.btp.cloud.sap" +} + +# subaccount variables +variable "subaccount_admins" { + type = list(string) + description = "Defines the colleagues who are added to each subaccount as subaccount administrators." + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.subaccount_admins : 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 "subaccount_service_admins" { + type = list(string) + description = "Defines the colleagues who are added to each subaccount as subaccount service administrators." + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.subaccount_service_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_service_admins) + error_message = "Please enter a valid email address for the Subaccount service Admins." + } +} + +variable "service_plan__sap_business_app_studio" { + type = string + description = "The plan for SAP Business Application Studio" + default = "standard-edition" + validation { + condition = contains(["standard-edition"], var.service_plan__sap_business_app_studio) + error_message = "Invalid value for service_plan__sap_business_app_studio. Only 'standard-edition' is allowed." + } +} + +### +# Entitlements +### +variable "entitlements" { + type = list(object({ + service_name = string + plan_name = string + type = string + })) + description = "The list of entitlements that shall be added to the subaccount." + default = [ + { + service_name = "connectivity" + plan_name = "lite", + type = "service" + }, + { + service_name = "destination" + plan_name = "lite", + type = "service" + }, + { + service_name = "html5-apps-repo" + plan_name = "app-host", + type = "service" + }, + { + service_name = "xsuaa" + plan_name = "application", + type = "service" + } + ] +} + +variable "appstudio_developers" { + type = list(string) + description = "Business Application Studio Developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Business Application Studio Developers contains a list of valid email addresses + validation { + condition = length([for email in var.appstudio_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_developers) + error_message = "Please enter a valid email address for the Business Application Studio Developers" + } +} + +variable "appstudio_admins" { + type = list(string) + description = "Business Application Studio Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Business Application Studio Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.appstudio_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_admins) + error_message = "Please enter a valid email address for the Business Application Studio Administrators." + } +} + +variable "cloudconnector_admins" { + type = list(string) + description = "Cloud Connector Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Cloud Connector Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.cloudconnector_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cloudconnector_admins) + error_message = "Please enter a valid email address for the Cloud Connector Administrators." + } +} + +variable "conn_dest_admins" { + type = list(string) + description = "Connectivity and Destination Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Connectivity and Destination Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.conn_dest_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.conn_dest_admins) + error_message = "Please enter a valid email address for the Connectivity and Destination Administrators." + } +} + +variable "hana_cloud_admins" { + type = list(string) + description = "Defines the colleagues who are added as admins to access the instance of SAP HANA Cloud." + default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.hana_cloud_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.hana_cloud_admins) + error_message = "Please enter a valid email address for the admins of SAP HANA Cloud instance." + } +} + + +variable "hana_system_password" { + type = string + description = "The password of the database 'superuser' DBADMIN." + sensitive = true + + # add validation to check if the password is at least 8 characters long + validation { + condition = length(var.hana_system_password) > 7 + error_message = "The hana_system_password must be at least 8 characters long." + } + + # add validation to check if the password contains at least one upper case + validation { + condition = can(regex("[A-Z]", var.hana_system_password)) + error_message = "The hana_system_password must contain at least one upper case." + } + + # add validation to check if the password contains at least two lower case characters that can occur on arbitrary places in the string (not necessarily in a row) + validation { + condition = length(regexall("[a-z]", var.hana_system_password)) > 1 + error_message = "The hana_system_password must contain at least two lower case characters." + } + + # add validation to check if the password contains at least one numeric character + validation { + condition = can(regex("[0-9]", var.hana_system_password)) + error_message = "The hana_system_password must contain at least one numeric character." + } +} + + +variable "event_mesh_admins" { + type = list(string) + description = "Enterprise Messaging Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.event_mesh_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_admins) + error_message = "Please enter a valid email address for the Enterprise Messaging Administrators." + } +} + +variable "event_mesh_developers" { + type = list(string) + description = "Enterprise Messaging Developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Enterprise Messaging Developers contains a list of valid email addresses + validation { + condition = length([for email in var.event_mesh_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_developers) + error_message = "Please enter a valid email address for the Enterprise Messaging Developers." + } +} + +variable "service_plan__build_workzone" { + type = string + description = "The plan for build_workzone subscription" + default = "free" + validation { + condition = contains(["free", "standard"], var.service_plan__build_workzone) + error_message = "Invalid value for service_plan__build_workzone. Only 'free' and 'standard' are allowed." + } +} + +variable "workzone_se_administrators" { + type = list(string) + description = "Workzone Standard Edition Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Workzone Standard Edition Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.workzone_se_administrators : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.workzone_se_administrators) + error_message = "Please enter a valid email address for the Workzone Standard Edition Administratorss." + } +} + +variable "tms_admins" { + type = list(string) + description = "TMS Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if TMS Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.tms_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.tms_admins) + error_message = "Please enter a valid email address for the TMS Administrators." + } +} + +variable "tms_import_operators" { + type = list(string) + description = "TMS Import Operators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if TMS Import Operators contains a list of valid email addresses + validation { + condition = length([for email in var.tms_import_operators : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.tms_import_operators) + error_message = "Please enter a valid email address for the TMS Import Operators." + } +} + +variable "cicd_service_admins" { + type = list(string) + description = "CICD Service Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CICD Service Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.cicd_service_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cicd_service_admins) + error_message = "Please enter a valid email address for the CICD Service Administrators." + } +} + + diff --git a/released/discovery_center/mission_3501/step2/main.tf b/released/discovery_center/mission_3501/step2/main.tf new file mode 100644 index 00000000..b4812ee4 --- /dev/null +++ b/released/discovery_center/mission_3501/step2/main.tf @@ -0,0 +1,40 @@ +###################################################################### +# Create space using CF provider +###################################################################### +resource "cloudfoundry_space" "dev" { + name = "DEV" + org = var.cf_org_id +} + +###################################################################### +# add org and space users and managers +###################################################################### +resource "cloudfoundry_org_role" "organization_user" { + for_each = toset(var.cf_org_users) + username = each.value + type = "organization_user" + org = var.cf_org_id +} + +resource "cloudfoundry_org_role" "organization_manager" { + for_each = toset(var.cf_org_admins) + username = each.value + type = "organization_manager" + org = var.cf_org_id +} + +resource "cloudfoundry_space_role" "space_developer" { + for_each = toset(var.cf_space_developers) + username = each.value + type = "space_developer" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} + +resource "cloudfoundry_space_role" "space_manager" { + for_each = toset(var.cf_space_managers) + username = each.value + type = "space_manager" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step2/output.tf b/released/discovery_center/mission_3501/step2/output.tf new file mode 100644 index 00000000..ad4178cd --- /dev/null +++ b/released/discovery_center/mission_3501/step2/output.tf @@ -0,0 +1,19 @@ +output "subaccount_id" { + value = var.subaccount_id +} + +output "cf_landscape_label" { + value = var.cf_landscape_label +} + +output "cf_org_id" { + value = var.cf_org_id +} + +output "cf_api_url" { + value = var.cf_api_url +} + +output "cf_space_name" { + value = cloudfoundry_space.dev.name +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step2/provider.tf b/released/discovery_center/mission_3501/step2/provider.tf new file mode 100644 index 00000000..9337283b --- /dev/null +++ b/released/discovery_center/mission_3501/step2/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + cloudfoundry = { + source = "SAP/cloudfoundry" + version = "0.2.1-beta" + } + } +} + +###################################################################### +# Configure CF provider +###################################################################### +provider "cloudfoundry" { + # resolve API URL from environment instance + api_url = var.cf_api_url +} \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step2/variables.tf b/released/discovery_center/mission_3501/step2/variables.tf new file mode 100644 index 00000000..0b435101 --- /dev/null +++ b/released/discovery_center/mission_3501/step2/variables.tf @@ -0,0 +1,59 @@ +variable "cf_api_url" { + type = string +} + +variable "cf_landscape_label" { + type = string +} + +variable "cf_org_id" { + type = string +} + +variable "subaccount_id" { + type = string +} + +variable "cf_space_developers" { + type = list(string) + description = "CF Space developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Space developers 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) + error_message = "Please enter a valid email address for the CF Space developers." + } +} + +variable "cf_space_managers" { + type = list(string) + description = "CF Space managers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Space managers 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) + error_message = "Please enter a valid email address for the Cloud Connector Administrators." + } +} + +variable "cf_org_admins" { + type = list(string) + description = "CF Org Admins" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Org Admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_admins) + error_message = "Please enter a valid email address for the CF Org Admins." + } +} + +variable "cf_org_users" { + type = list(string) + description = "CF Org Users" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Org Users contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_users : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_users) + error_message = "Please enter a valid email address for the CF Org Users." + } +} diff --git a/released/discovery_center/mission_4033/README.md b/released/discovery_center/mission_4033/README.md index 1b417493..4c42264b 100644 --- a/released/discovery_center/mission_4033/README.md +++ b/released/discovery_center/mission_4033/README.md @@ -18,11 +18,11 @@ The setup comprises the following resources: To deploy the resources you must: -1. Create a file `secret.auto.tfvars` and maintain the credentials for the BTP and CF provider +1. Set the environment variables BTP_USERNAME and BTP_PASSWORD to pass credentials to the BTP provider to authenticate and interact with your BTP environments. - ```hcl - username = "" - password = "" + ```bash + export BTP_USERNAME= + export BTP_PASSWORD= ``` 2. Change the variables in the `samples.tfvars` file to meet your requirements @@ -45,7 +45,7 @@ To deploy the resources you must: 5. Apply your configuration to provision the resources: ```bash - terraform apply -var-file="sample.tfvars" + terraform apply -var-file="samples.tfvars" ``` ## In the end diff --git a/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_setup.tf b/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_setup.tf deleted file mode 100644 index 65aa7dba..00000000 --- a/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_setup.tf +++ /dev/null @@ -1,92 +0,0 @@ -# ------------------------------------------------------------------------------------------------------ -# Define the required providers for this module -# ------------------------------------------------------------------------------------------------------ -terraform { - required_providers { - btp = { - source = "SAP/btp" - version = "~> 1.4.0" - } - } -} - -###################################################################### -# Create app subscriptions -###################################################################### -data "btp_subaccount_subscriptions" "all" { - subaccount_id = var.btp_subaccount_id -} - -resource "btp_subaccount_subscription" "app" { - subaccount_id = var.btp_subaccount_id - for_each = { - for index, entitlement in var.entitlements : - index => entitlement if contains(["app"], entitlement.type) - } - app_name = [ - for subscription in data.btp_subaccount_subscriptions.all.values : - subscription - if subscription.commercial_app_name == each.value.service_name - ][0].app_name - plan_name = each.value.plan_name - depends_on = [data.btp_subaccount_subscriptions.all] -} - -###################################################################### -# Assign Role Collection -###################################################################### - -resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.conn_dest_admin) - subaccount_id = var.btp_subaccount_id - role_collection_name = "Connectivity and Destination Administrator" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "int_prov" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.int_provisioner) - subaccount_id = var.btp_subaccount_id - role_collection_name = "Integration_Provisioner" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "sbpa_admin" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.ProcessAutomationAdmin) - subaccount_id = var.btp_subaccount_id - role_collection_name = "ProcessAutomationAdmin" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "sbpa_dev" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.ProcessAutomationAdmin) - subaccount_id = var.btp_subaccount_id - role_collection_name = "ProcessAutomationAdmin" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "sbpa_part" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.ProcessAutomationParticipant) - subaccount_id = var.btp_subaccount_id - role_collection_name = "ProcessAutomationParticipant" - user_name = each.value -} - -###################################################################### -# Create app subscription to SAP Build Apps (depends on entitlement) -###################################################################### -module "sap-build-apps_standard" { - source = "../../../modules/services_apps/sap_build_apps/standard" - subaccount_id = var.btp_subaccount_id - subaccount_domain = var.subdomain - region = var.region - custom_idp_origin = var.custom_idp_origin - users_BuildAppsAdmin = var.users_BuildAppsAdmin - users_BuildAppsDeveloper = var.users_BuildAppsDeveloper - users_RegistryAdmin = var.users_RegistryAdmin - users_RegistryDeveloper = var.users_RegistryDeveloper -} diff --git a/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_variables.tf b/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_variables.tf deleted file mode 100644 index 0d8a1186..00000000 --- a/released/discovery_center/mission_4033/app_susbscriptions/app_subscriptions_variables.tf +++ /dev/null @@ -1,87 +0,0 @@ -### -# Entitlements -### -variable "entitlements" { - type = list(object({ - service_name = string - plan_name = string - type = string - })) - description = "The list of entitlements that shall be added to the subaccount." -} - -variable "kyma_instance" { type = object({ - name = string - region = string - machine_type = string - auto_scaler_min = number - auto_scaler_max = number - createtimeout = string - updatetimeout = string - deletetimeout = string -}) } - -variable "conn_dest_admin" { - type = list(string) - description = "Connectivity and Destination Administrator" -} - -variable "int_provisioner" { - type = list(string) - description = "Integration Provisioner" -} - -variable "custom_idp_origin" { - type = string - description = "Defines the custom IDP origin to be used for the subaccount" -} - -variable "users_BuildAppsAdmin" { - type = list(string) - description = "Defines the colleagues who have the role of 'BuildAppsAdmin' in SAP Build Apps." -} - -variable "users_BuildAppsDeveloper" { - type = list(string) - description = "Defines the colleagues who have the role of 'BuildAppsDeveloper' in SAP Build Apps." -} - -variable "users_RegistryAdmin" { - type = list(string) - description = "Defines the colleagues who have the role of 'RegistryAdmin' in SAP Build Apps." -} - -variable "users_RegistryDeveloper" { - type = list(string) - description = "Defines the colleagues who have the role of RegistryDeveloper' in SAP Build Apps." -} - -variable "ProcessAutomationAdmin" { - type = list(string) - description = "Defines the users who have the role of ProcessAutomationAdmin in SAP Build Process Automation" -} - -variable "ProcessAutomationDeveloper" { - type = list(string) - description = "Defines the users who have the role of ProcessAutomationDeveloper in SAP Build Process Automation" -} - -variable "ProcessAutomationParticipant" { - type = list(string) - description = "Defines the users who have the role of ProcessAutomationParticipant in SAP Build Process Automation" -} - -variable "region" { - type = string - description = "The region where the project account shall be created in." -} - -variable "btp_subaccount_id" { - type = string - description = "SAP BTP Subaccount ID" -} - -variable "subdomain" { - type = string - description = "SAP BTP Subdomain" -} \ No newline at end of file diff --git a/released/discovery_center/mission_4033/locals.tf b/released/discovery_center/mission_4033/locals.tf new file mode 100644 index 00000000..b920c29a --- /dev/null +++ b/released/discovery_center/mission_4033/locals.tf @@ -0,0 +1,5 @@ +locals { + service_name__sap_build_apps = "sap-build-apps" + service_name__sap_process_automation = "process-automation" + service_name__sap_integration_suite = "integrationsuite" +} \ No newline at end of file diff --git a/released/discovery_center/mission_4033/main.tf b/released/discovery_center/mission_4033/main.tf index bdda4a21..3a5c9f00 100644 --- a/released/discovery_center/mission_4033/main.tf +++ b/released/discovery_center/mission_4033/main.tf @@ -13,27 +13,32 @@ locals { # Creation of subaccount ############################################################################################### resource "btp_subaccount" "project" { + count = var.subaccount_id == "" ? 1 : 0 + name = var.subaccount_name subdomain = local.project_subaccount_domain region = lower(var.region) + usage = "USED_FOR_PRODUCTION" +} + +data "btp_subaccount" "project" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.project[0].id } + ############################################################################################### -# Assignment of users as sub account administrators +# Assignment of emergency admins to the sub account as sub account administrators ############################################################################################### -resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { - for_each = toset("${var.subaccount_admins}") - subaccount_id = btp_subaccount.project.id +resource "btp_subaccount_role_collection_assignment" "subaccount_admin" { + for_each = toset(var.subaccount_admins) + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Subaccount Administrator" user_name = each.value } -############################################################################################### -# Assignment of users as sub account service administrators -############################################################################################### -resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { - for_each = toset("${var.subaccount_service_admins}") - subaccount_id = btp_subaccount.project.id +resource "btp_subaccount_role_collection_assignment" "subaccount_service_admin" { + for_each = toset(var.subaccount_service_admins) + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Subaccount Service Administrator" user_name = each.value } @@ -42,8 +47,27 @@ resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" # Assign custom IDP to sub account ###################################################################### resource "btp_subaccount_trust_configuration" "fully_customized" { - subaccount_id = btp_subaccount.project.id - identity_provider = var.custom_idp + subaccount_id = data.btp_subaccount.project.id + identity_provider = var.custom_idp != "" ? var.custom_idp : element(split("/", btp_subaccount_subscription.identity_instance[0].subscription_url), 2) +} + +resource "btp_subaccount_entitlement" "identity" { + count = var.custom_idp == "" ? 1 : 0 + + subaccount_id = data.btp_subaccount.project.id + service_name = "sap-identity-services-onboarding" + plan_name = "default" +} + +resource "btp_subaccount_subscription" "identity_instance" { + count = var.custom_idp == "" ? 1 : 0 + + subaccount_id = data.btp_subaccount.project.id + app_name = "sap-identity-services-onboarding" + plan_name = "default" + parameters = jsonencode({ + cloud_service = "TEST" + }) } @@ -52,16 +76,16 @@ resource "btp_subaccount_trust_configuration" "fully_customized" { ###################################################################### data "btp_regions" "all" {} -data "btp_subaccount" "this" { - id = btp_subaccount.project.id -} +# data "btp_subaccount" "this" { +# id = data.btp_subaccount.project.id +# } locals { - subaccount_iaas_provider = [for region in data.btp_regions.all.values : region if region.region == data.btp_subaccount.this.region][0].iaas_provider + subaccount_iaas_provider = [for region in data.btp_regions.all.values : region if region.region == data.btp_subaccount.project.region][0].iaas_provider } resource "btp_subaccount_entitlement" "kymaruntime" { - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id service_name = "kymaruntime" plan_name = lower(local.subaccount_iaas_provider) amount = 1 @@ -69,11 +93,11 @@ resource "btp_subaccount_entitlement" "kymaruntime" { resource "btp_subaccount_environment_instance" "kyma" { - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id name = var.kyma_instance.name environment_type = "kyma" service_name = "kymaruntime" - plan_name = "aws" + plan_name = lower(local.subaccount_iaas_provider) parameters = jsonencode({ name = var.kyma_instance.name region = var.kyma_instance.region @@ -90,40 +114,231 @@ resource "btp_subaccount_environment_instance" "kyma" { } ###################################################################### -# Entitlement of all services +# Entitlement of all general services ###################################################################### -resource "btp_subaccount_entitlement" "name" { +resource "btp_subaccount_entitlement" "genentitlements" { for_each = { for index, entitlement in var.entitlements : index => entitlement } - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id service_name = each.value.service_name plan_name = each.value.plan_name } +###################################################################### +# Assign Role Collection +###################################################################### + +resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { + depends_on = [btp_subaccount_entitlement.genentitlements] + for_each = toset(var.conn_dest_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Connectivity and Destination Administrator" + user_name = each.value +} ###################################################################### -# Create App Subscriptions +# Create app subscription to SAP Integration Suite ###################################################################### -module "create_app_subscriptions" { - source = "./app_susbscriptions" - btp_subaccount_id = btp_subaccount.project.id - subdomain = btp_subaccount.project.subdomain - custom_idp_origin = btp_subaccount_trust_configuration.fully_customized.origin - entitlements = var.entitlements - region = var.region - kyma_instance = var.kyma_instance - - int_provisioner = var.int_provisioner - conn_dest_admin = var.conn_dest_admin - users_BuildAppsAdmin = var.users_BuildAppsAdmin - users_BuildAppsDeveloper = var.users_BuildAppsDeveloper - users_RegistryAdmin = var.users_RegistryAdmin - users_RegistryDeveloper = var.users_RegistryDeveloper - ProcessAutomationAdmin = var.ProcessAutomationAdmin - ProcessAutomationDeveloper = var.ProcessAutomationDeveloper - ProcessAutomationParticipant = var.ProcessAutomationParticipant - - depends_on = [btp_subaccount_entitlement.name] +resource "btp_subaccount_entitlement" "sap_integration_suite" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__sap_integration_suite + plan_name = var.service_plan__sap_integration_suite +} + +data "btp_subaccount_subscriptions" "all" { + subaccount_id = data.btp_subaccount.project.id + depends_on = [btp_subaccount_entitlement.sap_integration_suite] +} + +resource "btp_subaccount_subscription" "sap_integration_suite" { + subaccount_id = data.btp_subaccount.project.id + app_name = [ + for subscription in data.btp_subaccount_subscriptions.all.values : + subscription + if subscription.commercial_app_name == local.service_name__sap_integration_suite + ][0].app_name + plan_name = var.service_plan__sap_integration_suite + depends_on = [data.btp_subaccount_subscriptions.all] +} + +resource "btp_subaccount_role_collection_assignment" "int_prov" { + depends_on = [btp_subaccount_subscription.sap_integration_suite] + for_each = toset(var.int_provisioners) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Integration_Provisioner" + user_name = each.value +} + +# ###################################################################### +# # Create app subscription to SAP Build Process Automation +# ###################################################################### + +resource "btp_subaccount_entitlement" "build_process_automation" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__sap_process_automation + plan_name = var.service_plan__sap_process_automation +} + +# Create app subscription to SAP Build Workzone, standard edition (depends on entitlement) +resource "btp_subaccount_subscription" "build_process_automation" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service_name__sap_process_automation + plan_name = var.service_plan__sap_process_automation + depends_on = [btp_subaccount_entitlement.build_process_automation] +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_admin" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationAdmin" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_dev" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationAdmin" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_part" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_participants) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationParticipant" + user_name = each.value +} + +############################################################################################### +# Prepare and setup app: SAP Build Apps +############################################################################################### +# Entitle subaccount for usage of SAP Build Apps +resource "btp_subaccount_entitlement" "sap_build_apps" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__sap_build_apps + plan_name = var.service_plan__sap_build_apps + amount = 1 + depends_on = [btp_subaccount_trust_configuration.fully_customized] +} + +# Create a subscription to the SAP Build Apps +resource "btp_subaccount_subscription" "sap-build-apps_standard" { + subaccount_id = data.btp_subaccount.project.id + app_name = "sap-appgyver-ee" + plan_name = var.service_plan__sap_build_apps + depends_on = [btp_subaccount_entitlement.sap_build_apps] +} + +# Get all roles in the subaccount +data "btp_subaccount_roles" "all" { + subaccount_id = data.btp_subaccount.project.id + depends_on = [btp_subaccount_subscription.sap-build-apps_standard] +} + +############################################################################################### +# Setup for role collection BuildAppsAdmin +############################################################################################### +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_BuildAppsAdmin" { + subaccount_id = data.btp_subaccount.project.id + name = "BuildAppsAdmin" + + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["BuildAppsAdmin"], role.name) + ] +} +# Assign users to the role collection +resource "btp_subaccount_role_collection_assignment" "build_apps_BuildAppsAdmin" { + depends_on = [btp_subaccount_role_collection.build_apps_BuildAppsAdmin] + for_each = toset(var.users_buildApps_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "BuildAppsAdmin" + user_name = each.value + origin = btp_subaccount_trust_configuration.fully_customized.origin +} + +############################################################################################### +# Setup for role collection BuildAppsDeveloper +############################################################################################### +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_BuildAppsDeveloper" { + subaccount_id = data.btp_subaccount.project.id + name = "BuildAppsDeveloper" + + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["BuildAppsDeveloper"], role.name) + ] +} +# Assign users to the role collection +resource "btp_subaccount_role_collection_assignment" "build_apps_BuildAppsDeveloper" { + depends_on = [btp_subaccount_role_collection.build_apps_BuildAppsDeveloper] + for_each = toset(var.users_buildApps_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "BuildAppsDeveloper" + user_name = each.value + origin = btp_subaccount_trust_configuration.fully_customized.origin +} + +############################################################################################### +# Setup for role collection RegistryAdmin +############################################################################################### +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_RegistryAdmin" { + subaccount_id = data.btp_subaccount.project.id + name = "RegistryAdmin" + + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["RegistryAdmin"], role.name) + ] +} +# Assign users to the role collection +resource "btp_subaccount_role_collection_assignment" "build_apps_RegistryAdmin" { + depends_on = [btp_subaccount_role_collection.build_apps_RegistryAdmin] + for_each = toset(var.users_registry_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "RegistryAdmin" + user_name = each.value + origin = btp_subaccount_trust_configuration.fully_customized.origin +} + +############################################################################################### +# Setup for role collection RegistryDeveloper +############################################################################################### +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_RegistryDeveloper" { + subaccount_id = data.btp_subaccount.project.id + name = "RegistryDeveloper" + + roles = [ + for role in data.btp_subaccount_roles.all.values : { + name = role.name + role_template_app_id = role.app_id + role_template_name = role.role_template_name + } if contains(["RegistryDeveloper"], role.name) + ] +} +# Assign users to the role collection +resource "btp_subaccount_role_collection_assignment" "build_apps_RegistryDeveloper" { + depends_on = [btp_subaccount_role_collection.build_apps_RegistryDeveloper] + for_each = toset(var.users_registry_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "RegistryDeveloper" + user_name = each.value + origin = btp_subaccount_trust_configuration.fully_customized.origin } diff --git a/released/discovery_center/mission_4033/outputs.tf b/released/discovery_center/mission_4033/outputs.tf new file mode 100644 index 00000000..c12e4ba4 --- /dev/null +++ b/released/discovery_center/mission_4033/outputs.tf @@ -0,0 +1,4 @@ +output "subaccount_id" { + value = data.btp_subaccount.project.id + description = "The ID of the project subaccount." +} \ No newline at end of file diff --git a/released/discovery_center/mission_4033/provider.tf b/released/discovery_center/mission_4033/provider.tf index b06d38d9..d27c2b83 100644 --- a/released/discovery_center/mission_4033/provider.tf +++ b/released/discovery_center/mission_4033/provider.tf @@ -13,7 +13,5 @@ terraform { provider "btp" { globalaccount = var.globalaccount cli_server_url = var.cli_server_url - username = var.username - password = var.password } diff --git a/released/discovery_center/mission_4033/sample.tfvars b/released/discovery_center/mission_4033/sample.tfvars new file mode 100644 index 00000000..c4843dfc --- /dev/null +++ b/released/discovery_center/mission_4033/sample.tfvars @@ -0,0 +1,35 @@ +# ------------------------------------------------------------------------------------------------------ +# Provider configuration +# ------------------------------------------------------------------------------------------------------ +# Your global account subdomain +globalaccount = "yourglobalaccount" +region = "us10" +subaccount_name = "DC Mission 4033 - Create simple, connected digital experiences with API-based integration 1" +custom_idp = "xxxxxxxxxxxxx.accounts.ondemand.com" + +kyma_instance = { + name = "my-kyma-environment" + region = "us-east-1" + machine_type = "mx5.xlarge" + auto_scaler_min = 3 + auto_scaler_max = 20 + createtimeout = "1h" + updatetimeout = "35m" + deletetimeout = "1h" +} + +# ------------------------------------------------------------------------------------------------------ +# Project specific configuration (please adapt!) +# ------------------------------------------------------------------------------------------------------ +subaccount_admins = ["another.user@test.com"] +subaccount_service_admins = ["another.user@test.com"] +conn_dest_admins = ["another.user@test.com"] +int_provisioners = ["another.user@test.com"] +users_buildApps_admins = ["another.user@test.com"] +users_registry_admins = ["another.user@test.com"] +users_buildApps_developers = ["another.user@test.com"] +users_registry_developers = ["another.user@test.com"] +process_automation_admins = ["another.user@test.com"] +process_automation_developers = ["another.user@test.com"] +process_automation_participants = ["another.user@test.com"] + diff --git a/released/discovery_center/mission_4033/samples.tfvars b/released/discovery_center/mission_4033/samples.tfvars deleted file mode 100644 index 8b7b9a4c..00000000 --- a/released/discovery_center/mission_4033/samples.tfvars +++ /dev/null @@ -1,35 +0,0 @@ -# ------------------------------------------------------------------------------------------------------ -# Provider configuration -# ------------------------------------------------------------------------------------------------------ -# Your global account subdomain -globalaccount = "yoursubdomain" -region = "us10" -subaccount_name = "DC Mission 4033 - Create simple, connected digital experiences with API-based integration 2" -custom_idp = "youridp.accounts.ondemand.com" - -kyma_instance = { - name = "my-kyma-environment" - region = "us-east-1" - machine_type = "mx5.xlarge" - auto_scaler_min = 3 - auto_scaler_max = 20 - createtimeout = "1h" - updatetimeout = "35m" - deletetimeout = "1h" -} - -# ------------------------------------------------------------------------------------------------------ -# Project specific configuration (please adapt!) -# ------------------------------------------------------------------------------------------------------ -subaccount_admins = ["jane.doe@test.com", "john.doe@test.com"] -subaccount_service_admins = ["jane.doe@test.com", "john.doe@test.com"] - -conn_dest_admin = ["jane.doe@test.com", "john.doe@test.com"] -int_provisioner = ["jane.doe@test.com", "john.doe@test.com"] -users_BuildAppsAdmin = ["jane.doe@test.com", "john.doe@test.com"] -users_RegistryAdmin = ["jane.doe@test.com", "john.doe@test.com"] -users_BuildAppsDeveloper = ["jane.doe@test.com", "john.doe@test.com"] -users_RegistryDeveloper = ["jane.doe@test.com", "john.doe@test.com"] -ProcessAutomationAdmin = ["jane.doe@test.com", "john.doe@test.com"] -ProcessAutomationDeveloper = ["jane.doe@test.com", "john.doe@test.com"] -ProcessAutomationParticipant = ["jane.doe@test.com", "john.doe@test.com"] diff --git a/released/discovery_center/mission_4033/variables.tf b/released/discovery_center/mission_4033/variables.tf index ba1f3ec3..c61cf79b 100644 --- a/released/discovery_center/mission_4033/variables.tf +++ b/released/discovery_center/mission_4033/variables.tf @@ -13,6 +13,13 @@ variable "subaccount_name" { description = "The subaccount name." default = "DC Mission 4033 - Create simple, connected digital experiences with API-based integration" } + +variable "subaccount_id" { + type = string + description = "The subaccount ID." + default = "" +} + # Region variable "region" { type = string @@ -24,22 +31,48 @@ variable "region" { variable "cli_server_url" { type = string description = "The BTP CLI server URL." - default = "https://cpcli.cf.eu10.hana.ondemand.com" + default = "https://cli.btp.cloud.sap" } variable "subaccount_admins" { type = list(string) - description = "Defines the colleagues who are added to each subaccount as subaccount administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] + description = "Defines the colleagues who are added to each subaccount as Subaccount administrators." } variable "subaccount_service_admins" { type = list(string) - description = "Defines the colleagues who are added to each subaccount as subaccount service administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] + description = "Defines the colleagues who are added to each subaccount as Subaccount service administrators." } +variable "service_plan__sap_build_apps" { + type = string + description = "The plan for SAP Build Apps subscription" + default = "free" + validation { + condition = contains(["free", "standard", "partner"], var.service_plan__sap_build_apps) + error_message = "Invalid value for service_plan__sap_build_apps. Only 'free', 'standard' and 'partner' are allowed." + } +} + +variable "service_plan__sap_process_automation" { + type = string + description = "The plan for SAP Build Process Automation" + default = "standard" + validation { + condition = contains(["standard", "advanced-user"], var.service_plan__sap_process_automation) + error_message = "Invalid value for service_plan__sap_process_automation. Only 'standard' and 'advanced-user' are allowed." + } +} +variable "service_plan__sap_integration_suite" { + type = string + description = "The plan for SAP Integration Suite" + default = "enterprise_agreement" + validation { + condition = contains(["enterprise_agreement"], var.service_plan__sap_integration_suite) + error_message = "Invalid value for service_plan__sap_integration_suite. Only 'enterprise_agreement' are allowed." + } +} ### # Entitlements @@ -62,21 +95,6 @@ variable "entitlements" { plan_name = "application", type = "service" }, - { - service_name = "integrationsuite" - plan_name = "enterprise_agreement", - type = "app" - }, - { - service_name = "sap-build-apps" - plan_name = "standard" - type = "service" - }, - { - service_name = "process-automation" - plan_name = "standard", - type = "app" - }, { service_name = "process-automation-service" plan_name = "standard", @@ -106,16 +124,27 @@ variable "kyma_instance" { type = object({ deletetimeout = string }) } -variable "conn_dest_admin" { +variable "conn_dest_admins" { type = list(string) description = "Connectivity and Destination Administrator" - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.conn_dest_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.conn_dest_admins) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "int_provisioner" { +variable "int_provisioners" { type = list(string) description = "Integration Provisioner" - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.int_provisioners : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.int_provisioners) + error_message = "Please enter a valid email address for the CF space managers." + } + } variable "custom_idp" { @@ -129,56 +158,80 @@ variable "custom_idp" { } } -variable "users_BuildAppsAdmin" { +variable "users_buildApps_admins" { type = list(string) description = "Defines the colleagues who have the role of 'BuildAppsAdmin' in SAP Build Apps." - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.users_buildApps_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.users_buildApps_admins) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "users_BuildAppsDeveloper" { +variable "users_buildApps_developers" { type = list(string) description = "Defines the colleagues who have the role of 'BuildAppsDeveloper' in SAP Build Apps." - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.users_buildApps_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.users_buildApps_developers) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "users_RegistryAdmin" { +variable "users_registry_admins" { type = list(string) description = "Defines the colleagues who have the role of 'RegistryAdmin' in SAP Build Apps." - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.users_registry_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.users_registry_admins) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "users_RegistryDeveloper" { +variable "users_registry_developers" { type = list(string) description = "Defines the colleagues who have the role of RegistryDeveloper' in SAP Build Apps." - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.users_registry_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.users_registry_developers) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "ProcessAutomationAdmin" { +variable "process_automation_admins" { type = list(string) description = "Defines the users who have the role of ProcessAutomationAdmin in SAP Build Process Automation" - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_admins) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "ProcessAutomationDeveloper" { +variable "process_automation_developers" { type = list(string) description = "Defines the users who have the role of ProcessAutomationDeveloper in SAP Build Process Automation" - default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_developers) + error_message = "Please enter a valid email address for the CF space managers." + } } -variable "ProcessAutomationParticipant" { +variable "process_automation_participants" { type = list(string) description = "Defines the users who have the role of ProcessAutomationParticipant in SAP Build Process Automation" default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "username" { - description = "BTP username" - type = string - sensitive = false -} -variable "password" { - description = "BTP user password" - type = string - sensitive = true -} + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_participants : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_participants) + error_message = "Please enter a valid email address for the CF space managers." + } +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/README.md b/released/discovery_center/mission_4172/README.md index 0055c17a..aaf708d9 100644 --- a/released/discovery_center/mission_4172/README.md +++ b/released/discovery_center/mission_4172/README.md @@ -19,40 +19,14 @@ The setup comprises the following resources: To deploy the resources you must: -1. Create a file `secret.auto.tfvars` and maintain the credentials for the BTP and CF provider +1. Export environment variables BTP_USERNAME, BTP_PASSWORD, CF_USER, and CF_PASSWORD with your username and password for the custom IdP of your global account. - ```hcl - username = "" - password = "" - ``` - -2. Change the variables in the `samples.tfvars` file to meet your requirements +2. Change the variables in the `samples.tfvars` file in the main folder to meet your requirements > ⚠ NOTE: You should pay attention **specifically** to the users defined in the samples.tfvars whether they already exist in your SAP BTP accounts. Otherwise you might get error messages like e.g. `Error: The user could not be found: jane.doe@test.com`. +3. Execute the apply.sh script. -3. Initialize your workspace: - - ```bash - terraform init - ``` - -4. You can check what Terraform plans to apply based on your configuration: - - ```bash - terraform plan -var-file="sample.tfvars" - ``` - -5. Apply your configuration to provision the resources: - - ```bash - terraform apply -var-file="sample.tfvars" - ``` - -## In the end - -You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the following command: +4. Verify e.g., in BTP cockpit that a new subaccount with a integration suite, SAP Business Application Studio, CF environment instance and a CF space have been created. -```bash -terraform destroy -``` +5. Clean up by running the destroy.sh script. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/apply.sh b/released/discovery_center/mission_4172/apply.sh new file mode 100755 index 00000000..fb333585 --- /dev/null +++ b/released/discovery_center/mission_4172/apply.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +cd step1 + +terraform init +terraform apply -var-file='../samples.tfvars' -auto-approve +terraform output > ../step2/step1vars.tfvars + +cd ../step2 + +terraform init +terraform apply -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/destroy.sh b/released/discovery_center/mission_4172/destroy.sh new file mode 100755 index 00000000..c149b746 --- /dev/null +++ b/released/discovery_center/mission_4172/destroy.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +cd step2 + +terraform destroy -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve +rm step1vars.tfvars + +cd ../step1 + +terraform destroy -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4172/main.tf b/released/discovery_center/mission_4172/main.tf deleted file mode 100644 index de83e6bc..00000000 --- a/released/discovery_center/mission_4172/main.tf +++ /dev/null @@ -1,173 +0,0 @@ -############################################################################################### -# Setup of names in accordance to naming convention -############################################################################################### -resource "random_uuid" "uuid" {} - -locals { - random_uuid = random_uuid.uuid.result - project_subaccount_domain = lower(replace("mission-4172-${local.random_uuid}", "_", "-")) - project_subaccount_cf_org = substr(replace("${local.project_subaccount_domain}", "-", ""), 0, 32) -} - -############################################################################################### -# Creation of subaccount -############################################################################################### -resource "btp_subaccount" "project" { - name = var.subaccount_name - subdomain = local.project_subaccount_domain - region = lower(var.region) -} - -############################################################################################### -# Assignment of users as sub account administrators -############################################################################################### -resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { - for_each = toset("${var.subaccount_admins}") - subaccount_id = btp_subaccount.project.id - role_collection_name = "Subaccount Administrator" - user_name = each.value -} - -############################################################################################### -# Assignment of users as sub account service administrators -############################################################################################### -resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { - for_each = toset("${var.subaccount_service_admins}") - subaccount_id = btp_subaccount.project.id - role_collection_name = "Subaccount Service Administrator" - user_name = each.value -} - -###################################################################### -# Creation of Cloud Foundry environment -###################################################################### -resource "btp_subaccount_environment_instance" "cf" { - subaccount_id = btp_subaccount.project.id - name = local.project_subaccount_cf_org - environment_type = "cloudfoundry" - service_name = "cloudfoundry" - plan_name = "standard" - landscape_label = var.cf_environment_label - parameters = jsonencode({ - instance_name = local.project_subaccount_cf_org - }) -} - -###################################################################### -# Entitlement of all services and apps -###################################################################### -resource "btp_subaccount_entitlement" "name" { - for_each = { - for index, entitlement in var.entitlements : - index => entitlement - } - subaccount_id = btp_subaccount.project.id - service_name = each.value.service_name - plan_name = each.value.plan_name -} - -###################################################################### -# Create service instances (and service keys when needed) -###################################################################### -# hana plan id -data "btp_subaccount_service_plan" "hana_plan" { - subaccount_id = btp_subaccount.project.id - name = "hana" - offering_name = "hana-cloud" - depends_on = [btp_subaccount_entitlement.name] -} - -# hana-cloud -resource "btp_subaccount_service_instance" "hana_instance" { - depends_on = [data.btp_subaccount_service_plan.hana_plan] - name = "hana_cloud_instance" - serviceplan_id = data.btp_subaccount_service_plan.hana_plan.id - subaccount_id = btp_subaccount.project.id - parameters = jsonencode({ "data" : { "memory" : 32, "edition" : "cloud", "systempassword" : "Abcd1234", "whitelistIPs" : ["0.0.0.0/0"] } }) -} - -###################################################################### -# Assign custom IDP to sub account -###################################################################### -resource "btp_subaccount_trust_configuration" "fully_customized" { - subaccount_id = btp_subaccount.project.id - identity_provider = var.custom_idp -} - -###################################################################### -# Create app subscriptions -###################################################################### -data "btp_subaccount_subscriptions" "all" { - subaccount_id = btp_subaccount.project.id - depends_on = [btp_subaccount_entitlement.name] -} - -resource "btp_subaccount_subscription" "app" { - subaccount_id = btp_subaccount.project.id - for_each = { - for index, entitlement in var.entitlements : - index => entitlement if contains(["app"], entitlement.type) - } - app_name = [ - for subscription in data.btp_subaccount_subscriptions.all.values : - subscription - if subscription.commercial_app_name == each.value.service_name - ][0].app_name - plan_name = each.value.plan_name - depends_on = [data.btp_subaccount_subscriptions.all, btp_subaccount_trust_configuration.fully_customized] -} - -###################################################################### -# Role Collections -###################################################################### -resource "btp_subaccount_role_collection_assignment" "bas_dev" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.appstudio_developers) - subaccount_id = btp_subaccount.project.id - role_collection_name = "Business_Application_Studio_Developer" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "bas_admn" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.appstudio_admin) - subaccount_id = btp_subaccount.project.id - role_collection_name = "Business_Application_Studio_Administrator" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "cloud_conn_admn" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.cloudconnector_admin) - subaccount_id = btp_subaccount.project.id - role_collection_name = "Cloud Connector Administrator" - user_name = each.value -} - -resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.conn_dest_admin) - subaccount_id = btp_subaccount.project.id - role_collection_name = "Connectivity and Destination Administrator" - user_name = each.value -} - -###################################################################### -# Advanced Event Mesh -###################################################################### -resource "btp_subaccount_entitlement" "aem" { - subaccount_id = btp_subaccount.project.id - service_name = "integration-suite-advanced-event-mesh" - plan_name = "default" -} - -resource "btp_subaccount_subscription" "aem_app" { - subaccount_id = btp_subaccount.project.id - app_name = "integration-suite-advanced-event-mesh" - plan_name = "default" - parameters = jsonencode({ - "admin_user_email" : var.advanced_event_mesh_admin - }) - depends_on = [btp_subaccount_entitlement.aem] -} - diff --git a/released/discovery_center/mission_4172/provider.tf b/released/discovery_center/mission_4172/provider.tf deleted file mode 100644 index f70eba0c..00000000 --- a/released/discovery_center/mission_4172/provider.tf +++ /dev/null @@ -1,18 +0,0 @@ -terraform { - required_providers { - btp = { - source = "sap/btp" - version = "~> 1.4.0" - } - } -} - -# Please checkout documentation on how best to authenticate against SAP BTP -# via the Terraform provider for SAP BTP -provider "btp" { - globalaccount = var.globalaccount - cli_server_url = var.cli_server_url - username = var.username - password = var.password -} - diff --git a/released/discovery_center/mission_4172/samples.tfvars b/released/discovery_center/mission_4172/samples.tfvars index 76816115..adf8e887 100644 --- a/released/discovery_center/mission_4172/samples.tfvars +++ b/released/discovery_center/mission_4172/samples.tfvars @@ -1,22 +1,27 @@ -# ------------------------------------------------------------------------------------------------------ -# Provider configuration -# ------------------------------------------------------------------------------------------------------ -# Your global account subdomain -globalaccount = "youraccount" -region = "us10" -subaccount_name = "Discovery Center mission - build Events-to-Business actions" -cf_environment_label = "cf-us10" -custom_idp = "abcde1234.accounts.ondemand.com" +globalaccount = "myglobalaccount" +region = "us10" +subaccount_name = "Discovery Center mission - Build Events-to-Business actions" +cf_org_name = "cf-environment" -# ------------------------------------------------------------------------------------------------------ -# Project specific configuration (please adapt!) -# ------------------------------------------------------------------------------------------------------ -subaccount_admins = ["jane.doe@test.com", "john.doe@test.com"] -subaccount_service_admins = ["jane.doe@test.com", "john.doe@test.com"] +subaccount_admins = ["john.doe@sap.com"] +subaccount_service_admins = ["john.doe@sap.com"] -advanced_event_mesh_admin = "jane.doe@test.com" +appstudio_developers = ["john.doe@sap.com"] +appstudio_admins = ["john.doe@sap.com"] +cloudconnector_admins = ["john.doe@sap.com"] +conn_dest_admins = ["john.doe@sap.com"] -appstudio_developers = ["jane.doe@test.com", "john.doe@test.com"] -appstudio_admin = ["jane.doe@test.com", "john.doe@test.com"] -cloudconnector_admin = ["jane.doe@test.com", "john.doe@test.com"] -conn_dest_admin = ["jane.doe@test.com", "john.doe@test.com"] +cf_space_developers = ["john.doe@sap.com"] +cf_space_managers = ["john.doe@sap.com"] +cf_org_admins = ["john.doe@sap.com"] +cf_org_users = ["john.doe@sap.com"] + +hana_system_password = "Abc12345" +hana_cloud_admins = ["john.doe@sap.com"] + +process_automation_admins = ["john.doe@sap.com"] +process_automation_developers = ["john.doe@sap.com"] +process_automation_participants = ["john.doe@sap.com"] + +event_mesh_admins = ["john.doe@sap.com"] +event_mesh_developers = ["john.doe@sap.com"] diff --git a/released/discovery_center/mission_4172/step1/locals.tf b/released/discovery_center/mission_4172/step1/locals.tf new file mode 100644 index 00000000..00e26833 --- /dev/null +++ b/released/discovery_center/mission_4172/step1/locals.tf @@ -0,0 +1,5 @@ +locals { + service__sap_business_app_studio = "sapappstudio" + service_name__hana_cloud_tools = "hana-cloud-tools" + service_name__sap_process_automation = "process-automation" +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/main.tf b/released/discovery_center/mission_4172/step1/main.tf new file mode 100644 index 00000000..0f4216f3 --- /dev/null +++ b/released/discovery_center/mission_4172/step1/main.tf @@ -0,0 +1,306 @@ +############################################################################################### +# Setup of names in accordance to naming convention +############################################################################################### +resource "random_uuid" "uuid" {} + +locals { + random_uuid = random_uuid.uuid.result + project_subaccount_domain = lower(replace("mission-4172-${local.random_uuid}", "_", "-")) + project_subaccount_cf_org = substr(replace("${local.project_subaccount_domain}", "-", ""), 0, 32) +} + +############################################################################################### +# Creation of subaccount +############################################################################################### +resource "btp_subaccount" "project" { + count = var.subaccount_id == "" ? 1 : 0 + + name = var.subaccount_name + subdomain = local.project_subaccount_domain + region = lower(var.region) + usage = "USED_FOR_PRODUCTION" +} + +data "btp_subaccount" "project" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.project[0].id +} + +############################################################################################### +# Assignment of users as sub account administrators +############################################################################################### +resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { + for_each = toset("${var.subaccount_admins}") + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Subaccount Administrator" + user_name = each.value +} + +############################################################################################### +# Assignment of users as sub account service administrators +############################################################################################### +resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { + for_each = toset("${var.subaccount_service_admins}") + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Subaccount Service Administrator" + user_name = each.value +} + +###################################################################### +# Extract list of CF landscape labels from environments +###################################################################### +data "btp_subaccount_environments" "all" { + subaccount_id = data.btp_subaccount.project.id +} + +locals { + cf_landscape_labels = [ + for env in data.btp_subaccount_environments.all.values : env.landscape_label + if env.environment_type == "cloudfoundry" + ] +} + + +###################################################################### +# Creation of Cloud Foundry environment +###################################################################### +resource "btp_subaccount_environment_instance" "cloudfoundry" { + subaccount_id = data.btp_subaccount.project.id + name = var.cf_org_name + environment_type = "cloudfoundry" + service_name = "cloudfoundry" + plan_name = "standard" + landscape_label = local.cf_landscape_labels[0] + parameters = jsonencode({ + instance_name = local.project_subaccount_cf_org + }) +} + +###################################################################### +# Entitlement of all general services +###################################################################### +resource "btp_subaccount_entitlement" "genentitlements" { + for_each = { + for index, entitlement in var.entitlements : + index => entitlement + } + subaccount_id = data.btp_subaccount.project.id + service_name = each.value.service_name + plan_name = each.value.plan_name +} + +# ###################################################################### +# # Create app subscription to SAP Business APplication Studio +# ###################################################################### + +resource "btp_subaccount_entitlement" "bas" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio +} + +# Create app subscription to busineass applicaiton stuido +resource "btp_subaccount_subscription" "bas" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio + depends_on = [btp_subaccount_entitlement.bas] +} + +resource "btp_subaccount_role_collection_assignment" "bas_dev" { + depends_on = [btp_subaccount_subscription.bas] + for_each = toset(var.appstudio_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Business_Application_Studio_Developer" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "bas_admn" { + depends_on = [btp_subaccount_subscription.bas] + for_each = toset(var.appstudio_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Business_Application_Studio_Administrator" + user_name = each.value +} + +###################################################################### +# Assign other Role Collection +###################################################################### + +resource "btp_subaccount_role_collection_assignment" "cloud_conn_admn" { + depends_on = [btp_subaccount_entitlement.genentitlements] + for_each = toset(var.cloudconnector_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Cloud Connector Administrator" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { + depends_on = [btp_subaccount_entitlement.genentitlements] + for_each = toset(var.conn_dest_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Connectivity and Destination Administrator" + user_name = each.value +} + +# ------------------------------------------------------------------------------------------------------ +# Entitle subaccount for usage of SAP HANA Cloud tools +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_entitlement" "hana_cloud_tools" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__hana_cloud_tools + plan_name = "tools" +} + +resource "btp_subaccount_subscription" "hana_cloud_tools" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service_name__hana_cloud_tools + plan_name = "tools" + depends_on = [btp_subaccount_entitlement.hana_cloud_tools] +} + +# Assign users to Role Collection: SAP HANA Cloud Administrator +resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { + for_each = toset(var.hana_cloud_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "SAP HANA Cloud Administrator" + user_name = each.value + depends_on = [btp_subaccount_subscription.hana_cloud_tools] +} + +# ------------------------------------------------------------------------------------------------------ +# Entitle subaccount for usage of SAP HANA Cloud +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_entitlement" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + service_name = "hana-cloud" + plan_name = "hana" +} + +# Get plan for SAP HANA Cloud +data "btp_subaccount_service_plan" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + offering_name = "hana-cloud" + name = "hana" + depends_on = [btp_subaccount_entitlement.hana_cloud] +} + +resource "btp_subaccount_service_instance" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + serviceplan_id = data.btp_subaccount_service_plan.hana_cloud.id + name = "my-hana-cloud-instance" + depends_on = [btp_subaccount_entitlement.hana_cloud] + parameters = jsonencode( + { + "data" : { + "memory" : 32, + "edition" : "cloud", + "systempassword" : "${var.hana_system_password}", + "additionalWorkers" : 0, + "disasterRecoveryMode" : "no_disaster_recovery", + "enabledservices" : { + "docstore" : false, + "dpserver" : true, + "scriptserver" : false + }, + "requestedOperation" : {}, + "serviceStopped" : false, + "slaLevel" : "standard", + "storage" : 120, + "vcpu" : 2, + "whitelistIPs" : ["0.0.0.0/0"] + } + }) + + timeouts = { + create = "45m" + update = "45m" + delete = "45m" + } +} + +# Create service binding to SAP HANA Cloud service +resource "btp_subaccount_service_binding" "hana_cloud" { + subaccount_id = data.btp_subaccount.project.id + service_instance_id = btp_subaccount_service_instance.hana_cloud.id + name = "hana-cloud-key" +} + +# ###################################################################### +# # Create app subscription to SAP Build Process Automation +# ###################################################################### + +resource "btp_subaccount_entitlement" "build_process_automation" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__sap_process_automation + plan_name = var.service_plan__sap_process_automation +} + +# Create app subscription to SAP Build Workzone, standard edition (depends on entitlement) +resource "btp_subaccount_subscription" "build_process_automation" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service_name__sap_process_automation + plan_name = var.service_plan__sap_process_automation + depends_on = [btp_subaccount_entitlement.build_process_automation] +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_admin" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationAdmin" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_dev" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationDeveloper" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "sbpa_part" { + depends_on = [btp_subaccount_subscription.build_process_automation] + for_each = toset(var.process_automation_participants) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "ProcessAutomationParticipant" + user_name = each.value +} + +###################################################################### +# Event Mesh +###################################################################### +resource "btp_subaccount_entitlement" "event_mesh" { + subaccount_id = data.btp_subaccount.project.id + service_name = "enterprise-messaging" + plan_name = "default" +} + +resource "btp_subaccount_entitlement" "event_mesh_application" { + subaccount_id = data.btp_subaccount.project.id + service_name = "enterprise-messaging-hub" + plan_name = "standard" +} + +resource "btp_subaccount_subscription" "event_mesh_application" { + subaccount_id = data.btp_subaccount.project.id + app_name = "enterprise-messaging-hub" + plan_name = "standard" + depends_on = [btp_subaccount_entitlement.event_mesh_application] +} + +resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { + depends_on = [btp_subaccount_entitlement.event_mesh_application] + for_each = toset(var.event_mesh_admins) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Enterprise Messaging Administrator" + user_name = each.value +} + +resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { + depends_on = [btp_subaccount_entitlement.event_mesh_application] + for_each = toset(var.event_mesh_developers) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Enterprise Messaging Developer" + user_name = each.value +} diff --git a/released/discovery_center/mission_4172/step1/output.tf b/released/discovery_center/mission_4172/step1/output.tf new file mode 100644 index 00000000..56f90f7b --- /dev/null +++ b/released/discovery_center/mission_4172/step1/output.tf @@ -0,0 +1,15 @@ +output "cf_landscape_label" { + value = btp_subaccount_environment_instance.cloudfoundry.landscape_label +} + +output "cf_api_url" { + value = jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"] +} + +output "cf_org_id" { + value = btp_subaccount_environment_instance.cloudfoundry.platform_id +} + +output "subaccount_id" { + value = data.btp_subaccount.project.id +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/provider.tf b/released/discovery_center/mission_4172/step1/provider.tf new file mode 100644 index 00000000..f4e6f577 --- /dev/null +++ b/released/discovery_center/mission_4172/step1/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + btp = { + source = "SAP/btp" + version = "1.4.0" + } + } +} + +###################################################################### +# Configure BTP provider +###################################################################### +provider "btp" { + cli_server_url = var.cli_server_url + globalaccount = var.globalaccount +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step1/variables.tf b/released/discovery_center/mission_4172/step1/variables.tf new file mode 100644 index 00000000..88540b91 --- /dev/null +++ b/released/discovery_center/mission_4172/step1/variables.tf @@ -0,0 +1,272 @@ +###################################################################### +# Customer account setup +###################################################################### +# subaccount +variable "globalaccount" { + type = string + description = "The globalaccount subdomain." + default = "yourglobalaccount" +} + +variable "subaccount_id" { + type = string + description = "The subaccount ID." + default = "" +} + +# subaccount +variable "subaccount_name" { + type = string + description = "The subaccount name." + default = "UC - Deliver Connected Experiences with a single view of Material Availability" +} + +# cf org name +variable "cf_org_name" { + type = string + description = "Cloud Foundry Org Name" + default = "cloud-foundry" +} + +# Region +variable "region" { + type = string + description = "The region where the project account shall be created in." + default = "us10" +} + +# CLI server +variable "cli_server_url" { + type = string + description = "The BTP CLI server URL." + default = "https://cli.btp.cloud.sap" +} + +# subaccount variables +variable "subaccount_admins" { + type = list(string) + description = "Defines the colleagues who are added to each subaccount as subaccount administrators." + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.subaccount_admins : 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 "subaccount_service_admins" { + type = list(string) + description = "Defines the colleagues who are added to each subaccount as subaccount service administrators." + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.subaccount_service_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.subaccount_service_admins) + error_message = "Please enter a valid email address for the Subaccount service Admins." + } +} + +variable "service_plan__sap_business_app_studio" { + type = string + description = "The plan for SAP Business Application Studio" + default = "standard-edition" + validation { + condition = contains(["standard-edition"], var.service_plan__sap_business_app_studio) + error_message = "Invalid value for service_plan__sap_business_app_studio. Only 'standard-edition' is allowed." + } +} + +### +# Entitlements +### +variable "entitlements" { + type = list(object({ + service_name = string + plan_name = string + type = string + })) + description = "The list of entitlements that shall be added to the subaccount." + default = [ + { + service_name = "connectivity" + plan_name = "lite", + type = "service" + }, + { + service_name = "destination" + plan_name = "lite", + type = "service" + }, + { + service_name = "html5-apps-repo" + plan_name = "app-host", + type = "service" + }, + { + service_name = "xsuaa" + plan_name = "application", + type = "service" + } + ] +} + +variable "appstudio_developers" { + type = list(string) + description = "Business Application Studio Developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Business Application Studio Developers contains a list of valid email addresses + validation { + condition = length([for email in var.appstudio_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_developers) + error_message = "Please enter a valid email address for the Business Application Studio Developers" + } +} + +variable "appstudio_admins" { + type = list(string) + description = "Business Application Studio Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Business Application Studio Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.appstudio_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.appstudio_admins) + error_message = "Please enter a valid email address for the Business Application Studio Administrators." + } +} + +variable "cloudconnector_admins" { + type = list(string) + description = "Cloud Connector Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Cloud Connector Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.cloudconnector_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cloudconnector_admins) + error_message = "Please enter a valid email address for the Cloud Connector Administrators." + } +} + +variable "conn_dest_admins" { + type = list(string) + description = "Connectivity and Destination Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Connectivity and Destination Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.conn_dest_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.conn_dest_admins) + error_message = "Please enter a valid email address for the Connectivity and Destination Administrators." + } +} + +variable "hana_cloud_admins" { + type = list(string) + description = "Defines the colleagues who are added as admins to access the instance of SAP HANA Cloud." + default = ["jane.doe@test.com", "john.doe@test.com"] + + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.hana_cloud_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.hana_cloud_admins) + error_message = "Please enter a valid email address for the admins of SAP HANA Cloud instance." + } +} + + +variable "hana_system_password" { + type = string + description = "The password of the database 'superuser' DBADMIN." + sensitive = true + + # add validation to check if the password is at least 8 characters long + validation { + condition = length(var.hana_system_password) > 7 + error_message = "The hana_system_password must be at least 8 characters long." + } + + # add validation to check if the password contains at least one upper case + validation { + condition = can(regex("[A-Z]", var.hana_system_password)) + error_message = "The hana_system_password must contain at least one upper case." + } + + # add validation to check if the password contains at least two lower case characters that can occur on arbitrary places in the string (not necessarily in a row) + validation { + condition = length(regexall("[a-z]", var.hana_system_password)) > 1 + error_message = "The hana_system_password must contain at least two lower case characters." + } + + # add validation to check if the password contains at least one numeric character + validation { + condition = can(regex("[0-9]", var.hana_system_password)) + error_message = "The hana_system_password must contain at least one numeric character." + } +} + +# Cloudfoundry environment label +variable "cf_environment_label" { + type = string + description = "The Cloudfoundry environment label" + default = "cf-us10" +} + +variable "service_plan__sap_process_automation" { + type = string + description = "The plan for SAP Build Process Automation" + default = "standard" + validation { + condition = contains(["standard", "advanced-user"], var.service_plan__sap_process_automation) + error_message = "Invalid value for service_plan__sap_process_automation. Only 'standard' and 'advanced-user' are allowed." + } +} + + +variable "process_automation_admins" { + type = list(string) + description = "SAP Build Process Automation Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if SAP Build Process Automation Administrators contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_admins) + error_message = "Please enter a valid email address for the SAP Build Process Automation Administrators." + } +} + +variable "process_automation_developers" { + type = list(string) + description = "SAP Build Process Automation Developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if SAP Build Process Automation Developers contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_developers) + error_message = "Please enter a valid email address for the SAP Build Process Automation Developers." + } +} + +variable "process_automation_participants" { + type = list(string) + description = "SAP Build Process Automation Participants" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if SAP Build Process Automation Participants contains a list of valid email addresses + validation { + condition = length([for email in var.process_automation_participants : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.process_automation_participants) + error_message = "Please enter a valid email address for the SAP Build Process Automation Participants." + } +} + +variable "event_mesh_admins" { + type = list(string) + description = "Enterprise Messaging Administrators" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if admins contains a list of valid email addresses + validation { + condition = length([for email in var.event_mesh_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_admins) + error_message = "Please enter a valid email address for the Enterprise Messaging Administrators." + } +} + +variable "event_mesh_developers" { + type = list(string) + description = "Enterprise Messaging Developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if Enterprise Messaging Developers contains a list of valid email addresses + validation { + condition = length([for email in var.event_mesh_developers : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.event_mesh_developers) + error_message = "Please enter a valid email address for the Enterprise Messaging Developers." + } +} + + diff --git a/released/discovery_center/mission_4172/step2/main.tf b/released/discovery_center/mission_4172/step2/main.tf new file mode 100644 index 00000000..b4812ee4 --- /dev/null +++ b/released/discovery_center/mission_4172/step2/main.tf @@ -0,0 +1,40 @@ +###################################################################### +# Create space using CF provider +###################################################################### +resource "cloudfoundry_space" "dev" { + name = "DEV" + org = var.cf_org_id +} + +###################################################################### +# add org and space users and managers +###################################################################### +resource "cloudfoundry_org_role" "organization_user" { + for_each = toset(var.cf_org_users) + username = each.value + type = "organization_user" + org = var.cf_org_id +} + +resource "cloudfoundry_org_role" "organization_manager" { + for_each = toset(var.cf_org_admins) + username = each.value + type = "organization_manager" + org = var.cf_org_id +} + +resource "cloudfoundry_space_role" "space_developer" { + for_each = toset(var.cf_space_developers) + username = each.value + type = "space_developer" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} + +resource "cloudfoundry_space_role" "space_manager" { + for_each = toset(var.cf_space_managers) + username = each.value + type = "space_manager" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step2/output.tf b/released/discovery_center/mission_4172/step2/output.tf new file mode 100644 index 00000000..ad4178cd --- /dev/null +++ b/released/discovery_center/mission_4172/step2/output.tf @@ -0,0 +1,19 @@ +output "subaccount_id" { + value = var.subaccount_id +} + +output "cf_landscape_label" { + value = var.cf_landscape_label +} + +output "cf_org_id" { + value = var.cf_org_id +} + +output "cf_api_url" { + value = var.cf_api_url +} + +output "cf_space_name" { + value = cloudfoundry_space.dev.name +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step2/provider.tf b/released/discovery_center/mission_4172/step2/provider.tf new file mode 100644 index 00000000..9337283b --- /dev/null +++ b/released/discovery_center/mission_4172/step2/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + cloudfoundry = { + source = "SAP/cloudfoundry" + version = "0.2.1-beta" + } + } +} + +###################################################################### +# Configure CF provider +###################################################################### +provider "cloudfoundry" { + # resolve API URL from environment instance + api_url = var.cf_api_url +} \ No newline at end of file diff --git a/released/discovery_center/mission_4172/step2/variables.tf b/released/discovery_center/mission_4172/step2/variables.tf new file mode 100644 index 00000000..0b435101 --- /dev/null +++ b/released/discovery_center/mission_4172/step2/variables.tf @@ -0,0 +1,59 @@ +variable "cf_api_url" { + type = string +} + +variable "cf_landscape_label" { + type = string +} + +variable "cf_org_id" { + type = string +} + +variable "subaccount_id" { + type = string +} + +variable "cf_space_developers" { + type = list(string) + description = "CF Space developers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Space developers 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) + error_message = "Please enter a valid email address for the CF Space developers." + } +} + +variable "cf_space_managers" { + type = list(string) + description = "CF Space managers" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Space managers 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) + error_message = "Please enter a valid email address for the Cloud Connector Administrators." + } +} + +variable "cf_org_admins" { + type = list(string) + description = "CF Org Admins" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Org Admins contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_admins : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_admins) + error_message = "Please enter a valid email address for the CF Org Admins." + } +} + +variable "cf_org_users" { + type = list(string) + description = "CF Org Users" + default = ["jane.doe@test.com", "john.doe@test.com"] + # add validation to check if CF Org Users contains a list of valid email addresses + validation { + condition = length([for email in var.cf_org_users : can(regex("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$", email))]) == length(var.cf_org_users) + error_message = "Please enter a valid email address for the CF Org Users." + } +} diff --git a/released/discovery_center/mission_4172/variables.tf b/released/discovery_center/mission_4172/variables.tf deleted file mode 100644 index d69a99d6..00000000 --- a/released/discovery_center/mission_4172/variables.tf +++ /dev/null @@ -1,163 +0,0 @@ -###################################################################### -# Customer account setup -###################################################################### -# subaccount -variable "globalaccount" { - type = string - description = "The globalaccount subdomain." - default = "yourglobalaccount" -} -# subaccount -variable "subaccount_name" { - type = string - description = "The subaccount name." - default = "UC - Events to Business Actions" -} -# Region -variable "region" { - type = string - description = "The region where the project account shall be created in." - default = "us10" -} - -# hana password -variable "hana_cloud_system_password" { - type = string - description = "The system password for the hana_cloud service instance." - default = "Abcd1234" -} - -# CLI server -variable "cli_server_url" { - type = string - description = "The BTP CLI server URL." - default = "https://cpcli.cf.eu10.hana.ondemand.com" -} - -variable "subaccount_admins" { - type = list(string) - description = "Defines the colleagues who are added to each subaccount as subaccount administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "subaccount_service_admins" { - type = list(string) - description = "Defines the colleagues who are added to each subaccount as subaccount service administrators." - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "advanced_event_mesh_admin" { - type = string - description = "Defines the colleagues who are Cloudfoundry org auditors" - default = "jane.doe@test.com" -} - -variable "appstudio_developers" { - type = list(string) - description = "Business Application Studio Developer" - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "appstudio_admin" { - type = list(string) - description = "Business Application Studio Administrator" - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "cloudconnector_admin" { - type = list(string) - description = "Cloud Connector Administrator" - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -variable "conn_dest_admin" { - type = list(string) - description = "Connectivity and Destination Administrator" - default = ["jane.doe@test.com", "john.doe@test.com"] -} - -### -# Entitlements -### -variable "entitlements" { - type = list(object({ - service_name = string - plan_name = string - type = string - })) - description = "The list of entitlements that shall be added to the subaccount." - default = [ - { - service_name = "connectivity" - plan_name = "lite", - type = "service" - }, - { - service_name = "destination" - plan_name = "lite", - type = "service" - }, - { - service_name = "html5-apps-repo" - plan_name = "app-host", - type = "service" - }, - { - service_name = "sapappstudio" - plan_name = "standard-edition", - type = "app" - }, - { - service_name = "xsuaa" - plan_name = "application", - type = "service" - }, - { - service_name = "hana" - plan_name = "hdi-shared", - type = "service" - }, - { - service_name = "hana-cloud" - plan_name = "hana", - type = "service" - } - ] -} - -# variable "advanced_event_mesh" { -# service_name = "integration-suite-advanced-event-mesh" -# } - -variable "username" { - description = "BTP username" - type = string - sensitive = false - -} - -variable "password" { - description = "BTP user password" - type = string - sensitive = true -} - -variable "custom_idp" { - type = string - description = "Defines the custom IDP to be used for the subaccount" - default = "terraformint" - - validation { - condition = can(regex("^[a-z-]", var.custom_idp)) - error_message = "Please enter a valid entry for the custom-idp of the subaccount." - } -} - -# Cloudfoundry environment label -variable "cf_environment_label" { - type = string - description = "The Cloudfoundry environment label" - default = "cf-us10" -} - - diff --git a/released/discovery_center/mission_4356/README.md b/released/discovery_center/mission_4356/README.md index 9936cf77..2fc17e02 100644 --- a/released/discovery_center/mission_4356/README.md +++ b/released/discovery_center/mission_4356/README.md @@ -19,40 +19,15 @@ The setup comprises the following resources: To deploy the resources you must: -1. Create a file `secret.auto.tfvars` and maintain the credentials for the BTP and CF provider +1. Export environment variables BTP_USERNAME, BTP_PASSWORD, CF_USER, and CF_PASSWORD with your username and password for the custom IdP of your global account. - ```hcl - username = "" - password = "" - ``` - -2. Change the variables in the `samples.tfvars` file to meet your requirements +2. Change the variables in the `samples.tfvars` file in the main folder to meet your requirements > ⚠ NOTE: You should pay attention **specifically** to the users defined in the samples.tfvars whether they already exist in your SAP BTP accounts. Otherwise you might get error messages like e.g. `Error: The user could not be found: jane.doe@test.com`. +3. Execute the apply.sh script. -3. Initialize your workspace: - - ```bash - terraform init - ``` - -4. You can check what Terraform plans to apply based on your configuration: - - ```bash - terraform plan -var-file="sample.tfvars" - ``` - -5. Apply your configuration to provision the resources: - - ```bash - terraform apply -var-file="sample.tfvars" - ``` - -## In the end +4. Verify e.g., in BTP cockpit that a new subaccount with a integration suite, SAP Business Application Studio, CF environment instance and a CF space have been created. -You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the following command: +5. Clean up by running the destroy.sh script. -```bash -terraform destroy -``` diff --git a/released/discovery_center/mission_4356/apply.sh b/released/discovery_center/mission_4356/apply.sh new file mode 100755 index 00000000..fb333585 --- /dev/null +++ b/released/discovery_center/mission_4356/apply.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +cd step1 + +terraform init +terraform apply -var-file='../samples.tfvars' -auto-approve +terraform output > ../step2/step1vars.tfvars + +cd ../step2 + +terraform init +terraform apply -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4356/destroy.sh b/released/discovery_center/mission_4356/destroy.sh new file mode 100755 index 00000000..549e1c4e --- /dev/null +++ b/released/discovery_center/mission_4356/destroy.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +cd step-2 + +terraform destroy -var-file=step1vars.tfvars -var-file='../samples.tfvars' -auto-approve +rm samples.tfvars + +cd ../step-1 + +terraform destroy -var-file='../samples.tfvars' -auto-approve + +cd .. \ No newline at end of file diff --git a/released/discovery_center/mission_4356/provider.tf b/released/discovery_center/mission_4356/provider.tf deleted file mode 100644 index 8eba4d6d..00000000 --- a/released/discovery_center/mission_4356/provider.tf +++ /dev/null @@ -1,19 +0,0 @@ -terraform { - required_providers { - btp = { - source = "sap/btp" - version = "~> 1.4.0" - } - } -} - -# Please checkout documentation on how best to authenticate against SAP BTP -# via the Terraform provider for SAP BTP -provider "btp" { - globalaccount = var.globalaccount - cli_server_url = var.cli_server_url - username = var.username - password = var.password -} - - diff --git a/released/discovery_center/mission_4356/samples.tfvars b/released/discovery_center/mission_4356/samples.tfvars index cef35613..43b5f802 100644 --- a/released/discovery_center/mission_4356/samples.tfvars +++ b/released/discovery_center/mission_4356/samples.tfvars @@ -1,20 +1,18 @@ -# ------------------------------------------------------------------------------------------------------ -# Provider configuration -# ------------------------------------------------------------------------------------------------------ -# Your global account subdomain -globalaccount = "youraccount" -region = "us10" -subaccount_name = "Discovery Center mission - build Events-to-Business actions" -cf_environment_label = "cf-us10" +globalaccount = "ticoo" +region = "us10" +subaccount_name = "Discovery Center mission - Deliver Connected Experiences with a single view of Material Availability" +cf_org_name = "cf-environment" -# ------------------------------------------------------------------------------------------------------ -# Project specific configuration (please adapt!) -# ------------------------------------------------------------------------------------------------------ -subaccount_admins = ["jane.doe@test.com", "john.doe@test.com"] -subaccount_service_admins = ["jane.doe@test.com", "john.doe@test.com"] +subaccount_admins = ["m.palavalli1@sap.com"] +subaccount_service_admins = ["m.palavalli1@sap.com"] -appstudio_developers = ["jane.doe@test.com", "john.doe@test.com"] -appstudio_admin = ["jane.doe@test.com", "john.doe@test.com"] -cloudconnector_admin = ["jane.doe@test.com", "john.doe@test.com"] -conn_dest_admin = ["jane.doe@test.com", "john.doe@test.com"] -int_provisioner = ["jane.doe@test.com", "john.doe@test.com"] +appstudio_developers = ["m.palavalli@sap.com", "m.palavalli1@sap.com"] +appstudio_admin = ["m.palavalli@sap.com", "m.palavalli1@sap.com"] +cloudconnector_admin = ["m.palavalli@sap.com", "m.palavalli1@sap.com"] +conn_dest_admin = ["m.palavalli@sap.com", "m.palavalli1@sap.com"] +int_provisioner = ["m.palavalli@sap.com", "m.palavalli1@sap.com"] + +cf_space_developers = ["m.palavalli1@sap.com"] +cf_space_managers = ["m.palavalli1@sap.com"] +cf_org_admins = ["m.palavalli1@sap.com"] +cf_org_users = ["m.palavalli1@sap.com"] diff --git a/released/discovery_center/mission_4356/step1/locals.tf b/released/discovery_center/mission_4356/step1/locals.tf new file mode 100644 index 00000000..0663eaea --- /dev/null +++ b/released/discovery_center/mission_4356/step1/locals.tf @@ -0,0 +1,4 @@ +locals { + service__sap_business_app_studio = "sapappstudio" + service_name__sap_integration_suite = "integrationsuite" +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/main.tf b/released/discovery_center/mission_4356/step1/main.tf similarity index 57% rename from released/discovery_center/mission_4356/main.tf rename to released/discovery_center/mission_4356/step1/main.tf index cbe1c661..5facadde 100644 --- a/released/discovery_center/mission_4356/main.tf +++ b/released/discovery_center/mission_4356/step1/main.tf @@ -13,9 +13,16 @@ locals { # Creation of subaccount ############################################################################################### resource "btp_subaccount" "project" { + count = var.subaccount_id == "" ? 1 : 0 + name = var.subaccount_name subdomain = local.project_subaccount_domain region = lower(var.region) + usage = "USED_FOR_PRODUCTION" +} + +data "btp_subaccount" "project" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.project[0].id } ############################################################################################### @@ -23,7 +30,7 @@ resource "btp_subaccount" "project" { ############################################################################################### resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { for_each = toset("${var.subaccount_admins}") - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Subaccount Administrator" user_name = each.value } @@ -33,102 +40,137 @@ resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { ############################################################################################### resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" { for_each = toset("${var.subaccount_service_admins}") - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Subaccount Service Administrator" user_name = each.value } +###################################################################### +# Extract list of CF landscape labels from environments +###################################################################### +data "btp_subaccount_environments" "all" { + subaccount_id = data.btp_subaccount.project.id +} + +locals { + cf_landscape_labels = [ + for env in data.btp_subaccount_environments.all.values : env.landscape_label + if env.environment_type == "cloudfoundry" + ] +} + + ###################################################################### # Creation of Cloud Foundry environment ###################################################################### -resource "btp_subaccount_environment_instance" "cf" { - subaccount_id = btp_subaccount.project.id - name = local.project_subaccount_cf_org +resource "btp_subaccount_environment_instance" "cloudfoundry" { + subaccount_id = data.btp_subaccount.project.id + name = var.cf_org_name environment_type = "cloudfoundry" service_name = "cloudfoundry" plan_name = "standard" - landscape_label = var.cf_environment_label + landscape_label = local.cf_landscape_labels[0] parameters = jsonencode({ instance_name = local.project_subaccount_cf_org }) } ###################################################################### -# Entitlement of all services +# Entitlement of all general services ###################################################################### -resource "btp_subaccount_entitlement" "name" { +resource "btp_subaccount_entitlement" "genentitlements" { for_each = { for index, entitlement in var.entitlements : index => entitlement } - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id service_name = each.value.service_name plan_name = each.value.plan_name } ###################################################################### -# Create app subscriptions +# Create app subscription to SAP Integration Suite ###################################################################### +resource "btp_subaccount_entitlement" "sap_integration_suite" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service_name__sap_integration_suite + plan_name = var.service_plan__sap_integration_suite +} + data "btp_subaccount_subscriptions" "all" { - subaccount_id = btp_subaccount.project.id - depends_on = [btp_subaccount_entitlement.name] + subaccount_id = data.btp_subaccount.project.id + depends_on = [btp_subaccount_entitlement.sap_integration_suite] } -resource "btp_subaccount_subscription" "app" { - subaccount_id = btp_subaccount.project.id - for_each = { - for index, entitlement in var.entitlements : - index => entitlement if contains(["app"], entitlement.type) - } +resource "btp_subaccount_subscription" "sap_integration_suite" { + subaccount_id = data.btp_subaccount.project.id app_name = [ for subscription in data.btp_subaccount_subscriptions.all.values : subscription - if subscription.commercial_app_name == each.value.service_name + if subscription.commercial_app_name == local.service_name__sap_integration_suite ][0].app_name - plan_name = each.value.plan_name + plan_name = var.service_plan__sap_integration_suite depends_on = [data.btp_subaccount_subscriptions.all] } -###################################################################### -# Assign Role Collection -###################################################################### +resource "btp_subaccount_role_collection_assignment" "int_prov" { + depends_on = [btp_subaccount_subscription.sap_integration_suite] + for_each = toset(var.int_provisioner) + subaccount_id = data.btp_subaccount.project.id + role_collection_name = "Integration_Provisioner" + user_name = each.value +} + +# ###################################################################### +# # Create app subscription to SAP Business APplication Studio +# ###################################################################### + +resource "btp_subaccount_entitlement" "bas" { + subaccount_id = data.btp_subaccount.project.id + service_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio +} + +# Create app subscription to busineass applicaiton stuido +resource "btp_subaccount_subscription" "bas" { + subaccount_id = data.btp_subaccount.project.id + app_name = local.service__sap_business_app_studio + plan_name = var.service_plan__sap_business_app_studio + depends_on = [btp_subaccount_entitlement.bas] +} resource "btp_subaccount_role_collection_assignment" "bas_dev" { - depends_on = [btp_subaccount_subscription.app] + depends_on = [btp_subaccount_subscription.bas] for_each = toset(var.appstudio_developers) - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Business_Application_Studio_Developer" user_name = each.value } resource "btp_subaccount_role_collection_assignment" "bas_admn" { - depends_on = [btp_subaccount_subscription.app] + depends_on = [btp_subaccount_subscription.bas] for_each = toset(var.appstudio_admin) - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Business_Application_Studio_Administrator" user_name = each.value } +###################################################################### +# Assign Role Collection +###################################################################### + resource "btp_subaccount_role_collection_assignment" "cloud_conn_admn" { - depends_on = [btp_subaccount_subscription.app] + depends_on = [btp_subaccount_entitlement.genentitlements] for_each = toset(var.cloudconnector_admin) - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Cloud Connector Administrator" user_name = each.value } resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { - depends_on = [btp_subaccount_subscription.app] + depends_on = [btp_subaccount_entitlement.genentitlements] for_each = toset(var.conn_dest_admin) - subaccount_id = btp_subaccount.project.id + subaccount_id = data.btp_subaccount.project.id role_collection_name = "Connectivity and Destination Administrator" user_name = each.value } - -resource "btp_subaccount_role_collection_assignment" "int_prov" { - depends_on = [btp_subaccount_subscription.app] - for_each = toset(var.int_provisioner) - subaccount_id = btp_subaccount.project.id - role_collection_name = "Integration_Provisioner" - user_name = each.value -} diff --git a/released/discovery_center/mission_4356/step1/output.tf b/released/discovery_center/mission_4356/step1/output.tf new file mode 100644 index 00000000..56f90f7b --- /dev/null +++ b/released/discovery_center/mission_4356/step1/output.tf @@ -0,0 +1,15 @@ +output "cf_landscape_label" { + value = btp_subaccount_environment_instance.cloudfoundry.landscape_label +} + +output "cf_api_url" { + value = jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"] +} + +output "cf_org_id" { + value = btp_subaccount_environment_instance.cloudfoundry.platform_id +} + +output "subaccount_id" { + value = data.btp_subaccount.project.id +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/step1/provider.tf b/released/discovery_center/mission_4356/step1/provider.tf new file mode 100644 index 00000000..f4e6f577 --- /dev/null +++ b/released/discovery_center/mission_4356/step1/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + btp = { + source = "SAP/btp" + version = "1.4.0" + } + } +} + +###################################################################### +# Configure BTP provider +###################################################################### +provider "btp" { + cli_server_url = var.cli_server_url + globalaccount = var.globalaccount +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/variables.tf b/released/discovery_center/mission_4356/step1/variables.tf similarity index 76% rename from released/discovery_center/mission_4356/variables.tf rename to released/discovery_center/mission_4356/step1/variables.tf index 32ddd923..4cf8a08e 100644 --- a/released/discovery_center/mission_4356/variables.tf +++ b/released/discovery_center/mission_4356/step1/variables.tf @@ -7,12 +7,27 @@ variable "globalaccount" { description = "The globalaccount subdomain." default = "yourglobalaccount" } + +variable "subaccount_id" { + type = string + description = "The subaccount ID." + default = "" +} + # subaccount variable "subaccount_name" { type = string description = "The subaccount name." default = "UC - Deliver Connected Experiences with a single view of Material Availability" } + +# cf org name +variable "cf_org_name" { + type = string + description = "Cloud Foundry Org Name" + default = "cloud-foundry" +} + # Region variable "region" { type = string @@ -34,6 +49,7 @@ variable "cli_server_url" { default = "https://cpcli.cf.eu10.hana.ondemand.com" } +# subaccount variables variable "subaccount_admins" { type = list(string) description = "Defines the colleagues who are added to each subaccount as subaccount administrators." @@ -46,6 +62,25 @@ variable "subaccount_service_admins" { default = ["jane.doe@test.com", "john.doe@test.com"] } +variable "service_plan__sap_integration_suite" { + type = string + description = "The plan for SAP Integration Suite" + default = "enterprise_agreement" + validation { + condition = contains(["enterprise_agreement"], var.service_plan__sap_integration_suite) + error_message = "Invalid value for service_plan__sap_integration_suite. Only 'enterprise_agreement' is allowed." + } +} + +variable "service_plan__sap_business_app_studio" { + type = string + description = "The plan for SAP Business Application Studio" + default = "standard-edition" + validation { + condition = contains(["standard-edition"], var.service_plan__sap_business_app_studio) + error_message = "Invalid value for service_plan__sap_business_app_studio. Only 'standard-edition' is allowed." + } +} ### # Entitlements @@ -73,20 +108,10 @@ variable "entitlements" { plan_name = "app-host", type = "service" }, - { - service_name = "sapappstudio" - plan_name = "standard-edition", - type = "app" - }, { service_name = "xsuaa" plan_name = "application", type = "service" - }, - { - service_name = "integrationsuite" - plan_name = "enterprise_agreement", - type = "app" } ] } @@ -121,19 +146,6 @@ variable "int_provisioner" { default = ["jane.doe@test.com", "john.doe@test.com"] } -variable "username" { - description = "BTP username" - type = string - sensitive = false - -} - -variable "password" { - description = "BTP user password" - type = string - sensitive = true -} - # Cloudfoundry environment label variable "cf_environment_label" { type = string diff --git a/released/discovery_center/mission_4356/step2/main.tf b/released/discovery_center/mission_4356/step2/main.tf new file mode 100644 index 00000000..b4812ee4 --- /dev/null +++ b/released/discovery_center/mission_4356/step2/main.tf @@ -0,0 +1,40 @@ +###################################################################### +# Create space using CF provider +###################################################################### +resource "cloudfoundry_space" "dev" { + name = "DEV" + org = var.cf_org_id +} + +###################################################################### +# add org and space users and managers +###################################################################### +resource "cloudfoundry_org_role" "organization_user" { + for_each = toset(var.cf_org_users) + username = each.value + type = "organization_user" + org = var.cf_org_id +} + +resource "cloudfoundry_org_role" "organization_manager" { + for_each = toset(var.cf_org_admins) + username = each.value + type = "organization_manager" + org = var.cf_org_id +} + +resource "cloudfoundry_space_role" "space_developer" { + for_each = toset(var.cf_space_developers) + username = each.value + type = "space_developer" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} + +resource "cloudfoundry_space_role" "space_manager" { + for_each = toset(var.cf_space_managers) + username = each.value + type = "space_manager" + space = cloudfoundry_space.dev.id + depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/step2/output.tf b/released/discovery_center/mission_4356/step2/output.tf new file mode 100644 index 00000000..ad4178cd --- /dev/null +++ b/released/discovery_center/mission_4356/step2/output.tf @@ -0,0 +1,19 @@ +output "subaccount_id" { + value = var.subaccount_id +} + +output "cf_landscape_label" { + value = var.cf_landscape_label +} + +output "cf_org_id" { + value = var.cf_org_id +} + +output "cf_api_url" { + value = var.cf_api_url +} + +output "cf_space_name" { + value = cloudfoundry_space.dev.name +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/step2/provider.tf b/released/discovery_center/mission_4356/step2/provider.tf new file mode 100644 index 00000000..9337283b --- /dev/null +++ b/released/discovery_center/mission_4356/step2/provider.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + cloudfoundry = { + source = "SAP/cloudfoundry" + version = "0.2.1-beta" + } + } +} + +###################################################################### +# Configure CF provider +###################################################################### +provider "cloudfoundry" { + # resolve API URL from environment instance + api_url = var.cf_api_url +} \ No newline at end of file diff --git a/released/discovery_center/mission_4356/step2/variables.tf b/released/discovery_center/mission_4356/step2/variables.tf new file mode 100644 index 00000000..438dc703 --- /dev/null +++ b/released/discovery_center/mission_4356/step2/variables.tf @@ -0,0 +1,39 @@ +variable "cf_api_url" { + type = string +} + +variable "cf_landscape_label" { + type = string +} + +variable "cf_org_id" { + type = string +} + +variable "subaccount_id" { + type = string +} + +variable "cf_space_developers" { + type = list(string) + description = "CF Space developers" + default = ["jane.doe@test.com", "john.doe@test.com"] +} + +variable "cf_space_managers" { + type = list(string) + description = "CF Space managers" + default = ["jane.doe@test.com", "john.doe@test.com"] +} + +variable "cf_org_admins" { + type = list(string) + description = "CF Org Admins" + default = ["jane.doe@test.com", "john.doe@test.com"] +} + +variable "cf_org_users" { + type = list(string) + description = "CF Org Users" + default = ["jane.doe@test.com", "john.doe@test.com"] +}