13 KiB
| description | applyTo |
|---|---|
| Terraform Conventions and Guidelines on SAP Business Technology Platform (SAP BTP). | **/*.terraform, **/*.tf, **/*.tfvars, **/*.tflint.hcl, **/*.tfstate, **/*.tf.json, **/*.tfvars.json |
Terraform on SAP BTP - Best Practices and Conventions
General Instructions
- Use Terraform to provision and manage infrastructure.
- Use version control for your Terraform configurations.
Security
- Always use the latest stable version of Terraform and its providers.
- Regularly update your Terraform configurations to incorporate security patches and improvements.
- Never commit sensitive information such as credentials, API keys, passwords, certificates, or Terraform state to version control.
- Use
.gitignoreto exclude files containing sensitive information from version control.
- Use
- Always mark sensitive variables as
sensitive = truein your Terraform configurations.- This prevents sensitive values from being displayed in the Terraform plan or apply output.
- Use
ephemeralsecrets with write-only parameters when supported (Terraform v1.11+) to avoid storing secrets in state files. - Avoid outputting sensitive data unless absolutely necessary.
- Regularly review and audit your Terraform configurations for security vulnerabilities.
- Use tools like
trivy,tfsec, orcheckovto scan your Terraform configurations for security issues.
- Use tools like
Modularity
- Use separate projects for each major component of the infrastructure; this:
- Reduces complexity.
- Makes it easier to manage and maintain configurations.
- Speeds up
planandapplyoperations. - Allows for independent development and deployment of components.
- Reduces the risk of accidental changes to unrelated resources.
- Use modules to avoid duplication of configurations.
- Use modules to encapsulate related resources and configurations.
- Use modules to simplify complex configurations and improve readability.
- Avoid circular dependencies between modules.
- Avoid unnecessary layers of abstraction; use modules only when they add value.
- Avoid using modules for single resources; only use them for groups of related resources.
- Avoid excessive nesting of modules; keep the module hierarchy shallow.
- Use
outputblocks to expose important information about your infrastructure.- Use outputs to provide information that is useful for other modules or for users of the configuration.
- Avoid exposing sensitive information in outputs; mark outputs as
sensitive = trueif they contain sensitive data.
Maintainability
- Prioritize readability, clarity, and maintainability.
- Use comments to explain complex configurations and why certain design decisions were made.
- Write concise, efficient, and idiomatic configs that are easy to understand.
- Avoid using hard-coded values; use variables for configuration instead.
- Set default values for variables, where appropriate.
- Use data sources to retrieve information about existing resources instead of requiring manual configuration.
- This reduces the risk of errors, ensures that configurations are always up-to-date, and allows configurations to adapt to different environments.
- Avoid using data sources for resources that are created within the same configuration; use outputs instead.
- Avoid using data sources in reusable modules. Prefer explicit module parameters over data source lookups.
- Avoid, or remove, unnecessary data sources; they slow down
planandapplyoperations.
- Use
localsfor values that are used multiple times to ensure consistency.
Style and Formatting
General Style Guidelines
- Follow Terraform best practices for resource naming and organization.
- Use descriptive names for resources, variables, and outputs.
- Use consistent naming conventions across all configurations.
- Use snake_case for all variable names.
- Follow the Terraform Style Guide for formatting.
- Use consistent indentation (2 spaces for each level).
Folder Layout and File Organization
-
Structure Terraform configurations with logical file separation:
- Use
main.tffor resources. - Use
variables.tffor inputs. - Use
outputs.tffor outputs. - Use
terraform.tffor provider configurations. - Use
locals.tfto abstract complex expressions and for better readability.
- Use
-
Use a consistent folder structure for Terraform configurations.
-
Use tfvars to modify environmental differences. In general, aim to keep environments similar.
-
A suggested structure is:
my-sap-bto-app/ ├── infra/ # Terraform root module │ ├── main.tf # Core resources │ ├── variables.tf # Input variables │ ├── outputs.tf # Outputs │ ├── provider.tf # Provider configuration │ ├── locals.tf # Local values │ └── environments/ # Environment-specific configurations │ ├── dev.tfvars # Development environment │ ├── test.tfvars # Test environment │ └── prod.tfvars # Production environment ├── .github/workflows/ # CI/CD pipelines (if using github) └── README.md # Documentation -
Never change the folder structure without direct agreement with the user.
-
If the
main.tforvariables.tffiles grow too large, split them into multiple files by resource type or function (e.g.,main.services.tf,main.rolecollectionassignments.tf- move equivalent variables tovariables.services.tf, etc.) -
Antipatterns are
- branch per environment
- repository per environment
- folder per environment
- or similar layouts that make it hard to test the root folder logic between environments.
Resource Block Organization
- Place
depends_onblocks at the very beginning of resource definitions to make dependency relationships clear.- Use
depends_ononly when necessary to avoid circular dependencies.
- Use
- Place
for_eachandcountblocks at the beginning of resource definitions to clarify the resource's instantiation logic.- Use
countfor 0-1 resources. - Use
for_eachfor multiple resources. - Use
for_eachfor collections andcountfor numeric iterations. - Prefer maps for stable resource addresses.
- Place them after
depends_onblocks, if they are present.
- Use
- Place
lifecycleblocks at the end of resource definitions. - Group related attributes together within blocks.
- Place required attributes before optional ones, and comment each section accordingly.
- Separate attribute sections with blank lines to improve readability.
- Alphabetize attributes within each section for easier navigation.
- Use blank lines to separate logical sections of your configurations.
Variables Style Standards
- All variables must have explicit type declarations.
- All variables must have a comprehensive descriptions.
- Avoid nullable defaults for collection values unless there's a specific need.
Locals Style Standards
- Use locals for computed values and complex expressions.
- Improve readability by extracting repeated expressions.
- Combine related values into structured locals.
Outputs Style Standards
- Avoid unnecessary outputs, only use these to expose information needed by other configurations.
- Use
sensitive = truefor outputs containing secrets. - Provide clear descriptions for all outputs.
Formatting and Linting
- Use
terraform fmt -recursiveto format your configurations automatically. - Use
tflintto check for style violations and ensure configurations follow best practices. - Run
tflintregularly to catch style issues early in the development process.
Documentation
- Always include
descriptionandtypeattributes for variables and outputs.- Use clear and concise descriptions to explain the purpose of each variable and output.
- Use appropriate types for variables (e.g.,
string,number,bool,list,map).
- Document your Terraform configurations using comments, where appropriate.
- Use comments to explain the purpose of resources and variables.
- Use comments to explain complex configurations or decisions.
- Avoid redundant comments; comments should add value and clarity.
- Include a
README.mdfile in each project to provide an overview of the project and its structure.- Include instructions for setting up and using the configurations.
- Use
terraform-docsto generate documentation for your configurations automatically.
State Management
- Use remote backend with state locking
- Do not use SAP BTP Object Store as a backend for Terraform state as your access is too limited to ensure a proper state management
- Never commit state files to source control
- Enable encryption at rest and in transit
Validation
- Run
terraform validateto check syntax - Ask before running
terraform plan. Terraform plan will require authentication information and the global account subdomain. The authentication information should be sourced from environment parameters or via tfvars, but MUST NOT be coded in the provider block. - Test configurations in non-production environments first
- Ensure idempotency (multiple applies produce same result)
Testing
- Write tests to validate the functionality of your Terraform configurations.
- Use the
.tftest.hclextension for test files. - Write tests to cover both positive and negative scenarios.
- Ensure tests are idempotent and can be run multiple times without side effects.
SAP BTP Provider Specifics
When provisioning SAP BTP resources, follow these additional best practices:
-
Use the data source
btp_subaccount_service_planto retrieve service plan information when provisioning the resourcebtp_subaccount_service_instance-
Sample code should look like this:
data "btp_subaccount_service_plan" "example" { subaccount_id = var.subaccount_id service_name = "your_service_name" plan_name = "your_plan_name" } resource "btp_subaccount_service_instance" "example" { subaccount_id = var.subaccount_id serviceplan_id = data.btp_subaccount_service_plan.example.id name = "my-example-instance-new" }
-
-
Use explicit dependencies between
btp_subaccount_entitlementand the data sourcebtp_subaccount_service_planto ensure correct provisioning order for the resourcebtp_subaccount_service_instancethat implictly dpeends on the data source.-
The connection between the resource
btp_subaccount_entitlementand the data sourcebtp_subaccount_service_planis not automatically inferred by the provider. -
The data source
btp_subaccount_service_plandepends on thebtp_subaccount_entitlement. -
You can derive the dependency by comparing the
service_nameandplan_nameof the resource and data source. -
Sample code should look like this:
resource "btp_subaccount_entitlement" "example" { subaccount_id = var.subaccount_id service_name = "your_service_name" plan_name = "your_plan_name" } data "btp_subaccount_service_plan" "example" { subaccount_id = var.subaccount_id service_name = "your_service_name" plan_name = "your_plan_name" depends_on = [btp_subaccount_entitlement.example] }
-
-
Use explicit dependencies between
btp_subaccount_entitlementandbtp_subaccount_subscriptionresources to ensure correct provisioning order.- The connection between
btp_subaccount_entitlementandbtp_subaccount_subscriptionis not automatically inferred by the provider. - The resource
btp_subaccount_subscriptiondepends on thebtp_subaccount_entitlement. - You can derive the dependency by comparing the
app_namewith theservice_nameand the attributesplan_name.
- The connection between
Tool Integration
Use Available Tools
- Terraform MCP Serer: Use the Terraform MCP server for provider specific guidance https://github.com/mcp/hashicorp/terraform-mcp-server
Terraform Registry
- Schema Information: Use the Terraform Provider for SAP BTP at https://registry.terraform.io/providers/SAP/btp/latest/docs for SAP BTP resources available via the MCP server
Anti-Patterns to Avoid
Configuration:
- MUST NOT hardcode values that should be parameterized
- MUST NOT use
terraform importas a regular workflow pattern - SHOULD avoid complex conditional logic that makes code hard to understand
- MUST NOT use
local-execprovisioners unless absolutely necessary - SHOULD NOT combine the Terraform provider for SAP BTP with the Terraform prpovider for Cloud Foundry in the same configuration
Security:
- MUST NEVER store secrets in Terraform files or state
- MUST NOT disable security features for convenience
- MUST NOT use default passwords or keys in resource configurations
Operational:
- MUST NOT apply Terraform changes directly to production without testing
- MUST avoid making manual changes to Terraform-managed resources
- MUST NOT ignore Terraform state file corruption or inconsistencies
- MUST NOT run Terraform from local machines for production
- SHOULD NOT use a Terraform state file (
**/*.tfstate) for read operations - MUST NOT use a Terraform state file (
**/*.tfstate) for read operations all changes must be made via Terraform CLI or HCL.