* Initial skill to use compose Fabric modules * Update CONTRIBUTING to reflect new naming patterns * Fix boilertplate * Add readme, update year * Update script and conventions * fix python format * remove random string mention * Make fetch commands explicit. Allow downloading schemas. --------- Co-authored-by: Ludovico Magnocavallo <ludomagno@google.com>
4.4 KiB
4.4 KiB
Cloud Foundation Fabric (CFF) Conventions for Module Consumers
When generating Terraform code that consumes Cloud Foundation Fabric modules, you MUST adhere to the following conventions:
1. Module Preference
- Prefer Modules: Always prefer CFF modules over raw
google_*resources. - Flat Structure: Avoid creating wrapper modules or nested module calls (modules calling other modules). Consume CFF modules directly in your root module.
2. Naming Conventions
- Use
prefix: For modules that support it (e.g.,project,gcs), using aprefixvariable is recommended but not mandatory. - Deterministic Naming: Prefer using structured, deterministic tokens rather than random strings.
3. Dependency Management
- Output-to-Input: Pass outputs from one module directly as inputs to another (e.g.,
network = module.vpc.name). - Ordering: CFF modules encapsulate dependencies (like API activation) in their outputs. Rely on these outputs to ensure correct creation order.
- Service Agents: Use the
service_agentsoutput from theprojectmodule when granting IAM roles to Google-managed service accounts. - Implicit Dependencies: Avoid explicit
depends_onunless absolutely necessary. Rely on implicit dependencies (passing outputs to inputs) for better readability and maintainability.
4. Factories
- When to Use Factories: Use factories when you need to manage a large number of similar resources (e.g., projects, VPCs, firewall rules) without duplicating module blocks. Factories separate configuration data (in YAML files) from Terraform logic.
- Main Modules with Factory Support:
project-factory: For bulk creation of projects, folders, and budgets.net-vpc-factory: For bulk creation of VPCs and associated resources.net-vpc: Supports loading subnets and internal ranges from folders viasubnets_folderandinternal_ranges_folderkeys infactories_config.net-vpc-firewall: Supports loading firewall rules from a folder viarules_folder.organizationandfolder: Support loading organization policies and custom roles.vpc-sc: Supports loading access levels and service perimeters.
- Usage: Pass the path to the directory containing YAML files to the
factories_configvariable of the respective module.
5. Style for Root Modules
- File Structure: Make file structure dependent on size. For small configurations, use a single
main.tf. For larger configurations, split into multiple files grouped by resource type (e.g.,main.tffor general elements,networking.tf,compute.tf, etc.). - Variables & Defaults:
- Define all variables in
variables.tf, sorted alphabetically. - Set defaults directly in the
defaultattribute if a reasonable default exists or if provided by the user. - Avoid creating a
terraform.tfvarsfile unless explicitly requested by the user.
- Define all variables in
- Value Handling & Providers:
- No Hardcoded Values: Never use hardcoded values for project IDs, folder IDs, or other specific identifiers unless provided by the user. If a value is required, ask the user for it or create a variable.
- Provider Parameters: Do not set provider-level parameters like
project,zone, orregionat the resource level. Set them explicitly in the module calls.
- Formatting: Adhere to standard Terraform formatting and keep line lengths readable. Wrap complex ternaries in parentheses.
- No Local Exec: Never use
local-execor similar provisioners to run shell commands. Rely on native Terraform resources and data sources, preferably from official providers (i.e., no third-party providers).
6. Impersonation and Backend Management
- Impersonation: If the user requires service account impersonation, add the
impersonate_service_accountattribute to theprovider "google"andprovider "google-beta"blocks inproviders.tf. - Remote Backend: If the user wants to use a remote backend, prefer
gcs. Put the backend configuration in theterraformblock insideproviders.tf. If impersonation is used, also set it for the backend.
Template for providers.tf:
terraform {
backend "gcs" {
bucket = "${bucket}"
impersonate_service_account = "${service_account}"
}
}
provider "google" {
impersonate_service_account = "${service_account}"
}
provider "google-beta" {
impersonate_service_account = "${service_account}"
}