https://github.com/gocloudla/gocloud-cli
GoCloud CLI - Command-line interface for managing Terraform and Standard Platform operations
https://github.com/gocloudla/gocloud-cli
automation cli devops gocloud golang infrastructure management standard-platform terraform tool
Last synced: 2 months ago
JSON representation
GoCloud CLI - Command-line interface for managing Terraform and Standard Platform operations
- Host: GitHub
- URL: https://github.com/gocloudla/gocloud-cli
- Owner: gocloudLa
- License: apache-2.0
- Created: 2025-09-14T20:31:59.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-04-02T18:16:54.000Z (3 months ago)
- Last Synced: 2026-04-03T05:22:56.680Z (3 months ago)
- Topics: automation, cli, devops, gocloud, golang, infrastructure, management, standard-platform, terraform, tool
- Language: Go
- Homepage:
- Size: 244 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# GoCloud CLI
A command-line tool to generate and manage infrastructure-as-code project structure using Terraform/Terragrunt. It is the companion CLI for the **[GoCloud Standard Platform](https://github.com/gocloudLa/terraform-aws-standard-platform)** — an enterprise-ready AWS infrastructure platform with a layered architecture (Organization → Base → Foundation → Project → Workload) and 50+ pre-configured AWS services.
> **Beta.** This software is in beta. Use it at your own responsibility.
## What it does
- **Generate directory structure** for Terraform/Terragrunt projects
- **Create config files** (main.tf, metadata.tf, terragrunt.hcl, etc.)
- **Manage secrets** in AWS SSM Parameter Store or SOPS
- **Configure AWS SSO** and generate `.aws/config`
- **Validate** YAML configuration before generating
**Note:** GoCloud CLI **does not run Terraform** — it only generates files and structure.
### Standard Platform & documentation
The structure and `main.tf` files generated by GoCloud CLI are designed to use the **[Standard Platform](https://github.com/gocloudLa/terraform-aws-standard-platform)** Terraform modules:
- **[terraform-aws-standard-platform](https://github.com/gocloudLa/terraform-aws-standard-platform)** — Platform repo: layers (organization, security, base, foundation, project, workload), usage examples, and module documentation
- **Terraform Registry:** [gocloudLa/standard-platform/aws](https://registry.terraform.io/namespaces/gocloudLa) — Published modules (e.g. `gocloudLa/standard-platform/aws//modules/base`)
- **[GoCloud (gocloudLa)](https://github.com/gocloudLa)** — Organization and other tools; [gocloud.la](https://gocloud.la) for more info
## Install
### Option 1: Download binary (recommended)
Binaries are published on [GitHub Releases](https://github.com/gocloudLa/gocloud-cli/releases). Asset names: `gocloud---` (e.g. `gocloud-v1.2.3-darwin-arm64` for Apple Silicon).
```bash
# Replace VERSION with the desired release (e.g. v1.2.3)
curl -sL -o gocloud "https://github.com/gocloudLa/gocloud-cli/releases/download/VERSION/gocloud-VERSION-darwin-arm64"
chmod +x gocloud
sudo mv gocloud /usr/local/bin/
```
### Option 2: Build from source
```bash
git clone https://github.com/gocloudLa/gocloud-cli.git
cd gocloud-cli
make build
sudo cp bin/gocloud /usr/local/bin/
```
Check for updates: `gocloud version check`. Update on macOS/Linux: `gocloud version update`.
## Quick start
```bash
gocloud config init my-project # Interactive config
cd my-project
gocloud config validate # Validate gocloud.yaml
gocloud generate # Generate directory tree and files
gocloud sso setup # Write .aws/config with profiles
gocloud sso login --all # Login to all SSO profiles
# gocloud secrets init --all # Optional: create empty secrets for all layers
```
## Commands
### Version and update
#### `gocloud version [check|update]`
Shows current CLI version; subcommands compare with GitHub Releases or replace the binary (macOS/Linux when a matching release asset exists). Installation steps for all platforms are documented on [GitHub Releases](https://github.com/gocloudLa/gocloud-cli/releases).
```bash
gocloud version # Current version (build time, commit)
gocloud version check # Check if you're on the latest release
gocloud version update # Download and replace this binary (macOS/Linux only)
```
### Config
#### `gocloud config init [project-name]`
Creates a new `gocloud.yaml` via interactive prompts.
```bash
gocloud config init my-project # Simple usage
gocloud config init my-project -o custom.yaml # Custom output path
gocloud config init my-project --skip-environments # Skip environment prompts
gocloud config init my-project --skip-aws-sso # Skip AWS SSO prompts
```
#### `gocloud config validate [--config file.yaml]`
Validates the config file (required fields, types, unknown keys; reports errors and warnings).
```bash
gocloud config validate # Simple usage
gocloud config validate --config custom.yaml # Validate specific file
gocloud config validate --strict # Extra validation rules
```
### Generate
#### `gocloud generate [--config file.yaml]`
Reads `gocloud.yaml` and generates the directory tree (base, foundation, project, workload), config files (main.tf, metadata.tf, terragrunt.hcl, backend.tf, providers.tf, _secrets.tf where enabled), optionally a root `.gitignore` when `infrastructure.enable_gitignore` is not `false` (default: true), and project README.md. Validation runs first. New dirs/files are created without prompting; existing `main.tf` are never overwritten (only the module version line is updated when you change version in config); other changed files (including `.gitignore` when enabled) prompt before overwrite.
```bash
gocloud generate # Simple usage
gocloud generate --dry-run # Preview without writing files
gocloud generate --force # Overwrite existing files (except main.tf)
gocloud generate --working-dir custom-dir # Output to custom directory
gocloud generate --config custom.yaml # Use specific config file
```
### AWS SSO
#### `gocloud sso setup`
Writes `.aws/config` with one profile per environment (`{client}-{environment}`).
```bash
gocloud sso setup
```
#### `gocloud sso list`
Lists configured AWS SSO profiles (numbered for selection).
```bash
gocloud sso list
```
#### `gocloud sso login`
Login to AWS SSO profiles.
```bash
gocloud sso login # Interactive: choose profile
gocloud sso login --all # Login to all profiles
gocloud sso login --profiles prd,sha # Login to specific profiles
```
#### `gocloud sso verify`
Checks credential and account ID status (OK / Expired or Invalid / Account Mismatch).
```bash
gocloud sso verify
```
### Secrets
Manage secrets (e.g. DB URLs, API keys) that Terraform reads in each layer. Available providers:
- **SSM (default):** Stored in AWS. No extra tools; use your SSO profiles.
- **SOPS:** Stored in encrypted files; requires the `sops` binary and KMS (details in **Secrets control** below).
#### `gocloud secrets check [layer-path]`
Checks if the secrets store exists for that layer (SSM: parameter; SOPS: `_secrets.yaml`).
```bash
gocloud secrets check base/production # One layer
gocloud secrets check --environment dev # All layers in an environment
gocloud secrets check --all # All layers
```
#### `gocloud secrets init [layer-path]`
Creates empty secrets for the layer (SSM: new parameter with `{}`; SOPS: creates or ensures `_secrets.yaml` and KMS key).
```bash
gocloud secrets init foundation/dev # One layer
gocloud secrets init --environment dev # All layers in an environment
gocloud secrets init --all # All layers
```
#### `gocloud secrets list `
Lists all secret keys for that layer.
```bash
gocloud secrets list base/production
gocloud secrets list project/core/production
```
#### `gocloud secrets get `
Gets the value of one secret key for that layer.
```bash
gocloud secrets get base/production database_url
gocloud secrets get project/core/production api_key
```
#### `gocloud secrets set `
Sets the value of one secret.
```bash
gocloud secrets set base/production database_url "postgresql://..."
gocloud secrets set project/core/production api_key "secret-key"
```
#### `gocloud secrets delete `
Removes one secret key from that layer.
```bash
gocloud secrets delete base/production database_url
gocloud secrets delete project/core/production api_key
```
#### `gocloud secrets edit `
Opens your editor to edit the layer’s secrets as JSON (validated on save).
```bash
gocloud secrets edit base/production
gocloud secrets edit project/core/production
```
### Health
Check AWS managed notification events per environment (AWS User Notifications / Notification Center → AWS managed). This helps reduce noise from emails/SNS by presenting events grouped by environment.
#### `gocloud health check`
Lists managed notification events for one environment or all.
```bash
gocloud health check --environment prd
gocloud health check --environment org # organization account ({client}-org) when configured
gocloud health check --environment sec # security account ({client}-sec) when configured
gocloud health check --all
```
Filter controls:
```bash
gocloud health check --all --managed-days 180
gocloud health check --all --include-ended # include events whose end time is already past
```
Output format:
```bash
gocloud health check --all --output list # default
gocloud health check --all --output table
```
### Modules
Generate READMEs for Terraform modules from a YAML config and optional template.
```bash
gocloud module readme generate # From README.yml (default), output README.md
gocloud module readme generate-example # Same for example-style READMEs
```
### Shell completion
Prints a script to source so that Tab completes commands, layer paths, and secret keys. Add to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.).
```bash
gocloud completion bash # Bash
gocloud completion zsh # Zsh (e.g. macOS default)
gocloud completion fish # Fish
gocloud completion powershell # PowerShell
```
## Configuration file (`gocloud.yaml`)
GoCloud uses a single YAML file to define your project: client name, AWS accounts and regions, layers to generate (see **Layer control**), backend (Terraform state), AWS SSO (login), and secrets (SSM or SOPS). Everything below is optional except the fields marked required. Default is set at **Infrastructure**; overrides apply in order: **Environment** → **Project** / **Workload** (more specific wins).
**Override levels** (where each option can be set):
| Config | Infrastructure | Environment | Project | Workload |
|--------|:---:|:---:|:---:|:---:|
| Backend | ✓ | ✓ | ✓ | ✓ |
| Providers | ✓ | ✓ | ✓ | ✓ |
| Secrets | ✓ | ✓ | ✓ | ✓ |
| Terragrunt | ✓ | ✓ | ✓ | ✓ |
| SSO | ✓ | ✓ | — | — |
| Region | ✓ | ✓ | — | — |
| Version | ✓ | ✓ | — | — |
| Source | ✓ | ✓ | — | — |
| Layers | ✓ | ✓ (base, foundation only) | — | — |
| Metadata | ✓ | ✓ | — | — |
### General structure
Below, each key is explained in comments. For backend and providers, see **Backend** and **Providers**.
```yaml
# CLI behaviour (all optional; uncomment to override)
cli:
# working_dir: "." # (default) project root
# auto_backup: true # (default) backup config before overwriting
# backup_dir: ".bkp" # (default)
# verbose: false # (default)
# debug: false # (default)
infrastructure:
client: "my-client" # Required. Client/project name (e.g. SSO profile names)
company: "gcl" # Required. Short prefix, 2–10 chars (bucket names, SSM paths)
region: "us-east-1" # Required. Default AWS region
# version: "0.17.0" # (default) module version in main.tf
# enable_secrets: true # (default: true) generate _secrets.tf and gocloud secrets commands
# enable_sso: true # (default: true) generate SSO profile
# enable_terragrunt: true # (default: true) generate terragrunt.hcl files
# enable_gitignore: true # (default: true) generate root .gitignore
# # Optional: use Git repo instead of Terraform registry for modules
# source: "git@github.com:org/repo.git"
# source_ref: "main" # branch, tag, or commit
# Backend: Terraform state (S3 + DynamoDB).
backend:
# pattern: "s3-backend" # (default)
# region: "us-east-1" # (default: uses infrastructure.region)
# account: "sha" # (default) environment key where state bucket lives
# encrypt: true # (default)
# type: "s3" # (default)
# use_profile: true # (default)
# key_template: "..." # (optional) Custom state path
# role_template: "..." # (optional) Custom assume_role name
# bucket_name: "custom-bucket" # Custom bucket (optional; default: {company}-{account}-{pattern})
# dynamodb_table_name: "custom-table" # Custom lock table (optional; default: {company}-{account}-{pattern})
# AWS SSO: required for gocloud sso setup. Generates .aws/config with profiles {client}-{environment}.
aws_sso:
# region: "us-east-1" # (default: uses infrastructure.region)
start_url: "https://my-client.awsapps.com/start#/" # Required. IAM Identity Center URL
role_name: "Admin" # Required. Role name after SSO login
# Layers (default: all true). organization/security only if respective aws_account set; see Layer control.
layers:
# base: true # (default)
# foundation: true # (default)
# organization: true # (default)
# security: true # (default)
# Custom metadata (optional): injected into every metadata.tf.
# Default/fallback for all layers unless a more specific metadata is set.
# metadata:
# public_domain: "gocloud.la"
# private_domain: "gocloud.private"
metadata:
public_domain: "gocloud.la" # (optional) add any key-value pairs
private_domain: "gocloud.private"
internal_domain: "gocloud.internal"
# Secrets backend (optional, default: "ssm")
# secrets:
# type: "ssm" # or "sops"
# Providers: AWS providers in providers.tf. Uncomment to customize.
# providers:
# use_profiles: true # (default: true)
# default_providers:
# - name: "aws"
# region: "local.metadata.aws_region"
# - name: "aws"
# region: "us-east-1"
# alias: "use1"
# # (optional) assume_role for cross-account
# # - name: "aws"
# # assume_role:
# # role_arn: "arn:aws:iam::123456789012:role/RoleName"
# # session_name: "TerraformSession"
# Optional: organization layer + SSO profile {client}-org (uncomment to enable)
organization:
aws_account: "123456789012" # Required for SSO: creates profile {client}-org
# metadata: {} # (optional) metadata override for organization layer
# enable_secrets: true # (optional) secrets only for organization (overrides global enable_secrets)
# aws_sso: # (optional) override SSO for org profile
# start_url: "https://..."
# role_name: "Admin"
# backend: {} # (optional) override backend for organization layer
# providers: {} # (optional) override providers for organization layer
# secrets: # (optional) override secrets type organization layer
# type: "sops"
# Optional: security layer (global) + SSO profile {client}-sec — same fields as organization, dir security/, module //modules/security; generated main.tf wires aws.log and aws.kms into the module (override in main.tf if you use other aliases)
# security:
# aws_account: "123456789013"
# metadata: {} # (optional) metadata override for security layer
# Environments: each key is an environment (shared, dev, production, etc.). Required: aws_account per env.
environments:
shared:
name: "Shared" # (optional; default: key) display name
# dir_name: "shared" # (optional; default: key) directory name in generated tree
aws_account: "123456789013" # Required. 12-digit AWS account ID
# region: "us-east-1" # (default: infrastructure.region)
# version: "0.17.0" # (default: infrastructure.version)
# enable_secrets: true # (default: inherit from global)
# enable_sso: true # (default: inherit from global)
# enable_terragrunt: true # (default: true)
# layers: # (optional) disable layer for this environment
# base: true
# foundation: true
# aws_sso: # (optional) override start_url / role_name for this env
# start_url: "https://..."
# role_name: "Admin"
# metadata: {} # (optional) metadata override for this environment
# secrets: { type: "ssm" } # (optional) backend for this env
projects: ["core", "common"] # Project subdirs (e.g. project/core/shared)
workloads: ["webapp", "api"] # Workload subdirs (e.g. workload/webapp/shared)
```
---
### Environments
**What they are:** Each entry under `environments` is an environment (e.g. shared, dev, production) with its own AWS account (or shared). GoCloud generates one directory tree per environment under `base/`, `foundation/`, `project//`, `workload//`. Environments inherit global config; you can override per environment.
```yaml
infrastructure:
environments:
dev:
name: "Development" # (optional; default: key) display name
aws_account: "111111111111" # Required
# dir_name: "dev" # (default: key)
# region: "us-east-1" # (default: infrastructure.region)
# version: "0.17.0" # (default: infrastructure.version)
# enable_secrets: true # (default: inherit)
# enable_sso: true # (default)
# enable_terragrunt: true # (default)
# layers: { base: true, foundation: true } # (optional)
# aws_sso: { start_url: "...", role_name: "..." } # (optional) override for this env
# secrets: { type: "ssm" } # (optional)
projects: ["core", "common"]
workloads: ["webapp", "api"]
shared:
name: "Shared"
aws_account: "111111111111"
# dir_name: "shared" # (default: key)
layers: # (optional) disable base only in this env
base: true
foundation: false
projects: ["core", "common"]
workloads: ["webapp", "api"]
production:
name: "Production"
dir_name: "production" # (optional) custom dir name
aws_account: "222222222222"
region: "eu-west-1" # (optional) override region
version: "0.14.0" # (optional) override module version
enable_secrets: false # (optional) disable secrets for this env
enable_sso: false # (optional) no SSO profile for this env
aws_sso: # (optional) different SSO for this env
start_url: "https://prod.awsapps.com/start#/"
role_name: "ProductionAdmin"
projects: ["core", "common"]
workloads: ["webapp", "api"]
```
---
### Projects and workloads
**What they are:** For each environment you list *projects* (e.g. core, common) and *workloads* (e.g. webapp, api). They become directories like `project/core/production` and `workload/webapp/production`. The directory name is the key by default; you can set `name` (display + dir from lowercased name) or `dir_name` (exact directory name). Projects and workloads can have `depends_on` (e.g. project: `["foundation"]` or `[]`; workload: which project layers they depend on) and per-item `enable_secrets` / `enable_terragrunt`.
```yaml
infrastructure:
environments:
production:
projects:
- core # (default) dir = key
- common
- dept: # key: dept
name: "Deposits" # (optional) dir from name lowercased
- wdwl:
name: "Withdrawals"
dir_name: "withdrawals" # (optional) exact dir name
# enable_terragrunt: true # (default: true)
workloads:
- webapp
- api
- blockchain-service:
depends_on: ["project/common", "project/core"] # (optional) custom deps
- legacy-app:
enable_secrets: false # (optional) disable secrets for this workload
- dept:
name: "Deposits"
dir_name: "deposits"
enable_secrets: false
# depends_on: ["project/core"] # (default: auto)
```
---
### Layer control
GoCloud generates: **organization** (if `infrastructure.organization.aws_account` set), **security** (if `infrastructure.security.aws_account` set), **base**, **foundation**, plus **project** / **workload** from each environment's lists. **Override levels:** see table above (Infrastructure + Environment only; per env only `base` and `foundation` can be disabled).
**Example** (global + override per env):
```yaml
infrastructure:
layers:
base: true
foundation: true
organization: true
security: true
environments:
staging:
layers:
base: false
foundation: true
```
---
### Secrets control
Secrets (e.g. DB URLs, API keys) are read by Terraform via `_secrets.tf`. GoCloud stores them in **SSM** (default) or **SOPS** (encrypted files; requires `sops` and KMS). Use `enable_secrets: false` to disable per layer, or `secrets.type: "sops"` to switch backend. **Override levels:** see table above.
**Example** (global + overrides at env, project, workload):
```yaml
infrastructure:
enable_secrets: true
secrets:
type: "ssm"
environments:
production:
secrets:
type: "sops"
projects:
- example:
secrets:
type: "sops"
workloads:
- legacy-app:
enable_secrets: false
```
---
### Root `.gitignore`
GoCloud generates a root `.gitignore` when `enable_gitignore: true` (default). It uses the same generated-file header and overwrite prompts as `providers.tf`. Set `false` if you manage `.gitignore` yourself—the CLI will not create or update it. **Override levels:** infrastructure only.
**Example** (opt out):
```yaml
infrastructure:
enable_gitignore: false
```
### Terragrunt control
GoCloud generates `terragrunt.hcl` per layer when `enable_terragrunt: true` (default). If you set `false`, existing `terragrunt.hcl` in that scope is removed. **Override levels:** see table above.
**Example** (global + overrides at env, project, workload):
```yaml
infrastructure:
enable_terragrunt: true
environments:
staging:
enable_terragrunt: false
production:
projects:
- legacy-system:
enable_terragrunt: false
workloads:
- legacy-app:
enable_terragrunt: false
```
---
### SSO control
GoCloud generates `.aws/config` with one profile per environment (see **gocloud sso setup** in Commands). Default: `enable_sso: true`; each env gets a profile from global `aws_sso`. Set `enable_sso: false` per env to skip; set `aws_sso` per env to override `start_url` or `role_name`. **Override levels:** see table above (Infrastructure + Environment only).
**Example** (global + overrides per env):
```yaml
infrastructure:
aws_sso:
start_url: "https://my-client.awsapps.com/start#/"
role_name: "Admin"
environments:
dev:
aws_account: "111111111111"
stg:
aws_account: "222222222222"
enable_sso: false
prd:
aws_account: "222222222222"
aws_sso:
role_name: "ProductionAdmin"
```
---
### Regions per environment
AWS region used in `metadata.tf` and provider configs. Default: all environments use `infrastructure.region`. Set `region` per environment to override. **Override levels:** see table above (Infrastructure + Environment only).
**Example** (global + override per env):
```yaml
infrastructure:
region: "us-east-1"
environments:
dev:
aws_account: "111111111111"
production:
aws_account: "222222222222"
region: "eu-west-1"
```
---
### Versions per environment
Module version written in generated `main.tf` (e.g. `version = "0.17.0"`). Default: all environments use `infrastructure.version`. Set `version` per environment to override; only affected `main.tf` files are updated. **Override levels:** see table above (Infrastructure + Environment only).
**Example** (global + overrides per env):
```yaml
infrastructure:
version: "0.17.0"
environments:
sha:
version: "latest"
prd:
version: "v2.14.0"
```
---
### Custom source (Git)
By default, `main.tf` uses the Terraform registry with `version`. Set `source` (repo URL) and `source_ref` (branch, tag, or commit) to use a Git repo instead; GoCloud then generates `source = "git@...//path?ref=..."` and omits `version`. **Override levels:** see table above (Infrastructure + Environment only).
**Example** (global + overrides per env):
```yaml
infrastructure:
version: "0.17.0"
environments:
dev:
source: "git@github.com:org/terraform-module.git"
source_ref: "feature/new-feature"
prd:
source: "git@github.com:org/terraform-module.git"
source_ref: "v1.0.0"
```
---
### Custom metadata
Optional key-value pairs (e.g. domain names, team) injected into every `metadata.tf`.
Priority (more specific wins):
- `infrastructure.organization.metadata` for the `organization` layer
- `infrastructure.security.metadata` for the `security` layer
- `infrastructure.environments..metadata` for env-based layers (`base`, `foundation`, `project`, `workload`)
- `infrastructure.metadata` as global fallback
**Example:**
```yaml
infrastructure:
metadata:
public_domain: "gocloud.la"
private_domain: "gocloud.private"
internal_domain: "gocloud.internal"
company_email: "devops@gocloud.la"
support_team: "platform"
# any_other_key: "value" # add any key-value pairs you need
organization:
aws_account: "123456789012"
metadata:
support_team: "platform-org" # overrides global for organization layer only
security:
aws_account: "123456789013"
metadata:
support_team: "platform-sec" # overrides global for security layer only
environments:
dev:
aws_account: "111111111111"
metadata:
support_team: "platform-dev" # overrides global for dev env layers
```
---
### Backend
GoCloud generates `backend.tf` (Terraform state: S3 + DynamoDB). If you omit `backend:`, defaults are used: `pattern: "s3-backend"`, `region` from infrastructure, `account: "sha"`, `encrypt: true`, `type: "s3"`, `use_profile: true`. Bucket and table names default to `{company}-{account}-{pattern}`. **Override levels:** see table above.
#### Template variables
**Variables available in `key_template`** (state file path):
- `{{.AccountID}}` — AWS account ID (e.g. `"123456789012"`)
- `{{.Layer}}` — Layer type (e.g. `"base"`, `"foundation"`, `"project"`, `"workload"`)
- `{{.Project}}` — Project key (only for project/workload layers; e.g. `"core"`, `"dept"`)
- `{{.Environment}}` — Environment key (e.g. `"prd"`, `"dev"`, `"stg"`)
- `{{.EnvironmentName}}` — From environment `name`: lowercased, spaces → underscores.
- `{{.Company}}` — Company prefix (e.g. `"gcl"`)
- `{{.Region}}` — AWS region (e.g. `"us-east-1"`)
- `{{.Client}}` — Client name (e.g. `"test-client"`)
**Variables available in `role_template`** (assume_role role name):
- `{{.AccountID}}` — AWS account ID of the current environment (e.g. `"123456789012"`)
- `{{.BackendAccountID}}` — AWS account ID of the backend environment (e.g. `"123456789013"`)
- `{{.Company}}` — Company prefix (e.g. `"gcl"`)
- `{{.BackendAccount}}` — Environment key of the backend (e.g. `"sha"`)
- `{{.Layer}}` — Layer type (e.g. `"base"`, `"foundation"`, `"project"`, `"workload"`)
- `{{.Project}}` — Project key (only for project/workload layers)
- `{{.Environment}}` — Environment key (e.g. `"prd"`, `"dev"`, `"stg"`)
- `{{.EnvironmentName}}` — From environment `name`: lowercased, spaces → underscores (same normalization as display-name→folder for projects/workloads).
- `{{.Region}}` — AWS region (e.g. `"us-east-1"`)
- `{{.Client}}` — Client name (e.g. `"test-client"`)
Default `role_template` if not set: `{{.Company}}-{{.BackendAccount}}-{{.BackendPattern}}-{{.AccountID}}`.
**Example** (global + overrides at env, project, workload):
```yaml
infrastructure:
backend:
pattern: "s3-backend"
region: "us-east-1"
account: "sha"
key_template: "{{.AccountID}}/{{.Layer}}/terraform.tfstate"
role_template: "{{.Company}}-{{.BackendAccount}}-{{.AccountID}}"
environments:
prd:
backend:
key_template: "{{.Company}}/{{.Environment}}/{{.Layer}}/terraform.tfstate"
projects:
- core:
backend:
key_template: "{{.Company}}/core/{{.Environment}}/terraform.tfstate"
role_template: "project-{{.BackendAccount}}-{{.AccountID}}"
workloads:
- api:
backend:
role_template: "workload-{{.BackendAccount}}-{{.AccountID}}"
```
---
### Providers
GoCloud generates `providers.tf` (AWS providers). If you omit `providers:`, defaults are used: `use_profiles: true` and one AWS provider with `region = local.metadata.aws_region` (reference to `locals` in `metadata.tf`) plus an optional second with `region = "us-east-1"`, `alias: "use1"`. For `default_providers[].region`, values that match the same built-in AWS region list used for `metadata.key.region` short codes are written quoted in HCL; anything else is copied unchanged (`local.*`, `var.*`, `${...}`, etc.). With `use_profiles: true`, the CLI sets `profile` on each `aws` entry to the SSO profile for that layer (`{client}-{environment}`, `{client}-org`, `{client}-sec`) **only when that entry has no `profile` in YAML**; if you set `profile` on a `default_providers` line, that value is left unchanged. **Override levels:** see table above.
**Example** (global + overrides at env, project, workload):
```yaml
infrastructure:
providers:
use_profiles: true
default_providers:
- name: "aws"
region: "local.metadata.aws_region"
- name: "aws"
region: "us-east-1"
alias: "use1"
environments:
prd:
providers:
use_profiles: false
default_providers:
- name: "aws"
region: "us-west-2"
projects:
- core:
providers:
default_providers:
- name: "aws"
region: "us-east-1"
alias: "primary"
workloads:
- api:
providers:
default_providers:
- name: "aws"
region: "eu-west-1"
alias: "europe"
```
---
### Workload dependencies
**What it is:** Terragrunt (and the generated structure) needs to know which layers a workload depends on. **By default, dependencies are assigned automatically.**
**Default dependencies:**
- `base`: depends on nothing
- `foundation`: depends on `base/{env}`
- `project/{name}`: depends on `foundation/{env}`
- `workload/{name}`: depends on `project/{name}/{env}` if that project exists for the environment, otherwise `project/common/{env}` (fallback)
Use `depends_on` on a **project** (e.g. `["foundation"]`, `["base", "foundation"]`, or `[]` for none) or on a **workload** (e.g. `["project/common", "project/core"]`, or `[]` for no dependencies).
**Behavior:**
- **Default**: Automatic dependencies based on layer hierarchy
- **Custom**: You can specify relative paths in `depends_on` (project: `foundation` / `base`; workload: `project/`, `foundation`, `base`)
- **No dependencies**: Use `depends_on: []` to disable
Sample configuration block
```yaml
infrastructure:
environments:
production:
workloads:
- blockchain-service:
depends_on: ["project/common", "project/core"] # (optional) custom deps
- standalone-app:
depends_on: [] # (optional) no dependencies
# - webapp: # (default) auto: project/common or project/; omit depends_on
# depends_on: []
```
---
### Directory names
**What it is:** The folder name for a project or workload (e.g. `project/core/production` vs `project/deposits/production`). **By default, the directory name is the key** you use in YAML.
**Priority** (highest to lowest):
1. **`dir_name`** — Exact directory name you specify
2. **`name`** — Display name converted to lowercase for the directory
3. **`key`** — The project/workload key (fallback)
**Behavior:**
- **Default**: The key is used as the directory name (e.g. `core` → `core/`)
- **With `name`**: Name is lowercased for the directory (e.g. `"Deposits"` → `deposits/`)
- **With `dir_name`**: The exact value is used (e.g. `"withdrawals"` → `withdrawals/`)
Sample configuration block
```yaml
# Default (key as directory)
projects:
- core # Directory: "core"
- common # Directory: "common"
# Project with custom name → directory from name lowercased
- dept: # Key: "dept"
name: "Deposits" # Directory: "deposits"
# Project with custom directory name
- wdwl: # Key: "wdwl"
name: "Withdrawals"
dir_name: "withdrawals" # Directory: "withdrawals"
workloads:
- webapp
- api
```
## Shell completion
### macOS (Zsh — recommended)
```bash
# Add completion to ~/.zshrc
echo 'source <(gocloud completion zsh)' >> ~/.zshrc
# Reload config
source ~/.zshrc
# Test completion
gocloud
```
### macOS (Bash)
```bash
# Install bash-completion
brew install bash-completion@2
# Add to ~/.bash_profile
echo '[[ -r "$(brew --prefix)/etc/profile.d/bash_completion.sh" ]] && . "$(brew --prefix)/etc/profile.d/bash_completion.sh"' >> ~/.bash_profile
echo 'source <(gocloud completion bash)' >> ~/.bash_profile
source ~/.bash_profile
```
### Linux
```bash
# Ubuntu/Debian
sudo apt install bash-completion
# CentOS/RHEL/Fedora
sudo yum install bash-completion
# or
sudo dnf install bash-completion
# Configure completion
echo 'source <(gocloud completion bash)' >> ~/.bashrc
source ~/.bashrc
```
## Troubleshooting
### Error: "failed to get shared config profile, default"
```bash
# The issue is that .aws/config does not exist
# Fix: Configure AWS SSO first
gocloud sso setup
gocloud sso login --all
```
### Completion not working on macOS
```bash
# If you get "command not found: compdef"
# Add at the TOP of ~/.zshrc:
echo 'autoload -Uz compinit' | cat - ~/.zshrc > ~/.zshrc.tmp && mv ~/.zshrc.tmp ~/.zshrc
echo 'compinit' | cat - ~/.zshrc > ~/.zshrc.tmp && mv ~/.zshrc.tmp ~/.zshrc
# Reload
source ~/.zshrc
```
### AWS CLI not found
```bash
# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```
### main.tf files not updating
`main.tf` files are protected from overwriting to preserve your custom logic. They are only updated automatically when the module version changes.
## Related
- **[Standard Platform](https://github.com/gocloudLa/terraform-aws-standard-platform)** — Terraform modules and layer documentation
- **[Terraform Registry](https://registry.terraform.io/namespaces/gocloudLa)** — `gocloudLa/standard-platform/aws` modules
- **[GoCloud](https://github.com/gocloudLa)** — Organization · [gocloud.la](https://gocloud.la)
## Development
**Prerequisites:** Go 1.25.1, golangci-lint (for linting).
```bash
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest # Install linter
make build # Build binary
make test # Run tests
make lint # Run linter
make fmt # Format code
make pre-commit # fmt + lint + test
```
See `make help` for all targets (e.g. `make quality`, `make deps-check`, `make test-coverage`).
## License
This project is under the MIT License. See the `LICENSE` file for details.