From 10cc19c32bcaedd725c86e9c74bce25feac18a4c Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Thu, 19 Sep 2024 14:06:20 +0530 Subject: [PATCH 1/8] 3501 - Polished for QAS --- .../discovery_center/mission_3501/README.md | 32 --- .../discovery_center/mission_3501/apply.sh | 14 - .../discovery_center/mission_3501/destroy.sh | 12 - .../mission_3501/step1/README.md | 62 +++++ .../mission_3501/step1/locals.tf | 5 - .../mission_3501/step1/main.tf | 249 ++++++++++-------- .../mission_3501/step1/outputs.tf | 21 +- .../{samples.tfvars => step1/sample.tfvars} | 8 +- .../mission_3501/step1/variables.tf | 128 +++++---- .../mission_3501/step2/README.md | 39 +++ .../mission_3501/step2/main.tf | 57 +++- .../mission_3501/step2/outputs.tf | 19 -- .../mission_3501/step2/provider.tf | 16 +- .../mission_3501/step2/variables.tf | 38 ++- 14 files changed, 430 insertions(+), 270 deletions(-) delete mode 100644 released/discovery_center/mission_3501/README.md delete mode 100755 released/discovery_center/mission_3501/apply.sh delete mode 100755 released/discovery_center/mission_3501/destroy.sh create mode 100644 released/discovery_center/mission_3501/step1/README.md delete mode 100644 released/discovery_center/mission_3501/step1/locals.tf rename released/discovery_center/mission_3501/{samples.tfvars => step1/sample.tfvars} (77%) create mode 100644 released/discovery_center/mission_3501/step2/README.md delete mode 100644 released/discovery_center/mission_3501/step2/outputs.tf diff --git a/released/discovery_center/mission_3501/README.md b/released/discovery_center/mission_3501/README.md deleted file mode 100644 index b39d69cb..00000000 --- a/released/discovery_center/mission_3501/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# 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 deleted file mode 100755 index fb333585..00000000 --- a/released/discovery_center/mission_3501/apply.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/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 deleted file mode 100755 index c149b746..00000000 --- a/released/discovery_center/mission_3501/destroy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/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/step1/README.md b/released/discovery_center/mission_3501/step1/README.md new file mode 100644 index 00000000..e8238175 --- /dev/null +++ b/released/discovery_center/mission_3501/step1/README.md @@ -0,0 +1,62 @@ +# Discovery Center Mission: Enhance core ERP business processes with resilient applications on SAP BTP (3501) - Step 1 + +## 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. Set your credentials as environment variables + + ```bash + export BTP_USERNAME ='' + export BTP_PASSWORD ='' + export CF_USER ='' + export CF_PASSWORD ='' + ``` + +2. Change the variables in the `sample.tfvars` file in the main folder to meet your requirements + + > The minimal set of parameters you should specify (besides user_email and password) is global account (i.e. its subdomain) and the used custom_idp and all user assignments + + > ⚠ NOTE: You should pay attention **specifically** to the users defined in the sample.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. 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: + +```bash +terraform destroy -var-file="sample.tfvars" +``` \ No newline at end of file diff --git a/released/discovery_center/mission_3501/step1/locals.tf b/released/discovery_center/mission_3501/step1/locals.tf deleted file mode 100644 index 90bebd94..00000000 --- a/released/discovery_center/mission_3501/step1/locals.tf +++ /dev/null @@ -1,5 +0,0 @@ -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 index 80424d5a..67782f2a 100644 --- a/released/discovery_center/mission_3501/step1/main.tf +++ b/released/discovery_center/mission_3501/step1/main.tf @@ -1,102 +1,117 @@ -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # 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) + random_uuid = random_uuid.uuid.result + subaccount_domain = lower(replace("mission-3501-${local.random_uuid}", "_", "-")) + subaccount_cf_org = "cf-${random_uuid.uuid.result}" +} + +# ------------------------------------------------------------------------------------------------------ +# Subscriptions +# ------------------------------------------------------------------------------------------------------ + +locals { + service__sap_business_app_studio = "sapappstudio" + service_name__hana_cloud_tools = "hana-cloud-tools" + service_name__build_workzone = "SAPLaunchpad" } -############################################################################################### +# ------------------------------------------------------------------------------------------------------ # Creation of subaccount -############################################################################################### -resource "btp_subaccount" "project" { +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount" "dc_mission" { count = var.subaccount_id == "" ? 1 : 0 name = var.subaccount_name - subdomain = local.project_subaccount_domain + subdomain = local.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 +data "btp_subaccount" "dc_mission" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.dc_mission[0].id +} + +# ------------------------------------------------------------------------------------------------------ +# Assign custom IDP to sub account (if custom_idp is set) +# ------------------------------------------------------------------------------------------------------ +resource "btp_subaccount_trust_configuration" "fully_customized" { + # Only create trust configuration if custom_idp has been set + count = var.custom_idp == "" ? 0 : 1 + subaccount_id = data.btp_subaccount.dc_mission.id + identity_provider = var.custom_idp } -############################################################################################### +locals { + custom_idp_tenant = var.custom_idp != "" ? element(split(".", var.custom_idp), 0) : "" + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.default" + origin_key_app_users = var.custom_idp != "" ? var.custom_idp_apps_origin_key : "sap.default" +} + +# ------------------------------------------------------------------------------------------------------ # 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 + for_each = toset(var.subaccount_admins) + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Administrator" + origin = local.origin_key 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 + for_each = toset(var.subaccount_service_admins) + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Service Administrator" + origin = local.origin_key user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # Extract list of CF landscape labels from environments -###################################################################### +# ------------------------------------------------------------------------------------------------------ data "btp_subaccount_environments" "all" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id } # Take the landscape label from the first CF environment if no environment label is provided resource "terraform_data" "cf_landscape_label" { input = length(var.cf_landscape_label) > 0 ? var.cf_landscape_label : [for env in data.btp_subaccount_environments.all.values : env if env.service_name == "cloudfoundry" && env.environment_type == "cloudfoundry"][0].landscape_label } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # Creation of Cloud Foundry environment -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_environment_instance" "cloudfoundry" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id name = var.cf_org_name environment_type = "cloudfoundry" service_name = "cloudfoundry" plan_name = "standard" landscape_label = terraform_data.cf_landscape_label.output parameters = jsonencode({ - instance_name = local.project_subaccount_cf_org + instance_name = local.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 + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service__sap_business_app_studio plan_name = var.service_plan__sap_business_app_studio depends_on = [btp_subaccount_entitlement.bas] @@ -105,36 +120,18 @@ resource "btp_subaccount_subscription" "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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Business_Application_Studio_Developer" + origin = local.origin_key_app_users 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 + subaccount_id = data.btp_subaccount.dc_mission.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" + origin = local.origin_key_app_users user_name = each.value } @@ -142,13 +139,13 @@ resource "btp_subaccount_role_collection_assignment" "conn_dest_admn" { # Entitle subaccount for usage of SAP HANA Cloud tools # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud_tools" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service_name__hana_cloud_tools plan_name = "tools" depends_on = [btp_subaccount_entitlement.hana_cloud_tools] @@ -157,9 +154,10 @@ resource "btp_subaccount_subscription" "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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "SAP HANA Cloud Administrator" user_name = each.value + origin = local.origin_key_app_users depends_on = [btp_subaccount_subscription.hana_cloud_tools] } @@ -167,21 +165,21 @@ resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { # Entitle subaccount for usage of SAP HANA Cloud # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id serviceplan_id = data.btp_subaccount_service_plan.hana_cloud.id name = "my-hana-cloud-instance" depends_on = [btp_subaccount_entitlement.hana_cloud] @@ -216,28 +214,28 @@ resource "btp_subaccount_service_instance" "hana_cloud" { # Create service binding to SAP HANA Cloud service resource "btp_subaccount_service_binding" "hana_cloud" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging" plan_name = "default" } resource "btp_subaccount_entitlement" "event_mesh_application" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging-hub" plan_name = "standard" } resource "btp_subaccount_subscription" "event_mesh_application" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = "enterprise-messaging-hub" plan_name = "standard" depends_on = [btp_subaccount_entitlement.event_mesh_application] @@ -246,30 +244,32 @@ resource "btp_subaccount_subscription" "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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Administrator" + origin = local.origin_key_app_users 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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Developer" + origin = local.origin_key_app_users user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # CI CD -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "cicd" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "cicd-app" plan_name = "default" } resource "btp_subaccount_subscription" "cicd" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = "cicd-app" plan_name = "default" depends_on = [btp_subaccount_entitlement.cicd] @@ -279,35 +279,36 @@ resource "btp_subaccount_subscription" "cicd" { 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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "CICD Service Administrator" + origin = local.origin_key_app_users user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # alm-ts -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "alm_ts" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "alm-ts" plan_name = "standard" } resource "btp_subaccount_subscription" "alm_ts" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id name = "TMS Admin" depends_on = [data.btp_subaccount_roles.all] roles = [ @@ -322,14 +323,15 @@ resource "btp_subaccount_role_collection" "alm_ts_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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "TMS Admin" + origin = local.origin_key_app_users 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 + subaccount_id = data.btp_subaccount.dc_mission.id name = "TMS Import Operator" roles = [ @@ -345,45 +347,46 @@ resource "btp_subaccount_role_collection" "alm_ts_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 + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "TMS Import Operator" + origin = local.origin_key_app_users user_name = each.value } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # autoscaler -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "autoscaler" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "autoscaler" plan_name = "standard" } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # alert-notification -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "alert_notification" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "alert-notification" plan_name = "standard" } -###################################################################### +# ------------------------------------------------------------------------------------------------------ # application-logs -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "app_logs" { - subaccount_id = data.btp_subaccount.project.id + subaccount_id = data.btp_subaccount.dc_mission.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 + subaccount_id = data.btp_subaccount.dc_mission.id service_name = local.service_name__build_workzone plan_name = var.service_plan__build_workzone amount = var.service_plan__build_workzone == "free" ? 1 : null @@ -391,7 +394,7 @@ resource "btp_subaccount_entitlement" "build_workzone" { # 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 + subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service_name__build_workzone plan_name = var.service_plan__build_workzone depends_on = [btp_subaccount_entitlement.build_workzone] @@ -399,10 +402,40 @@ resource "btp_subaccount_subscription" "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 + for_each = toset(var.workzone_se_administrators) + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Launchpad_Admin" + origin = local.origin_key_app_users user_name = each.value depends_on = [btp_subaccount_subscription.build_workzone] } +# ------------------------------------------------------------------------------------------------------ +# Create tfvars file for step 2 (if variable `create_tfvars_file_for_step2` is set to true) +# ------------------------------------------------------------------------------------------------------ +resource "local_file" "output_vars_step1" { + count = var.create_tfvars_file_for_step2 ? 1 : 0 + content = <<-EOT + globalaccount = "${var.globalaccount}" + cli_server_url = ${jsonencode(var.cli_server_url)} + custom_idp = ${jsonencode(var.custom_idp)} + + subaccount_id = "${data.btp_subaccount.dc_mission.id}" + + cf_api_url = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"]}" + + cf_org_id = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org ID"]}" + cf_org_name = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org Name"]}" + + cf_space_name = "${var.cf_space_name}" + + cf_org_admins = ${jsonencode(var.cf_org_admins)} + cf_space_developers = ${jsonencode(var.cf_space_developers)} + cf_space_managers = ${jsonencode(var.cf_space_managers)} + + + EOT + filename = "../step2/terraform.tfvars" +} + + diff --git a/released/discovery_center/mission_3501/step1/outputs.tf b/released/discovery_center/mission_3501/step1/outputs.tf index 56f90f7b..fc566926 100644 --- a/released/discovery_center/mission_3501/step1/outputs.tf +++ b/released/discovery_center/mission_3501/step1/outputs.tf @@ -11,5 +11,24 @@ output "cf_org_id" { } output "subaccount_id" { - value = data.btp_subaccount.project.id + value = data.btp_subaccount.dc_mission.id +} + +output "bas_url" { + value = btp_subaccount_subscription.bas.subscription_url +} +output "hana_cloud_tools_url" { + value = btp_subaccount_subscription.hana_cloud_tools.subscription_url +} +output "cicd_url" { + value = btp_subaccount_subscription.cicd.subscription_url +} +output "event_mesh_application_url" { + value = btp_subaccount_subscription.event_mesh_application.subscription_url +} +output "alm_ts_url" { + value = btp_subaccount_subscription.alm_ts.subscription_url +} +output "build_workzone_url" { + value = btp_subaccount_subscription.build_workzone.subscription_url } \ No newline at end of file diff --git a/released/discovery_center/mission_3501/samples.tfvars b/released/discovery_center/mission_3501/step1/sample.tfvars similarity index 77% rename from released/discovery_center/mission_3501/samples.tfvars rename to released/discovery_center/mission_3501/step1/sample.tfvars index 66d600f8..79927a9c 100644 --- a/released/discovery_center/mission_3501/samples.tfvars +++ b/released/discovery_center/mission_3501/step1/sample.tfvars @@ -1,15 +1,13 @@ globalaccount = "myglobalaccount" region = "us10" subaccount_name = "Discovery Center mission - 3501" -cf_org_name = "cf-environment" +custom_idp = "<>.accounts.ondemand.com" 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"] +appstudio_developers = ["john.doe@sap.com"] +appstudio_admins = ["john.doe@sap.com"] cf_space_developers = ["john.doe@sap.com"] cf_space_managers = ["john.doe@sap.com"] diff --git a/released/discovery_center/mission_3501/step1/variables.tf b/released/discovery_center/mission_3501/step1/variables.tf index 8a7d2e66..78b8245f 100644 --- a/released/discovery_center/mission_3501/step1/variables.tf +++ b/released/discovery_center/mission_3501/step1/variables.tf @@ -4,8 +4,7 @@ # subaccount variable "globalaccount" { type = string - description = "The globalaccount subdomain." - default = "yourglobalaccount" + description = "The globalaccount subdomain where the sub account shall be created." } variable "subaccount_id" { @@ -49,6 +48,33 @@ variable "cli_server_url" { default = "https://cli.btp.cloud.sap" } +variable "custom_idp" { + type = string + description = "The custom identity provider for the subaccount." + default = "" +} + +variable "custom_idp_apps_origin_key" { + type = string + description = "The custom identity provider for the subaccount." + default = "sap.custom" +} + +variable "origin" { + type = string + description = "Defines the origin key of the identity provider" + default = "sap.ids" + # The value for the origin_key can be defined + # but are normally set to "sap.ids", "sap.default" or "sap.custom" +} + +variable "origin_key" { + type = string + description = "Defines the origin key of the identity provider" + default = "" + # The value for the origin_key can be defined, set to "sap.ids", "sap.default" or "sap.custom" +} + # subaccount variables variable "subaccount_admins" { type = list(string) @@ -72,6 +98,39 @@ variable "subaccount_service_admins" { } } +variable "cf_space_name" { + type = string + description = "Name of the Cloud Foundry space." + default = "dev" + + validation { + condition = can(regex("^.{1,255}$", var.cf_space_name)) + error_message = "The Cloud Foundry space name must not be emtpy and not exceed 255 characters." + } +} + +variable "cf_org_admins" { + type = list(string) + description = "List of users to set as Cloudfoundry org administrators." +} + +variable "cf_org_users" { + type = list(string) + description = "List of users to set as Cloudfoundry org users." +} + +variable "cf_space_managers" { + type = list(string) + description = "Defines the colleagues who are added to a CF space as space manager." +} + +variable "cf_space_developers" { + type = list(string) + description = "Defines the colleagues who are added to a CF space as space developer." +} + + + variable "service_plan__sap_business_app_studio" { type = string description = "The plan for SAP Business Application Studio" @@ -82,40 +141,6 @@ variable "service_plan__sap_business_app_studio" { } } -### -# 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" @@ -138,28 +163,6 @@ variable "appstudio_admins" { } } -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." @@ -280,4 +283,13 @@ variable "cicd_service_admins" { } } +# ------------------------------------------------------------------------------------------------------ +# Switch for creating tfvars for step 2 +# ------------------------------------------------------------------------------------------------------ +variable "create_tfvars_file_for_step2" { + type = bool + description = "Switch to enable the creation of the tfvars file for step 2." + default = true +} + diff --git a/released/discovery_center/mission_3501/step2/README.md b/released/discovery_center/mission_3501/step2/README.md new file mode 100644 index 00000000..5f36c77a --- /dev/null +++ b/released/discovery_center/mission_3501/step2/README.md @@ -0,0 +1,39 @@ +# Discovery Center Mission: Enhance core ERP business processes with resilient applications on SAP BTP (3501) - Step 2 + +## Overview + +This script shows how to create a SAP BTP subaccount for Discovery Center Mission: Enhance core ERP business processes with resilient applications on SAP BTP (3501). Step 2 comprises all activities that depend on the step 1 completion. + + +## Deploying the resources + +To deploy the resources you must: + + +1. If you did not create a `tfvars` file in step 1 (via the variable `create_tfvars_file_for_step2`) you must manually Take the output of step 1 and transfer it in a `tfvars` file e.g. `sample.tfvars` file to meet your requirements. Of course you can also further adjust the generated `tfvars` file from step 1. + +2. If not already done in step 1, initialize your workspace: + + ```bash + terraform init + ``` + +3. You can check what Terraform plans to apply based on your configuration. If you use the generated `tfvars` file from step 1 you do not need need to explicitly add the filename to the command: + + ```bash + terraform plan -var-file="terraform.tfvars" + ``` + +4. According to the variants of step 3. apply your configuration to provision the resources either via: + + ```bash + terraform apply -var-file="terraform.tfvars" + ``` + +## In the end + +You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the command fitting your setup: + +```bash +terraform destroy -var-file="terraform.tfvars" +``` diff --git a/released/discovery_center/mission_3501/step2/main.tf b/released/discovery_center/mission_3501/step2/main.tf index b4812ee4..653fa227 100644 --- a/released/discovery_center/mission_3501/step2/main.tf +++ b/released/discovery_center/mission_3501/step2/main.tf @@ -1,26 +1,65 @@ -###################################################################### +# ------------------------------------------------------------------------------------------------------ +# Import custom trust config and disable for user login +# ------------------------------------------------------------------------------------------------------ +locals { + available_for_user_logon = var.custom_idp != "" ? false : true +} + +import { + to = btp_subaccount_trust_configuration.default + id = "${var.subaccount_id},sap.default" +} + +resource "btp_subaccount_trust_configuration" "default" { + subaccount_id = var.subaccount_id + identity_provider = "" + auto_create_shadow_users = false + available_for_user_logon = local.available_for_user_logon +} + +# ------------------------------------------------------------------------------------------------------ # Create space using CF provider -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "cloudfoundry_space" "dev" { - name = "DEV" + name = var.cf_space_name org = var.cf_org_id } -###################################################################### +# ------------------------------------------------------------------------------------------------------ +# SETUP ALL SERVICES FOR CF USAGE +# ------------------------------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------------------------------ +# USERS AND ROLES +# ------------------------------------------------------------------------------------------------------ +data "btp_whoami" "me" {} + +locals { + # Remove current user if issuer (idp) of logged in user is not same as used custom idp + cf_org_admins = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_admins), [data.btp_whoami.me.email]) + cf_org_users = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_users), [data.btp_whoami.me.email]) + + # get origin_key from custom.idp + custom_idp_tenant = var.custom_idp != "" ? element(split(".", var.custom_idp), 0) : "" + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.ids" +} + +# ------------------------------------------------------------------------------------------------------ # add org and space users and managers -###################################################################### +# ------------------------------------------------------------------------------------------------------ resource "cloudfoundry_org_role" "organization_user" { - for_each = toset(var.cf_org_users) + for_each = toset(local.cf_org_users) username = each.value type = "organization_user" org = var.cf_org_id + origin = local.origin_key } resource "cloudfoundry_org_role" "organization_manager" { - for_each = toset(var.cf_org_admins) + for_each = toset(local.cf_org_admins) username = each.value type = "organization_manager" org = var.cf_org_id + origin = local.origin_key } resource "cloudfoundry_space_role" "space_developer" { @@ -28,6 +67,7 @@ resource "cloudfoundry_space_role" "space_developer" { username = each.value type = "space_developer" space = cloudfoundry_space.dev.id + origin = local.origin_key depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] } @@ -36,5 +76,6 @@ resource "cloudfoundry_space_role" "space_manager" { username = each.value type = "space_manager" space = cloudfoundry_space.dev.id + origin = local.origin_key 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/outputs.tf b/released/discovery_center/mission_3501/step2/outputs.tf deleted file mode 100644 index ad4178cd..00000000 --- a/released/discovery_center/mission_3501/step2/outputs.tf +++ /dev/null @@ -1,19 +0,0 @@ -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 index b58d086e..7d04ed08 100644 --- a/released/discovery_center/mission_3501/step2/provider.tf +++ b/released/discovery_center/mission_3501/step2/provider.tf @@ -4,13 +4,19 @@ terraform { source = "SAP/cloudfoundry" version = "1.0.0-rc1" } + btp = { + source = "SAP/btp" + version = "~> 1.5.0" + } } } -###################################################################### -# Configure CF provider -###################################################################### +provider "btp" { + globalaccount = var.globalaccount + cli_server_url = var.cli_server_url +} + + 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 index 0b435101..125bf875 100644 --- a/released/discovery_center/mission_3501/step2/variables.tf +++ b/released/discovery_center/mission_3501/step2/variables.tf @@ -1,8 +1,23 @@ -variable "cf_api_url" { - type = string +variable "globalaccount" { + type = string + description = "The globalaccount subdomain where the sub account shall be created." +} + +# The BTP CLI server URL +variable "cli_server_url" { + type = string + description = "The BTP CLI server URL." + default = "https://cli.btp.cloud.sap" } -variable "cf_landscape_label" { +# The CF Org name from the Cloud Foundry environment instance +variable "cf_org_name" { + type = string + description = "The Cloud Foundry Org name from the Cloud Foundry environment instance." + +} + +variable "cf_api_url" { type = string } @@ -57,3 +72,20 @@ variable "cf_org_users" { error_message = "Please enter a valid email address for the CF Org Users." } } + +variable "custom_idp" { + type = string + description = "Defines the custom IDP to be used for the subaccount" + default = "" +} + +variable "cf_space_name" { + type = string + description = "Name of the Cloud Foundry space." + default = "dev" + + validation { + condition = can(regex("^.{1,255}$", var.cf_space_name)) + error_message = "The Cloud Foundry space name must not be emtpy and not exceed 255 characters." + } +} From 2f10290e0cdd73e9c6173c99888c6ff310340126 Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Fri, 20 Sep 2024 14:26:07 +0530 Subject: [PATCH 2/8] fixes --- .../mission_3501/step1/main.tf | 5 +- .../mission_3501/step1/variables.tf | 72 ------------------- .../mission_3501/step2/variables.tf | 24 ------- 3 files changed, 3 insertions(+), 98 deletions(-) diff --git a/released/discovery_center/mission_3501/step1/main.tf b/released/discovery_center/mission_3501/step1/main.tf index 67782f2a..a65ee448 100644 --- a/released/discovery_center/mission_3501/step1/main.tf +++ b/released/discovery_center/mission_3501/step1/main.tf @@ -242,7 +242,7 @@ resource "btp_subaccount_subscription" "event_mesh_application" { } resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { - depends_on = [btp_subaccount_entitlement.event_mesh_application] + depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_admins) subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Administrator" @@ -251,7 +251,7 @@ resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { } resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { - depends_on = [btp_subaccount_entitlement.event_mesh_application] + depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_developers) subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Developer" @@ -429,6 +429,7 @@ resource "local_file" "output_vars_step1" { cf_space_name = "${var.cf_space_name}" + cf_org_users = ${jsonencode(var.cf_org_users)} cf_org_admins = ${jsonencode(var.cf_org_admins)} cf_space_developers = ${jsonencode(var.cf_space_developers)} cf_space_managers = ${jsonencode(var.cf_space_managers)} diff --git a/released/discovery_center/mission_3501/step1/variables.tf b/released/discovery_center/mission_3501/step1/variables.tf index 78b8245f..f745ced6 100644 --- a/released/discovery_center/mission_3501/step1/variables.tf +++ b/released/discovery_center/mission_3501/step1/variables.tf @@ -79,23 +79,11 @@ variable "origin_key" { 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 "cf_space_name" { @@ -134,45 +122,21 @@ variable "cf_space_developers" { 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." - } } 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 "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." - } } @@ -210,23 +174,11 @@ variable "hana_system_password" { 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" { @@ -242,45 +194,21 @@ variable "service_plan__build_workzone" { 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/variables.tf b/released/discovery_center/mission_3501/step2/variables.tf index 125bf875..d5554516 100644 --- a/released/discovery_center/mission_3501/step2/variables.tf +++ b/released/discovery_center/mission_3501/step2/variables.tf @@ -32,45 +32,21 @@ variable "subaccount_id" { 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." - } } variable "custom_idp" { From f3b276dffa4481ed7bff4394047dcc3ef696904b Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Fri, 20 Sep 2024 14:39:54 +0530 Subject: [PATCH 3/8] fix2 --- released/discovery_center/mission_3501/step1/variables.tf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/released/discovery_center/mission_3501/step1/variables.tf b/released/discovery_center/mission_3501/step1/variables.tf index f745ced6..7e979676 100644 --- a/released/discovery_center/mission_3501/step1/variables.tf +++ b/released/discovery_center/mission_3501/step1/variables.tf @@ -122,6 +122,11 @@ variable "cf_space_developers" { 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." + } } variable "appstudio_developers" { From eb347d24cba1f6afecf6dc89671292997e9bfd81 Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Tue, 24 Sep 2024 23:29:24 +0530 Subject: [PATCH 4/8] 3680 QAS Polished and few fixes --- .../mission_3680/step1/README.md | 22 +- .../mission_3680/step1/locals.tf | 4 - .../mission_3680/step1/main.tf | 220 ++++++++++++++++-- .../mission_3680/step1/outputs.tf | 36 +-- .../step1/{samples.tfvars => sample.tfvars} | 17 +- .../mission_3680/step1/variables.tf | 60 ++++- .../mission_3680/step2/README.md | 38 +++ .../mission_3680/step2/main.tf | 41 +++- .../mission_3680/step2/outputs.tf | 23 -- .../mission_3680/step2/provider.tf | 16 +- .../mission_3680/step2/variables.tf | 23 +- 11 files changed, 376 insertions(+), 124 deletions(-) delete mode 100644 released/discovery_center/mission_3680/step1/locals.tf rename released/discovery_center/mission_3680/step1/{samples.tfvars => sample.tfvars} (66%) create mode 100644 released/discovery_center/mission_3680/step2/README.md delete mode 100644 released/discovery_center/mission_3680/step2/outputs.tf diff --git a/released/discovery_center/mission_3680/step1/README.md b/released/discovery_center/mission_3680/step1/README.md index a2862bdc..76fd72d3 100644 --- a/released/discovery_center/mission_3680/step1/README.md +++ b/released/discovery_center/mission_3680/step1/README.md @@ -1,4 +1,4 @@ -# Discovery Center Mission: Create a custom mobile app to extend HR capabilities (3680) +# Discovery Center Mission: Create a custom mobile app to extend HR capabilities (3680) - Step 1 ## Overview @@ -18,27 +18,31 @@ The setup comprises the following 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. +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. -2. Change the variables in the `samples.tfvars` file in the main folder to meet your requirements + ```bash + export BTP_USERNAME= + export BTP_PASSWORD= + ``` + +2. Change the variables in the `sample.tfvars` file 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. +3. Initialize your workspace: ```bash terraform init ``` -5. You can check what Terraform plans to apply based on your configuration: +4. You can check what Terraform plans to apply based on your configuration: ```bash - terraform plan -var-file="samples.tfvars" + terraform plan -var-file="sample.tfvars" ``` -6. Apply your configuration to provision the resources: +5. Apply your configuration to provision the resources: ```bash terraform apply -var-file="samples.tfvars" @@ -50,4 +54,4 @@ You probably want to remove the assets after trying them out to avoid unnecessar ```bash terraform destroy -var-file="samples.tfvars" -``` \ No newline at end of file +``` diff --git a/released/discovery_center/mission_3680/step1/locals.tf b/released/discovery_center/mission_3680/step1/locals.tf deleted file mode 100644 index 0cad1df9..00000000 --- a/released/discovery_center/mission_3680/step1/locals.tf +++ /dev/null @@ -1,4 +0,0 @@ -locals { - service_name__sap_build_apps = "sap-build-apps" - service_name__build_workzone = "SAPLaunchpad" -} \ No newline at end of file diff --git a/released/discovery_center/mission_3680/step1/main.tf b/released/discovery_center/mission_3680/step1/main.tf index 8764c364..464e4f0a 100644 --- a/released/discovery_center/mission_3680/step1/main.tf +++ b/released/discovery_center/mission_3680/step1/main.tf @@ -9,22 +9,71 @@ locals { # If a cf_org_name was defined by the user, take that as a subaccount_cf_org. Otherwise create it. subaccount_cf_org = length(var.cf_org_name) > 0 ? var.cf_org_name : substr(replace("${local.subaccount_domain}", "-", ""), 0, 32) } + +locals { + service_name__sap_build_apps = "sap-build-apps" + service_name__build_workzone = "SAPLaunchpad" +} + # ------------------------------------------------------------------------------------------------------ # Creation of subaccount # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount" "dc_mission" { + count = var.subaccount_id == "" ? 1 : 0 + name = var.subaccount_name subdomain = local.subaccount_domain region = lower(var.region) usage = "USED_FOR_PRODUCTION" } +data "btp_subaccount" "dc_mission" { + id = var.subaccount_id != "" ? var.subaccount_id : btp_subaccount.dc_mission[0].id +} + + +# ------------------------------------------------------------------------------------------------------ +# Assign custom IDP to sub account +# ------------------------------------------------------------------------------------------------------ +locals { + service_name__sap_identity_services_onboarding = "sap-identity-services-onboarding" +} + +# Entitle +resource "btp_subaccount_entitlement" "sap_identity_services_onboarding" { + count = var.custom_idp == "" ? 1 : 0 + + subaccount_id = data.btp_subaccount.dc_mission.id + service_name = local.service_name__sap_identity_services_onboarding + plan_name = var.service_plan__sap_identity_services_onboarding +} +# Subscribe +resource "btp_subaccount_subscription" "sap_identity_services_onboarding" { + count = var.custom_idp == "" ? 1 : 0 + + subaccount_id = data.btp_subaccount.dc_mission.id + app_name = local.service_name__sap_identity_services_onboarding + plan_name = var.service_plan__sap_identity_services_onboarding +} + +# IdP trust configuration +resource "btp_subaccount_trust_configuration" "fully_customized" { + subaccount_id = data.btp_subaccount.dc_mission.id + identity_provider = var.custom_idp != "" ? var.custom_idp : element(split("/", btp_subaccount_subscription.sap_identity_services_onboarding[0].subscription_url), 2) +} + +locals { + custom_idp_tenant = element(split(".", btp_subaccount_trust_configuration.fully_customized.identity_provider), 0) + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.default" + origin_key_app_users = var.custom_idp_apps_origin_key +} + # ------------------------------------------------------------------------------------------------------ # 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.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Administrator" user_name = each.value } @@ -33,7 +82,7 @@ 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.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Service Administrator" user_name = each.value } @@ -43,13 +92,13 @@ resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" # Entitle subaccount for usage of SAP HANA Cloud tools # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud_tools" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "hana-cloud-tools" plan_name = "tools" } resource "btp_subaccount_subscription" "hana_cloud_tools" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = "hana-cloud-tools" plan_name = "tools" depends_on = [btp_subaccount_entitlement.hana_cloud_tools] @@ -57,10 +106,9 @@ resource "btp_subaccount_subscription" "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 = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "SAP HANA Cloud Administrator" - user_name = each.value + user_name = var.hana_system_admin depends_on = [btp_subaccount_subscription.hana_cloud_tools] } @@ -68,21 +116,21 @@ resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { # Entitle subaccount for usage of SAP HANA Cloud # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "hana_cloud" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "hana-cloud" plan_name = "hana" } # Get plan for SAP HANA Cloud data "btp_subaccount_service_plan" "hana_cloud" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id offering_name = "hana-cloud" name = "hana" depends_on = [btp_subaccount_entitlement.hana_cloud] } resource "btp_subaccount_service_instance" "hana_cloud" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id serviceplan_id = data.btp_subaccount_service_plan.hana_cloud.id name = "my-hana-cloud-instance" depends_on = [btp_subaccount_entitlement.hana_cloud] @@ -117,7 +165,7 @@ resource "btp_subaccount_service_instance" "hana_cloud" { # Create service binding to SAP HANA Cloud service resource "btp_subaccount_service_binding" "hana_cloud" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id service_instance_id = btp_subaccount_service_instance.hana_cloud.id name = "hana-cloud-key" } @@ -130,7 +178,7 @@ resource "btp_subaccount_service_binding" "hana_cloud" { # # Fetch all available environments for the subaccount data "btp_subaccount_environments" "all" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id } # ------------------------------------------------------------------------------------------------------ # Take the landscape label from the first CF environment if no environment label is provided @@ -143,7 +191,7 @@ resource "terraform_data" "cf_landscape_label" { # Creation of Cloud Foundry environment # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_environment_instance" "cloudfoundry" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id name = local.subaccount_cf_org environment_type = "cloudfoundry" service_name = "cloudfoundry" @@ -158,19 +206,19 @@ resource "btp_subaccount_environment_instance" "cloudfoundry" { # Event Mesh # ------------------------------------------------------------------------------------------------------ resource "btp_subaccount_entitlement" "event_mesh" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging" plan_name = "default" } resource "btp_subaccount_entitlement" "event_mesh_application" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id service_name = "enterprise-messaging-hub" plan_name = "standard" } resource "btp_subaccount_subscription" "event_mesh_application" { - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id app_name = "enterprise-messaging-hub" plan_name = "standard" depends_on = [btp_subaccount_entitlement.event_mesh_application] @@ -179,7 +227,7 @@ resource "btp_subaccount_subscription" "event_mesh_application" { resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_admins) - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Administrator" user_name = each.value } @@ -187,11 +235,140 @@ resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { depends_on = [btp_subaccount_subscription.event_mesh_application] for_each = toset(var.event_mesh_developers) - subaccount_id = btp_subaccount.dc_mission.id + subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Developer" 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.dc_mission.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.dc_mission.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.dc_mission.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.dc_mission.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.dc_mission.id + role_collection_name = "BuildAppsAdmin" + user_name = each.value + origin = local.origin_key_app_users +} + +# ------------------------------------------------------------------------------------------------------ +# Setup for role collection BuildAppsDeveloper +# ------------------------------------------------------------------------------------------------------ +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_BuildAppsDeveloper" { + subaccount_id = data.btp_subaccount.dc_mission.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.dc_mission.id + role_collection_name = "BuildAppsDeveloper" + user_name = each.value + origin = local.origin_key_app_users +} + +# ------------------------------------------------------------------------------------------------------ +# Setup for role collection RegistryAdmin +# ------------------------------------------------------------------------------------------------------ +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_RegistryAdmin" { + subaccount_id = data.btp_subaccount.dc_mission.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.dc_mission.id + role_collection_name = "RegistryAdmin" + user_name = each.value + origin = local.origin_key_app_users +} + +# ------------------------------------------------------------------------------------------------------ +# Setup for role collection RegistryDeveloper +# ------------------------------------------------------------------------------------------------------ +# Create the role collection +resource "btp_subaccount_role_collection" "build_apps_RegistryDeveloper" { + subaccount_id = data.btp_subaccount.dc_mission.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.dc_mission.id + role_collection_name = "RegistryDeveloper" + user_name = each.value + origin = local.origin_key_app_users +} # ------------------------------------------------------------------------------------------------------ # Create tfvars file for step 2 (if variable `create_tfvars_file_for_step2` is set to true) @@ -199,17 +376,16 @@ resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { resource "local_file" "output_vars_step1" { count = var.create_tfvars_file_for_step2 ? 1 : 0 content = <<-EOT - subaccount_id = "${btp_subaccount.dc_mission.id}" + subaccount_id = "${data.btp_subaccount.dc_mission.id}" + globalaccount = "${var.globalaccount}" cf_api_url = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"]}" cf_org_id = "${jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org ID"]}" - origin = "${var.origin}" cf_space_name = "${var.cf_space_name}" cf_org_users = ${jsonencode(var.cf_org_users)} cf_org_admins = ${jsonencode(var.cf_org_admins)} cf_space_developers = ${jsonencode(var.cf_space_developers)} cf_space_managers = ${jsonencode(var.cf_space_managers)} - event_mesh_url = "${btp_subaccount_subscription.event_mesh_application.subscription_url}" - hana_tools_url = "${btp_subaccount_subscription.hana_cloud_tools.subscription_url}" + custom_idp = "${btp_subaccount_trust_configuration.fully_customized.identity_provider}" EOT filename = "../step2/terraform.tfvars" } \ No newline at end of file diff --git a/released/discovery_center/mission_3680/step1/outputs.tf b/released/discovery_center/mission_3680/step1/outputs.tf index c6f4202a..303da533 100644 --- a/released/discovery_center/mission_3680/step1/outputs.tf +++ b/released/discovery_center/mission_3680/step1/outputs.tf @@ -1,5 +1,5 @@ output "subaccount_id" { - value = btp_subaccount.dc_mission.id + value = data.btp_subaccount.dc_mission.id description = "The ID of the subaccount." } @@ -27,38 +27,12 @@ output "hana_tools_url" { value = btp_subaccount_subscription.hana_cloud_tools.subscription_url description = "HANA Tools URL" } +output "build_apps_url" { + value = btp_subaccount_subscription.sap-build-apps_standard.subscription_url + description = "SAP Build Apps URL" +} output "cf_org_name" { value = jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["Org Name"] description = "The Cloudfoundry org name." } - -output "cf_org_admins" { - value = var.cf_org_admins - description = "The Cloudfoundry org admins." -} - -output "cf_org_users" { - value = var.cf_org_users - description = "The Cloudfoundry org users." -} - -output "cf_space_developers" { - value = var.cf_space_developers - description = "The Cloudfoundry space developers." -} - -output "cf_space_managers" { - value = var.cf_space_managers - description = "The Cloudfoundry space managers." -} - -output "cf_space_name" { - value = var.cf_space_name - description = "The Cloudfoundry space name." -} - -output "origin" { - value = var.origin - description = "The origin of the identity provider." -} diff --git a/released/discovery_center/mission_3680/step1/samples.tfvars b/released/discovery_center/mission_3680/step1/sample.tfvars similarity index 66% rename from released/discovery_center/mission_3680/step1/samples.tfvars rename to released/discovery_center/mission_3680/step1/sample.tfvars index 6ff37127..d4a28e28 100644 --- a/released/discovery_center/mission_3680/step1/samples.tfvars +++ b/released/discovery_center/mission_3680/step1/sample.tfvars @@ -5,6 +5,7 @@ globalaccount = "yourglobalaccount" region = "us10" subaccount_name = "SAP Discovery Center Mission 3680" +custom_idp = ".accounts.ondemand.com" # ------------------------------------------------------------------------------------------------------ # Project specific configuration (please adapt!) @@ -14,15 +15,21 @@ subaccount_name = "SAP Discovery Center Mission 3680" subaccount_admins = ["another.user@test.com"] subaccount_service_admins = ["another.user@test.com"] -hana_cloud_admins = ["another.user@test.com"] +hana_system_admin = "another.user@test.com" hana_system_password = "Abc12345" # Don't add the user, that is executing the TF script to cf_org_admins or cf_org_users! cf_org_admins = ["another.user@test.com"] cf_org_users = ["another.user@test.com"] -cf_space_managers = ["another.user@test.com", "you@test.com"] -cf_space_developers = ["another.user@test.com", "you@test.com"] +cf_space_managers = ["another.user@test.com"] +cf_space_developers = ["another.user@test.com"] # Event Mesh users -event_mesh_admins = ["another.user@test.com", "you@test.com"] -event_mesh_developers = ["another.user@test.com", "you@test.com"] +event_mesh_admins = ["another.user@test.com"] +event_mesh_developers = ["another.user@test.com"] + +# Build Apps +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"] diff --git a/released/discovery_center/mission_3680/step1/variables.tf b/released/discovery_center/mission_3680/step1/variables.tf index 5baffe57..7a233e3f 100644 --- a/released/discovery_center/mission_3680/step1/variables.tf +++ b/released/discovery_center/mission_3680/step1/variables.tf @@ -51,16 +51,9 @@ variable "region" { } -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_admin" { + type = string + description = "Defines the colleague who is added as admin to access the instance of SAP HANA Cloud." } variable "custom_idp" { @@ -72,7 +65,7 @@ variable "custom_idp" { variable "create_tfvars_file_for_step2" { type = bool description = "Switch to enable the creation of the tfvars file for step 2." - default = false + default = true } variable "hana_system_password" { @@ -178,4 +171,49 @@ variable "event_mesh_developers" { default = ["jane.doe@test.com", "john.doe@test.com"] } +variable "custom_idp_apps_origin_key" { + type = string + description = "The custom identity provider for the subaccount." + default = "sap.custom" +} + +variable "service_plan__sap_identity_services_onboarding" { + type = string + description = "The plan for service 'Cloud Identity Services' with technical name 'sap-identity-services-onboarding'" + default = "default" + validation { + condition = contains(["default"], var.service_plan__sap_identity_services_onboarding) + error_message = "Invalid value for service_plan__sap_identity_services_onboarding. Only 'default' is allowed." + } +} + +variable "users_buildApps_admins" { + type = list(string) + description = "Defines the colleagues who have the role of 'BuildAppsAdmin' in SAP Build Apps." +} + +variable "users_buildApps_developers" { + type = list(string) + description = "Defines the colleagues who have the role of 'BuildAppsDeveloper' in SAP Build Apps." +} + +variable "users_registry_admins" { + type = list(string) + description = "Defines the colleagues who have the role of 'RegistryAdmin' in SAP Build Apps." +} + +variable "users_registry_developers" { + type = list(string) + description = "Defines the colleagues who have the role of RegistryDeveloper' in SAP Build Apps." +} + +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." + } +} diff --git a/released/discovery_center/mission_3680/step2/README.md b/released/discovery_center/mission_3680/step2/README.md new file mode 100644 index 00000000..ef024581 --- /dev/null +++ b/released/discovery_center/mission_3680/step2/README.md @@ -0,0 +1,38 @@ +# Discovery Center mission - Create a custom mobile app to extend HR capabilities (3680) - Step 2 + +## Overview + +This script shows how to create a SAP BTP subaccount for Discovery Center Mission: Create a custom mobile app to extend HR capabilities (3680). Step 2 comprises all activities that depend on the step 1 completion. + +## Deploying the resources + +To deploy the resources you must: + + +1. If you did not create a `tfvars` file in step 1 (via the variable `create_tfvars_file_for_step2`) you must manually Take the output of step 1 and transfer it in a `tfvars` file e.g. `sample.tfvars` file to meet your requirements. Of course you can also further adjust the generated `tfvars` file from step 1. + +2. If not already done in step 1, initialize your workspace: + + ```bash + terraform init + ``` + +3. You can check what Terraform plans to apply based on your configuration. If you use the generated `tfvars` file from step 1 you do not need need to explicitly add the filename to the command: + + ```bash + terraform plan -var-file="terraform.tfvars" + ``` + +4. According to the variants of step 3. apply your configuration to provision the resources either via: + + ```bash + terraform apply -var-file="terraform.tfvars" + ``` + +## In the end + +You probably want to remove the assets after trying them out to avoid unnecessary costs. To do so execute the command fitting your setup: + +```bash +terraform destroy -var-file="terraform.tfvars" +``` diff --git a/released/discovery_center/mission_3680/step2/main.tf b/released/discovery_center/mission_3680/step2/main.tf index 14d85564..a982e0b3 100644 --- a/released/discovery_center/mission_3680/step2/main.tf +++ b/released/discovery_center/mission_3680/step2/main.tf @@ -1,3 +1,18 @@ +# ------------------------------------------------------------------------------------------------------ +# Import custom trust config and disable for user login +# ------------------------------------------------------------------------------------------------------ +import { + to = btp_subaccount_trust_configuration.default + id = "${var.subaccount_id},sap.default" +} + +resource "btp_subaccount_trust_configuration" "default" { + subaccount_id = var.subaccount_id + identity_provider = "" + auto_create_shadow_users = false + available_for_user_logon = false +} + # ------------------------------------------------------------------------------------------------------ # Create space using CF provider # ------------------------------------------------------------------------------------------------------ @@ -6,6 +21,24 @@ resource "cloudfoundry_space" "dev" { org = var.cf_org_id } +# ------------------------------------------------------------------------------------------------------ +# SETUP ALL SERVICES FOR CF USAGE +# ------------------------------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------------------------------ +# USERS AND ROLES +# ------------------------------------------------------------------------------------------------------ +data "btp_whoami" "me" {} + +locals { + # Remove current user if issuer (idp) of logged in user is not same as used custom idp + cf_org_admins = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_admins), [data.btp_whoami.me.email]) + cf_org_users = data.btp_whoami.me.issuer != var.custom_idp ? var.cf_org_admins : setsubtract(toset(var.cf_org_users), [data.btp_whoami.me.email]) + + # get origin_key from custom.idp + custom_idp_tenant = var.custom_idp != "" ? element(split(".", var.custom_idp), 0) : "" + origin_key = local.custom_idp_tenant != "" ? "${local.custom_idp_tenant}-platform" : "sap.ids" +} + # ------------------------------------------------------------------------------------------------------ # add org and space users and managers # ------------------------------------------------------------------------------------------------------ @@ -14,7 +47,7 @@ resource "cloudfoundry_org_role" "organization_user" { username = each.value type = "organization_user" org = var.cf_org_id - origin = var.origin + origin = local.origin_key } resource "cloudfoundry_org_role" "organization_manager" { @@ -22,7 +55,7 @@ resource "cloudfoundry_org_role" "organization_manager" { username = each.value type = "organization_manager" org = var.cf_org_id - origin = var.origin + origin = local.origin_key } resource "cloudfoundry_space_role" "space_developer" { @@ -30,7 +63,7 @@ resource "cloudfoundry_space_role" "space_developer" { username = each.value type = "space_developer" space = cloudfoundry_space.dev.id - origin = var.origin + origin = local.origin_key depends_on = [cloudfoundry_org_role.organization_user, cloudfoundry_org_role.organization_manager] } @@ -39,6 +72,6 @@ resource "cloudfoundry_space_role" "space_manager" { username = each.value type = "space_manager" space = cloudfoundry_space.dev.id - origin = var.origin + origin = local.origin_key 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_3680/step2/outputs.tf b/released/discovery_center/mission_3680/step2/outputs.tf deleted file mode 100644 index 039ee30d..00000000 --- a/released/discovery_center/mission_3680/step2/outputs.tf +++ /dev/null @@ -1,23 +0,0 @@ -output "subaccount_id" { - value = var.subaccount_id -} - -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 -} - -output "hana_tools_url" { - value = var.hana_tools_url -} - -output "event_mesh_url" { - value = var.event_mesh_url -} \ No newline at end of file diff --git a/released/discovery_center/mission_3680/step2/provider.tf b/released/discovery_center/mission_3680/step2/provider.tf index fade3e6e..4ec94611 100644 --- a/released/discovery_center/mission_3680/step2/provider.tf +++ b/released/discovery_center/mission_3680/step2/provider.tf @@ -1,16 +1,22 @@ terraform { required_providers { cloudfoundry = { - source = "sap/cloudfoundry" + source = "SAP/cloudfoundry" version = "1.0.0-rc1" } + btp = { + source = "SAP/btp" + version = "~> 1.5.0" + } } } -# ------------------------------------------------------------------------------------------------------ -# Configure CF provider -# ------------------------------------------------------------------------------------------------------ +provider "btp" { + globalaccount = var.globalaccount + cli_server_url = var.cli_server_url +} + + 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_3680/step2/variables.tf b/released/discovery_center/mission_3680/step2/variables.tf index 2f2e412d..2e94db23 100644 --- a/released/discovery_center/mission_3680/step2/variables.tf +++ b/released/discovery_center/mission_3680/step2/variables.tf @@ -1,12 +1,16 @@ -variable "cf_api_url" { - type = string +variable "globalaccount" { + type = string + description = "Defines the global account" + default = "yourglobalaccount" } -variable "hana_tools_url" { - type = string +variable "cli_server_url" { + type = string + description = "Defines the CLI server URL" + default = "https://cli.btp.cloud.sap" } -variable "event_mesh_url" { +variable "cf_api_url" { type = string } @@ -53,10 +57,9 @@ variable "cf_org_users" { default = ["jane.doe@test.com", "john.doe@test.com"] } -variable "origin" { + +variable "custom_idp" { type = string - description = "Defines the origin key of the identity provider" - default = "sap.ids" - # The value for the origin_key can be defined - # but are normally set to "sap.ids", "sap.default" or "sap.custom" + description = "Defines the custom IdP" + default = "" } \ No newline at end of file From 9c308c936dd28b6b9d193557a8aa69ad21de7706 Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Tue, 24 Sep 2024 23:39:48 +0530 Subject: [PATCH 5/8] fix --- .../discovery_center/mission_3680/step1/sample.tfvars | 8 ++++---- released/discovery_center/mission_3680/step1/variables.tf | 8 -------- released/discovery_center/mission_3680/step2/variables.tf | 4 ---- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/released/discovery_center/mission_3680/step1/sample.tfvars b/released/discovery_center/mission_3680/step1/sample.tfvars index d4a28e28..545ca8c4 100644 --- a/released/discovery_center/mission_3680/step1/sample.tfvars +++ b/released/discovery_center/mission_3680/step1/sample.tfvars @@ -29,7 +29,7 @@ event_mesh_admins = ["another.user@test.com"] event_mesh_developers = ["another.user@test.com"] # Build Apps -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"] +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"] diff --git a/released/discovery_center/mission_3680/step1/variables.tf b/released/discovery_center/mission_3680/step1/variables.tf index 7a233e3f..ce7dae42 100644 --- a/released/discovery_center/mission_3680/step1/variables.tf +++ b/released/discovery_center/mission_3680/step1/variables.tf @@ -28,13 +28,11 @@ variable "subaccount_id" { 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 "region" { @@ -119,25 +117,21 @@ variable "cf_space_name" { 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"] } variable "origin" { @@ -162,13 +156,11 @@ variable "cf_org_name" { variable "event_mesh_admins" { type = list(string) description = "Enterprise Messaging Administrators" - default = ["jane.doe@test.com", "john.doe@test.com"] } variable "event_mesh_developers" { type = list(string) description = "Enterprise Messaging Developers" - default = ["jane.doe@test.com", "john.doe@test.com"] } variable "custom_idp_apps_origin_key" { diff --git a/released/discovery_center/mission_3680/step2/variables.tf b/released/discovery_center/mission_3680/step2/variables.tf index 2e94db23..9db7c505 100644 --- a/released/discovery_center/mission_3680/step2/variables.tf +++ b/released/discovery_center/mission_3680/step2/variables.tf @@ -36,25 +36,21 @@ variable "cf_space_name" { 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"] } From 74aec2588e0c3a1a40b80932cc15084b97b72766 Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Tue, 24 Sep 2024 23:42:42 +0530 Subject: [PATCH 6/8] fix origin roles --- released/discovery_center/mission_3680/step1/main.tf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/released/discovery_center/mission_3680/step1/main.tf b/released/discovery_center/mission_3680/step1/main.tf index 464e4f0a..463453d1 100644 --- a/released/discovery_center/mission_3680/step1/main.tf +++ b/released/discovery_center/mission_3680/step1/main.tf @@ -76,6 +76,7 @@ resource "btp_subaccount_role_collection_assignment" "subaccount-admins" { subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Administrator" user_name = each.value + origin = local.origin_key } # ------------------------------------------------------------------------------------------------------ # Assignment of users as sub account service administrators @@ -85,9 +86,9 @@ resource "btp_subaccount_role_collection_assignment" "subaccount-service-admins" subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Subaccount Service Administrator" user_name = each.value + origin = local.origin_key } - # ------------------------------------------------------------------------------------------------------ # Entitle subaccount for usage of SAP HANA Cloud tools # ------------------------------------------------------------------------------------------------------ @@ -110,6 +111,7 @@ resource "btp_subaccount_role_collection_assignment" "hana_cloud_admin" { role_collection_name = "SAP HANA Cloud Administrator" user_name = var.hana_system_admin depends_on = [btp_subaccount_subscription.hana_cloud_tools] + origin = local.origin_key_app_users } # ------------------------------------------------------------------------------------------------------ @@ -230,6 +232,7 @@ resource "btp_subaccount_role_collection_assignment" "event_mesh_admin" { subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Administrator" user_name = each.value + origin = local.origin_key_app_users } resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { @@ -238,6 +241,7 @@ resource "btp_subaccount_role_collection_assignment" "event_mesh_developer" { subaccount_id = data.btp_subaccount.dc_mission.id role_collection_name = "Enterprise Messaging Developer" user_name = each.value + origin = local.origin_key_app_users } # ------------------------------------------------------------------------------------------------------ From 5f21d84932cbadf84d0438b923910d201e40538d Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Wed, 25 Sep 2024 14:45:21 +0530 Subject: [PATCH 7/8] fix region --- .../discovery_center/mission_3680/step1/variables.tf | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/released/discovery_center/mission_3680/step1/variables.tf b/released/discovery_center/mission_3680/step1/variables.tf index ce7dae42..cd76d5ac 100644 --- a/released/discovery_center/mission_3680/step1/variables.tf +++ b/released/discovery_center/mission_3680/step1/variables.tf @@ -38,14 +38,7 @@ variable "subaccount_service_admins" { variable "region" { type = string description = "The region where the sub account shall be created in." - default = "us10" - - # Checkout https://github.com/SAP-samples/btp-service-metadata/blob/main/v0/developer/aicore.json for the latest list of regions - # supported by the AI Core service with the "extended" service plan. - validation { - condition = contains(["ap10", "eu10", "eu11", "eu20", "eu30", "jp10", "us10", "us21", "us30"], var.region) - error_message = "Please enter a valid region for the sub account. Checkout https://github.com/SAP-samples/btp-service-metadata/blob/main/v0/developer/aicore.json for regions providing the AI Core service." - } + default = "" } From 39919083a991c6cc137b78b3eecaa79a4dcb7846 Mon Sep 17 00:00:00 2001 From: mahesh0431 Date: Wed, 25 Sep 2024 14:55:23 +0530 Subject: [PATCH 8/8] fix idp dependency --- released/discovery_center/mission_3680/step1/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/released/discovery_center/mission_3680/step1/main.tf b/released/discovery_center/mission_3680/step1/main.tf index 463453d1..3a09cdb9 100644 --- a/released/discovery_center/mission_3680/step1/main.tf +++ b/released/discovery_center/mission_3680/step1/main.tf @@ -54,6 +54,7 @@ resource "btp_subaccount_subscription" "sap_identity_services_onboarding" { subaccount_id = data.btp_subaccount.dc_mission.id app_name = local.service_name__sap_identity_services_onboarding plan_name = var.service_plan__sap_identity_services_onboarding + depends_on = [btp_subaccount_entitlement.sap_identity_services_onboarding] } # IdP trust configuration