Skip to content

Commit 23a217d

Browse files
authored
feat: sample code the the SAP BTP Usability Days 2025 (#475)
Co-authored-by: Christian Lechner <[email protected]>
1 parent 22a1a23 commit 23a217d

File tree

6 files changed

+305
-0
lines changed

6 files changed

+305
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Sample for SAP BTP Usability Days 2025
2+
3+
This folder contains a sample setup of a subaccount on SAP BTP using the Terraform provider for SAP BTP.
4+
5+
> [!IMPORTANT]
6+
> The sample is tested agianst a SAP BTP CPEA/BTPEA account. The configuration will not work when using a SAP BTP trial account.
7+
8+
## Prerequisites
9+
10+
Before you apply the configuration, make sure you have entered the necessary variables in the `samples.tfvars` file:
11+
12+
```terraform
13+
globalaccount = "<YOUR GLOBAL ACCOUNT SUBDOMAIN>"
14+
cost_center = "CC-12345678"
15+
contact_person = "John Doe"
16+
department = "Sales"
17+
```
18+
19+
If you use a custom platform IdP, make sure taht you also add the `idp` variable to the `samples.tfvars` file.
20+
21+
For the authentication to SAP BTP we recommend using the environment variables `BTP_USERNAME` and `BTP_PASSWORD` to store your credentials securely.
22+
23+
On Windows, you can set them in PowerShell like this:
24+
25+
```powershell
26+
$env:BTP_USERNAME="your-username"
27+
$env:BTP_PASSWORD="your-password"
28+
```
29+
30+
On Linux or Mac OS, you can set them in the terminal like this:
31+
32+
```bash
33+
export BTP_USERNAME="your-username"
34+
export BTP_PASSWORD="your-password"
35+
```
36+
37+
## Execution
38+
39+
To execute the configuration, run the following commands in your terminal:
40+
41+
1. Initialize the Terraform working directory:
42+
```bash
43+
terraform init
44+
```
45+
2. Validate the configuration:
46+
```bash
47+
terraform validate
48+
```
49+
50+
3. Create and review the execution plan:
51+
```bash
52+
terraform plan -var-file="samples.tfvars" -out="plan.out"
53+
```
54+
55+
4. If the proposed changes are as expected, apply the execution plan:
56+
57+
```bash
58+
terraform apply "plan.out"
59+
```
60+
61+
Once the apply is complete, you can find the outputs in the terminal or by running:
62+
63+
```bash
64+
terraform output
65+
```
66+
67+
The output `subaccount_url` provides a direct link to the created subaccount in the SAP BTP Cockpit.
68+
69+
70+
## Cleanup
71+
72+
To remove the created resources and clean up your environment, run the following command:
73+
74+
```bash
75+
terraform destroy -var-file="samples.tfvars"
76+
```
77+
78+
Review the proposed plan and confirm the destruction of resources when prompted.
79+
80+
81+
## Content
82+
83+
The configuration showcases some specific features:
84+
85+
- Validation of input variables using `validation` blocks in the `variables.tf` file.
86+
- Implementing naming conventions
87+
- Using maps and objects and the `lookup()` function to retrieve values based on the variables
88+
- Using ternary operators for conditionally setting values resouce attributes
89+
- Using modules as reusable components
90+
- Creating multiple resources using `for_each` based on a list
91+
- Creating outputs with dynamic values
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Needed for subdomain uniqueness
2+
resource "random_uuid" "self" {}
3+
4+
# Needed for output to construct the subaccount URL
5+
data "btp_globalaccount" "self" {}
6+
7+
locals {
8+
# Define a mapping of regions to their respective geo regions
9+
region_mapping = {
10+
"br10" = "LATAM"
11+
"jp10" = "APAC"
12+
"ap10" = "APAC"
13+
"ap11" = "APAC"
14+
"ap12" = "APAC"
15+
"ca10" = "AMER"
16+
"eu10" = "EMEA"
17+
"eu11" = "EMEA"
18+
"us10" = "AMER"
19+
"us11" = "AMER"
20+
"us30" = "AMER"
21+
"eu30" = "EMEA"
22+
"in30" = "APAC"
23+
"il30" = "EMEA"
24+
"jp30" = "APAC"
25+
"jp31" = "APAC"
26+
"ap30" = "APAC"
27+
"br30" = "APAC"
28+
"eu20" = "EMEA"
29+
"ap20" = "APAC"
30+
"ap21" = "APAC"
31+
"br20" = "APAC"
32+
"ca20" = "AMER"
33+
"cn20" = "APAC"
34+
"us20" = "AMER"
35+
"jp20" = "APAC"
36+
"us21" = "AMER"
37+
"ch20" = "EMEA"
38+
}
39+
40+
# Define default entitlements per stage
41+
default_entitlements = {
42+
"Dev" = {
43+
"aicore" = ["standard"],
44+
"ai-launchpad" = ["standard"]
45+
"alert-notification" = ["standard"],
46+
"application-logs" = ["standard=1"],
47+
"build-workzone-standard" = ["standard"],
48+
"credstore" = ["standard=1"],
49+
"jobscheduler" = ["standard=1"],
50+
"hana-cloud" = ["hana"],
51+
"transport" = ["standard"],
52+
},
53+
"Test" = {
54+
"ai-launchpad" = ["standard"]
55+
"alert-notification" = ["standard"],
56+
"application-logs" = ["standard=1"],
57+
"build-workzone-standard" = ["standard"],
58+
"credstore" = ["standard=1"],
59+
"jobscheduler" = ["standard=1"],
60+
"hana-cloud" = ["hana"],
61+
"transport" = ["standard"],
62+
},
63+
"Prod" = {
64+
"ai-launchpad" = ["standard"]
65+
"alert-notification" = ["standard"],
66+
"application-logs" = ["standard=1"],
67+
"build-workzone-standard" = ["standard"],
68+
"credstore" = ["standard=1"],
69+
"jobscheduler" = ["standard=1"],
70+
"hana-cloud" = ["hana"],
71+
"transport" = ["standard"],
72+
}
73+
}
74+
75+
# Naming conventions
76+
subaccount_name = "${var.subaccount_name} ${var.stage}"
77+
subaccount_subdomain = "${replace(lower(var.subaccount_name), " ", "-")}-${lower(var.stage)}-${random_uuid.self.result}"
78+
subaccount_description = "Subaccount ${var.subaccount_name} in the ${var.stage} stage for ${var.department}."
79+
cf_org_name = "CF-${var.subaccount_name}-${var.stage}"
80+
}
81+
82+
resource "btp_subaccount" "self" {
83+
name = local.subaccount_name
84+
subdomain = local.subaccount_subdomain
85+
region = var.region
86+
description = local.subaccount_description
87+
usage = var.stage == "Prod" ? "USED_FOR_PRODUCTION" : "NOT_USED_FOR_PRODUCTION"
88+
beta_enabled = var.stage == "Dev" ? true : false
89+
labels = {
90+
"Cost Center" = ["${var.cost_center}"]
91+
"Contact Person" = ["${var.contact_person}"]
92+
"Department" = ["${var.department}"]
93+
"Region" = ["${lookup(local.region_mapping, var.region, "UNKNOWN")}"]
94+
}
95+
}
96+
97+
module "sap_btp_entitlements" {
98+
source = "aydin-ozcan/sap-btp-entitlements/btp"
99+
version = "~> 1.0.1"
100+
101+
subaccount = btp_subaccount.self.id
102+
entitlements = local.default_entitlements[var.stage]
103+
}
104+
105+
data "btp_subaccount_environments" "all" {
106+
subaccount_id = btp_subaccount.self.id
107+
}
108+
109+
resource "terraform_data" "cf_landscape_label" {
110+
input = [for env in data.btp_subaccount_environments.all.values : env if env.service_name == "cloudfoundry" && env.environment_type == "cloudfoundry"][0].landscape_label
111+
}
112+
113+
114+
resource "btp_subaccount_environment_instance" "cloudfoundry" {
115+
subaccount_id = btp_subaccount.self.id
116+
name = local.cf_org_name
117+
environment_type = "cloudfoundry"
118+
service_name = "cloudfoundry"
119+
plan_name = "standard"
120+
landscape_label = terraform_data.cf_landscape_label.output
121+
parameters = jsonencode({
122+
instance_name = local.subaccount_subdomain
123+
})
124+
}
125+
126+
resource "btp_subaccount_role_collection_assignment" "emergency_admins" {
127+
for_each = toset(var.emergency_subaccount_admins)
128+
129+
subaccount_id = btp_subaccount.self.id
130+
role_collection_name = "Subaccount Administrator"
131+
user_name = each.value
132+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
output "subaccount_url" {
2+
value = "https://emea.cockpit.btp.cloud.sap/cockpit/#globalaccount/${data.btp_globalaccount.self.id}/subaccount/${btp_subaccount.self.id}"
3+
description = "The SAP BTP subaccount URL"
4+
}
5+
6+
output "cf_api_url" {
7+
value = jsondecode(btp_subaccount_environment_instance.cloudfoundry.labels)["API Endpoint"]
8+
description = "The Cloud Foundry API URL"
9+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
required_providers {
3+
btp = {
4+
source = "SAP/btp"
5+
version = "~> 1.15.0"
6+
}
7+
}
8+
}
9+
10+
# Configure the BTP Provider
11+
provider "btp" {
12+
globalaccount = var.globalaccount
13+
idp = var.idp
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
globalaccount = "<YOUR_GLOBAL_ACCOUNT_SUBDOMAIN>"
2+
subaccount_name = "btp-usability-days"
3+
region = "us10"
4+
cost_center = "CC-12345678"
5+
contact_person = "John Doe"
6+
department = "Sales"
7+
emergency_subaccount_admins = ["[email protected]", "firefighter1"]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
variable "globalaccount" {
2+
description = "The BTP global account name"
3+
type = string
4+
}
5+
6+
variable "idp" {
7+
description = "The Identity Provider to use for authentication (e.g. 'ias' or 'xsuaa')"
8+
type = string
9+
default = null
10+
}
11+
12+
variable "subaccount_name" {
13+
description = "The BTP subaccount name"
14+
type = string
15+
}
16+
17+
variable "region" {
18+
description = "The region of the SAP BTP subaccount"
19+
type = string
20+
default = "us10"
21+
}
22+
23+
variable "stage" {
24+
description = "The stage of the SAP BTP subaccount"
25+
type = string
26+
default = "Dev"
27+
validation {
28+
condition = contains(["Dev", "Test", "Prod"], var.stage)
29+
error_message = "Stage must be one of the following: `Dev`, `Test`, `Prod`."
30+
}
31+
}
32+
33+
variable "cost_center" {
34+
description = "The cost center for the SAP BTP subaccount"
35+
type = string
36+
}
37+
38+
variable "contact_person" {
39+
description = "The contact person for the SAP BTP subaccount"
40+
type = string
41+
}
42+
43+
variable "department" {
44+
description = "The department for the SAP BTP subaccount"
45+
type = string
46+
}
47+
48+
variable "emergency_subaccount_admins" {
49+
description = "List of emergency subaccount admins (emails)"
50+
type = list(string)
51+
default = []
52+
}

0 commit comments

Comments
 (0)