{"id":44820540,"url":"https://github.com/tjirsch/rs-cfg2hcl","last_synced_at":"2026-02-16T20:01:21.739Z","repository":{"id":338281502,"uuid":"1157095086","full_name":"tjirsch/rs-cfg2hcl","owner":"tjirsch","description":"A tool to transpile compact YAML infrastructure definitions into OpenTofu/Terraform HCL. Builtin functions to bootstrap a Google Cloud Organization and do state import, migration and discovery of an existing GCP Organization from state or live infrastructure.","archived":false,"fork":false,"pushed_at":"2026-02-13T15:21:13.000Z","size":151,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-14T01:32:36.715Z","etag":null,"topics":["discovery","gcp","google","hcl","opentofu"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tjirsch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T12:27:28.000Z","updated_at":"2026-02-13T16:34:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tjirsch/rs-cfg2hcl","commit_stats":null,"previous_names":["tjirsch/rs-cfg2hcl"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/tjirsch/rs-cfg2hcl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjirsch%2Frs-cfg2hcl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjirsch%2Frs-cfg2hcl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjirsch%2Frs-cfg2hcl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjirsch%2Frs-cfg2hcl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tjirsch","download_url":"https://codeload.github.com/tjirsch/rs-cfg2hcl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tjirsch%2Frs-cfg2hcl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29516871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T18:37:19.720Z","status":"ssl_error","status_checked_at":"2026-02-16T18:36:46.920Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["discovery","gcp","google","hcl","opentofu"],"created_at":"2026-02-16T20:00:37.242Z","updated_at":"2026-02-16T20:01:21.727Z","avatar_url":"https://github.com/tjirsch.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cfg2hcl\n\nA tool to transpile compact YAML infrastructure definitions into OpenTofu/Terraform HCL.\nBuiltin functions to bootstrap a Google Cloud Organization and do state import, migration and discovery of an existing GCP Organization from state or live infrastructure.\n\n## Folder Structure\n\nThe project is structured such that `cfg2hcl` (the tool) is kept separate from customer-specific definitions. Each customer repository follows this layout:\n\n```text\ncustomer-repo/ (e.g. project-root/)\n├── config.toml          # Tool configuration for this customer\n├── schemas/             # JSON schemas for used cloud providers\n├── yaml/                # Infrastructure definitions\n└── hcl/                 # Generated .tf files\n```\n\n### Global Options\n\nThese options can be placed anywhere in the command (e.g., before or after subcommands):\n\n- `-c, --config \u003cFILE\u003e`: Path to tool config file. Mandatory for most commands if `config.toml` is not in the current directory.\n- `-v, --validation \u003cLEVEL\u003e`: Validation level for mandatory parameters (`warn`, `error`, `none`).\n- `--verbose`: Enable verbose output. When invoked without a subcommand (e.g. `cfg2hcl --verbose`), prints full recursive help listing all subcommands and their options.\n\n## Installation\n\n### Using cargo-dist Installer (Recommended)\n\nInstall the latest release using the cargo-dist installer:\n\n```bash\ncurl --proto '=https' --tlsv1.2 -LsSf https://github.com/tjirsch/rs-cfg2hcl/releases/latest/download/cfg2hcl-installer.sh | sh\n```\n\nThis will install `cfg2hcl` to `~/.local/bin` and automatically add it to your PATH if needed.\n\n\u003e **Note:** The installer will:\n\u003e - Install the binary to `~/.local/bin`\n\u003e - Check if this directory is on your PATH\n\u003e - If not, add it to your shell profile (e.g., `.bashrc`, `.zshrc`)\n\u003e - Provide instructions to refresh your shell\n\u003e\n\u003e If you prefer a different location, you can override it:\n\u003e ```bash\n\u003e curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tjirsch/rs-cfg2hcl/releases/latest/download/cfg2hcl-installer.sh | CARGO_DIST_FORCE_INSTALL_DIR=/your/custom/path sh\n\u003e ```\n\n\u003e **Note:** The installer script is generated automatically when releases are created. If you get a 404 error, it means no releases have been published yet. Use the \"From Source\" method below instead.\n\n### From Source\n\nTo install the binary to `/usr/local/bin` (requires sudo):\n```bash\ncargo xtask install\n```\nThis command safely builds the release binary as your user and then uses `sudo` only for the copy step. It works from any subdirectory in the project.\n\nAlternatively, install directly with cargo:\n```bash\ncargo install --path .\n```\nThis installs to `~/.cargo/bin` (no sudo required).\n\n## CLI Usage\n\n### Initialize Project (`init`)\nBootstrap a new project directory with default folders, config, .gitignore, and schemas.\n\n```bash\ncfg2hcl init \\\n  --customer-id C01234567 \\\n  --customer-shortname example-org \\\n  --billing-account-infra A12345-B67890-C12345 \\\n  --customer-domain example.com \\\n  --customer-organization-id \"123456789012\"\n```\n\n**Parameters:**\n- `--defaults \u003cLIST\u003e`: Default provider sets to include (e.g., `google`).\n- `--providers \u003cLIST\u003e`: Explicit providers to include (e.g., `aws`, `azure`, `google`).\n- `--tf-tool \u003cTOOL\u003e`: Terraform binary to use (default: `tofu`).\n- `--customer-id \u003cID\u003e`: Workspace Organization ID (e.g., `C01234567`).\n- `--customer-shortname \u003cNAME\u003e`: Short slug for the customer.\n- `--billing-account-infra \u003cID\u003e`: Billing account ID.\n- `--customer-organization-id \u003cID\u003e`: GCP Organization ID.\n- `--customer-domain \u003cDOMAIN\u003e`: Primary domain name.\n- `--iac-user \u003cEMAIL\u003e`: Initial Admin User (default: `first.admin@\u003ccustomer-domain\u003e`).\n- `--default-region \u003cREGION\u003e`: Default GCP region (default: `europe-west3`).\n- `--infra-project-name \u003cID\u003e`: Override for the infrastructure project ID.\n- `--infra-bucket-name \u003cNAME\u003e`: Override for the state bucket name.\n\n**Under the Hood:**\n- Creates the standardized directory structure: `yaml/`, `hcl/`, `schemas/`.\n- Generates a default `config.toml` and `.gitignore`.\n- If customer details are provided, generates a template YAML file in `yaml/`.\n- Fetches the latest provider schemas for the configured providers.\n\n### Day 0 Bootstrap (`bootstrap`)\nThe `bootstrap` command automates the entire onboarding process for a new customer organization.\n\n```bash\ncfg2hcl bootstrap \u003cCONFIG_FILE\u003e [options]\n```\n\n**Parameters:**\n- `\u003cCONFIG_FILE\u003e`: Path to the YAML config file (e.g., `yaml/C01234567.yaml`).\n- `--dry-run`: Simulation mode; does not create resources.\n**Tip:** Use `--dry-run` to see what resources would be created without making changes.\n\n**Tip:** For a declarative approach, set `deployment-mode: boot` in your YAML and run `transpile`.\n\n**Under the Hood:**\n1.  **Authentication**: Uses Application Default Credentials (ADC).\n2.  **Infrastructure Folder**: Checks availability or creates the top-level folder (requires `Folder Admin`).\n3.  **Project Shell**: Creates the management project (project-id defaults to `shortname-iac-infra`) inside the folder.\n4.  **Billing Link**: Links the project to the specified Billing Account.\n5.  **Enable APIs**: Enables critical foundation APIs (Service Usage, Cloud Resource Manager, IAM, Storage).\n6.  **State Bucket**: Creates the GCS bucket for Terraform state (with versioning, uniform access).\n7.  **Automated Setup**:\n    - **Transpile**: Converts the YAML to HCL.\n    - **Init**: Runs `tofu init` to download plugins.\n    - **Import**: Automatically imports the created Folder, Project, and Bucket into the local state.\n\n### Transpile (`transpile`)\nConvert your YAML configuration to production-ready HCL.\n\n```bash\ncfg2hcl transpile \u003cINPUT\u003e [options]\n```\n\n**Parameters:**\n- `\u003cINPUT\u003e`: Name of the input YAML file. This is resolved relative to the `yaml_dir` defined in your config.\n- `--output, -o \u003cFILE\u003e`: Optional output subdirectory or absolute path. By default, output goes to `hcl_dir`.\n- `--schema-dir, -s \u003cDIR\u003e`: Override the schema directory.\n\n**Running from subdirectories:**\nYou can run the transpile command from any directory (e.g., from within the `hcl/` folder) by specifying the config path. Both styles are supported:\n```bash\n# Global option before subcommand\ncfg2hcl --config ../config.toml transpile my-infra.yaml\n\n# Global option after subcommand (Recommended)\ncfg2hcl transpile my-infra.yaml --config ../config.toml\n```\nThis will correctly look for `../yaml/my-infra.yaml` and update the files in the current directory.\n\n**Under the Hood:**\n- Reads the YAML file and processes any `!include` tags.\n- strict Validation: Checks the YAML against the loaded provider schemas `schemas/*.json` to ensure all required fields are present.\n- Merges variables from the `variables` block into the configuration.\n- Generates four files in the output directory:\n    - `main.tf`: Resources.\n    - `providers.tf`: Provider configurations and aliases.\n    - `variables.tf`: Variable declarations.\n    - `terraform.tfvars`: Variable values.\n    - `imports.tf`: (Optional) OpenTofu `import` blocks for existing resources.\n\n### Resource Imports\n\n`cfg2hcl` supports declarative resource imports using the OpenTofu/Terraform 1.5+ `import` block logic. This allows you to bring existing cloud resources under management without manually running CLI `import` commands.\n\n#### Declarative Imports (via `import-id`)\n\nTo import an existing resource, add the `import-id` tag to its definition in your YAML:\n\n```yaml\ngoogle_org_policy_policy:\n  iam.disableServiceAccountKeyCreation:\n    import-id: \"organizations/12345/policies/iam.disableServiceAccountKeyCreation\"\n    spec:\n      rules:\n        - enforce: \"TRUE\"\n```\n\n**How it works:**\n- **`import-id: \"\u003cID\u003e\"`**: Provide the full GCP resource ID.\n- **`imports.tf` Generation**: The transpiler detects the `import-id` and generates a corresponding OpenTofu `import` block in `hcl/imports.tf`.\n- **Automatic Lifecycle**: `imports.tf` is automatically deleted before each `transpile` run and only recreated if `import-id` tags are found.\n- **Execution**: Running `tofu plan` (or `apply`) will show these resources as \"to be imported\".\n\n#### Automatic Imports during Bootstrap\n\nThe `bootstrap` command automatically handles the import of core infrastructure resources (Folder, Project, and State Bucket) into your initial state so you don't have to manually link them.\n\n\u003e [!NOTE]\n\u003e Declarative imports require **OpenTofu** or **Terraform 1.5.0+**. For older versions, traditional CLI `tofu import` must be used.\n\n### Mode Switching \u0026 State Migration (`migrate`)\nSeamlessly move your project between development (`local`) and production (`cloud`) modes.\n\n```bash\ncfg2hcl migrate \u003cINPUT\u003e --mode \u003cMODE\u003e\n```\n\n**Parameters:**\n- `\u003cINPUT\u003e`: Name of the input YAML file.\n- `--mode, -m \u003cMODE\u003e`: Target mode (`local` or `cloud`).\n\n**Under the Hood:**\n- **Update YAML**: Modifies the `deployment-mode` anchor in the source YAML file.\n- **Regenerate**: Runs `transpile` to update the backend configuration (Local vs GCS) and provider authentication (ADC vs Impersonation).\n- **Migrate State**: Executes `tofu init -migrate-state` to safely move your terraform state to the new backend.\n\n### Infrastructure Discovery\n\n`cfg2hcl` provides two discovery commands to generate YAML configurations from existing infrastructure.\n\n#### Discover from Terraform State (`discover-from-state`)\nRead an existing Terraform/OpenTofu state and generate a corresponding YAML configuration.\n\n```bash\ncfg2hcl discover-from-state --output discovered.yaml\n```\n\n**Parameters:**\n- `--state-json \u003cFILE\u003e`: Path to Terraform state JSON file (optional). If omitted, runs `tofu show -json`.\n- `--output, -o \u003cFILE\u003e`: Path to output YAML file (default: `discovered.yaml`).\n- `--add-import-id`: Add `import-id` tag to every resource for declarative imports.\n- `--add-import-id-as-comment`: Add `import-id` as a comment to every resource.\n- `--discovery-config \u003cFILE\u003e`: Path to discovery configuration YAML file (default: `presets/discovery-config.yaml`).\n\n**Under the Hood:**\n- Reads the current state (either from a file or by running `tofu show -json`).\n- Reverse-engineers the resources to match the `cfg2hcl` YAML structure.\n- **Configurable Filtering**: respects `presets/discovery-config.yaml` to include/exclude specific resources and attributes.\n  - Resource types can be globally enabled/disabled (`import: true/false`).\n  - Specific attributes can be filtered via `exclude` and `include` lists per resource.\n- **Schema Validation**: Automatically validates discovered data against the Terraform Provider Schema, dropping read-only or computed fields that would cause HCL generation errors.\n- **IAM Heuristics**: Intelligently maps complex IAM resources (like `google_storage_bucket_iam_member`) to simplified, project-nested YAML structures.\n\n#### Discover from GCP Organization (`discover-from-organization`)\nDiscover infrastructure directly from a GCP Organization using the Cloud Asset API and generate a YAML configuration.\n\n```bash\ncfg2hcl discover-from-organization --customer-organization-id \"123456789012\" --output discovered.yaml\n```\n\n**Parameters:**\n- `--customer-organization-id \u003cID\u003e`: Numeric GCP Organization ID (required).\n- `--output, -o \u003cFILE\u003e`: Path to output YAML file (default: `discovered.yaml`).\n- `--add-import-id`: Add `import-id` tag to every resource for declarative imports.\n- `--add-import-id-as-comment`: Add `import-id` as a comment to every resource.\n- `--discovery-config \u003cFILE\u003e`: Path to discovery configuration YAML file (default: `presets/discovery-config.yaml`).\n\n**Under the Hood:**\n- Uses Google Cloud Asset API to enumerate all resources in the organization.\n- Requires appropriate IAM permissions (`cloudasset.assets.searchAllResources`).\n- Applies the same filtering and validation as `discover-from-state`.\n- Useful for discovering infrastructure that isn't managed by Terraform/OpenTofu yet.\n\n### Update Schemas (`update-schema`)\nRefresh local provider schemas to get the latest resource definitions.\n\n```bash\ncfg2hcl update-schema --providers google,google-beta\n```\n\n**Parameters:**\n- `--providers, -p \u003cLIST\u003e`: Comma-separated list of providers to update.\n- `--version, -v \u003cVERSION\u003e`: Provider version to fetch (default: from config).\n- `--tf-tool, -t \u003cTOOL\u003e`: Terraform/OpenTofu binary to use.\n\n**Under the Hood:**\n- runs `tofu init` in a temporary directory.\n- runs `tofu providers schema -json` to export the latest definitions.\n- Updates the JSON files in `schemas/`.\n\n### Self-update (`self-update`)\nCheck for and install a new release from GitHub. After a successful install, the tool downloads the release README and prints its full path, then opens it unless you pass the options below.\n\n```bash\ncfg2hcl self-update [options]\n```\n\n**Parameters:**\n- `--no-download-readme`: Do not download README.md after installing.\n- `--no-open-readme`: Download README and print its path, but do not open it (only applies if download runs).\n\n**Under the Hood:**\n- Fetches the latest release from the GitHub API, compares versions, and runs the cargo-dist installer script when a newer version is available. On success, optionally downloads `README.md` from the repo and prints its path (e.g. `README: /Users/you/Downloads/cfg2hcl-0.4.9-README.md`).\n\n## Day 0 Onboarding Playbook\n\nThis section outlines the step-by-step process for onboarding a new Google Cloud Organization.\n\n### Phase 1: Preparation\n\n#### Prerequisites\nEnsure the executing user has:\n- **Superadmin** access to the Google Workspace / Cloud Identity.\n- **Organization Administrator** role on the GCP Organization.\n- **Billing Account Administrator** on the target billing account (must be granted in the Reseller Console).\n\n#### Workspace Setup\n1. Authenticate with Google Cloud:\n   ```bash\n   gcloud auth application-default login\n   ```\n2. Initialize the tool configuration and folder structure:\n   ```bash\n   cfg2hcl init \\\n     --customer-id \"C01234567\" \\\n     --customer-shortname \"example-org\" \\\n     --billing-account-infra \"A12345-B67890-C12345\" \\\n     --customer-domain \"example.com\" \\\n     --customer-organization-id \"123456789012\" \\\n     --iac-user \"admin@example.com\"\n   ```\n\n### Phase 2: Fundamental Infrastructure\n\n#### 1. Bootstrap Core Resources\nThe `bootstrap` command automates the entire process: creating the infrastructure folder, project, bucket, linking billing, enabling foundation APIs (fixing the \"chicken-and-egg\" problem), and initializing the state.\n\n```bash\ncfg2hcl bootstrap yaml/C01234567.yaml\n```\n\n**What this does:**\n- Creates Folder, Project, Bucket, Service Account.\n- Enables Service Usage, IAM, and other core APIs.\n- Assigns `Folder Admin` to the user executing the bootstrap (if missing).\n- Automatically runs `transpile`, `init`, and `import` to bring resources under Terraform management.\n\n#### 2. (Optional) Customize \u0026 Transpile\n*Only needed if you modify the generated YAML configuration after bootstrap.*\n\nModify `yaml/C01234567.yaml` as needed, then manually generate the HCL:\n```bash\ncfg2hcl transpile C01234567.yaml\n```\n\n#### 3. (Optional) Configure Identity\n*Only needed if the default identity setup from bootstrap was insufficient.*\n\nIf customization was done, re-run initialization:\n```bash\ncd hcl\ntofu init\ntofu apply\n```\n\n\n\n### Phase 3: Identity \u0026 Access Rollout\n\n#### 1. Apply Management Infrastructure\nRun the first Tofu apply. This creates the **Identity Groups**, attaches the necessary **IAM roles** (including `Token Creator`), and finalizes the management project.\n\n```bash\ncd hcl/\ntofu plan\ntofu apply\n```\n\n### Phase 4: Cloud Migration\n\n#### 1. Perform State Migration\nToggle to `cloud` mode and move state to the GCS bucket:\n```bash\ncfg2hcl migrate C01234567.yaml --mode cloud\n```\nThe tool automatically updates the YAML, switches to **Service Account Impersonation**, and runs `tofu init -migrate-state`.\n\n#### 2. Verification\nIn `cloud` mode, verify that you can plan/apply using the restricted service account identity:\n```bash\ntofu plan\n```\n\n#### Template Variables Reference\n\nWhen you run `init`, the following variables are generated in the template:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `infra-folder-name` | `Infrastructure` | Display name for the top-level folder. Leave `\"\"` to create the project in the root. |\n| `infra-project-name` | `\"\"` | The unique ID for the management (IaC) project. |\n| `infra-bucket-name` | `\"\"` | The name of the GCS bucket for Terraform state. |\n| `customer-id` | (from CLI) | The Workspace Organization ID (e.g., `C01234567...`). |\n| `customer-organization-id` | `\"123456789012\"` | The numeric Google Cloud Organization ID. **Note:** Always use quotes, otherwise YAML interprets this as a number. |\n| `customer-domain` | `\"\"` | The customer's primary domain (e.g., `example.com`). |\n| `customer-longname` | `\"\"` | The full legal name of the customer entity. |\n| `customer-shortname` | `\"\"` | A unique slug or shortname for the customer. |\n| `svc-iac-account` | `svc-iac-001` | The name/ID of the primary IaC Service Account. |\n| `svc-iac-users-group` | `svc-iac-users` | The Cloud Identity group for IaC administrators. |\n| `billing-account-infra` | `\"\"` | The Billing Account ID (e.g., `A12345-B67890-C12345`). |\n| `deployment-engine` | `tofu` | The IaC tool: `tofu` or `terraform`. |\n| `deployment-mode` | `local` | `local` for Day 0 (User ADC); `cloud` for Day 1+ (Impersonation). |\n| `default-region` | `europe-west3` | Default region for regional resources. |\n| `default-zone` | `europe-west3-a` | Default zone for zonal resources. |\n\n### 3. Transpile\nConvert a YAML file to HCL. Run this from within the customer repository directory.\n```bash\ncfg2hcl transpile my-infra.yaml\n```\n- Input is read from `yaml_dir` (e.g., `./yaml/my-infra.yaml`).\n- Output is written directly to the `hcl_dir` defined in your config.\n- **Run from anywhere**: All paths are resolved relative to the configuration file's directory.\n- **Automatic Schema Sync**: The tool will automatically fetch missing provider schemas via `tofu/terraform` during transpilation.\n\n## YAML Configuration\n\nThe input YAML file is the source of truth for your infrastructure.\n\n### Terraform \u0026 Backend\nThe `terraform` block is mandatory and used primarily for backend configuration.\n\n```yaml\nterraform:\n  backend:\n    gcs:\n      bucket: \"my-infra-bucket\"\n      prefix: \"project-a\"\n```\n\n### Providers\nDefine one or more provider instances.\n\n```yaml\nproviders:\n  google:\n    region: \"europe-west3\"\n    zone: \"europe-west3-a\"\n  google: # Support for multiple aliased providers\n    - alias: \"secondary\"\n      region: \"us-central1\"\n```\n\n### Variables\nDeclare variables in a `variables` block. They are automatically merged to the root context and can be used with YAML anchors.\n\n```yaml\nvariables:\n  customer-id: \u0026customer-id \"C34projectroot\"\n  region: \u0026region \"europe-west3\"\n\ngoogle_project:\n  my-project:\n    project_id: *customer-id\n```\n- Variables are declared as `string` types in `_variables.tf`.\n- Values are written to `.tfvars`.\n\n### 3. Update Schemas\nRefresh provider schemas manually.\n```bash\ncfg2hcl update-schema --providers google,google-beta\n```\n\n## Configuration (config.toml)\n\nThe tool reads its settings from `config.toml`. Default values are:\n\n| Key | Default | Description |\n|-----|---------|-------------|\n| `yaml_dir` | `\"yaml\"` | Source directory for YAML files |\n| `hcl_dir` | `\"hcl\"` | Target directory for generated HCL |\n| `schema_dir` | `\"schemas\"` | Directory where provider schemas are cached |\n| `include_dirs` | `[\".\", \"yaml\"]` | Search paths for `!include` files |\n| `tf_tool` | `\"tofu\"` | The binary used to fetch schemas |\n| `google_providers` | `[\"google\", \"google-beta\"]` | List of Google providers |\n| `provider_version` | `\"7.12.0\"` | Provider version to use |\n| `auto_explode` | `[\"google_project_service\", \".*_iam_member\"]` | Resources that use compact explosion |\n| `validation_level` | `\"warn\"` | Validation level for mandatory parameters |\n\n## Schema Validation\n\nThe tool automatically checks your YAML against the provider schemas to ensure all mandatory parameters and blocks are present.\n\n- **Attributes**: Checks for `required` fields (e.g., `project_id`).\n- **Blocks**: Checks for mandatory blocks with `min_items \u003e 0` (e.g., `boot_disk` for a VM).\n\nYou can control the strictness via CLI `--validation` or `config.toml`.\n\n## YAML Features\n\n### Custom YAML Tags\nEnhance your configuration with dynamic logic:\n- **`!include \u003cfile\u003e`**: Recursively include other YAML snippets.\n- **`!format [template, arg1, arg2]`**: Dynamic string formatting using placeholders (`{}`).\n  ```yaml\n  member: !format\n    - \"serviceAccount:svc-iac-001@{}.iam.gserviceaccount.com\"\n    - *infra-project-name\n  ```\n- **`!join [arg1, arg2, ...]`**: Concatenate multiple values into a single string.\n\n### Conditional Folding\nSetting a folder's `display_name` to an empty string (`\"\"`) will skip the `google_folder` resource and \"implode\" its contents into the parent context. This is useful for conditionally creating folders based on variables.\n\n### Compact Explosion (CEX)\nResources named with a `CEX_` prefix (or listed in `auto_explode`) support compact definition styles:\n- **IAM**: Define many roles for one member in a simple block.\n- **Services**: Enable lists of GCP services in one block.\n\n## Core Principles\n\nThe tool follows a central design philosophy based on **Hierarchy Context**, **Attribute Inheritance**, and **Strict Validation**.\n\n### 1. Hierarchy Context \u0026 Nesting\nResources are defined within the context of their parent in the organization hierarchy:\n- **Project Context**: Resources that require a project (e.g., Buckets, VMs, Networks) are usually nested directly within a `google_project` definition.\n- **Folder Context**: Resources belonging to a folder (e.g., Folder IAM members) are usually nested within a `google_folder` block.\n- **Organization Context**: Organization-wide resources (e.g., Group memberships, Org IAM) are defined at the root level of the YAML.\n- **Explicit Placement**: Any resource can be defined outside its logical hierarchy container if the identifying parameter (e.g., `project_id`, `folder`) is provided explicitly.\n\n### 2. Attribute Inheritance (Narrowest Context)\nNested resources automatically inherit identity attributes from their surrounding context if not explicitly defined:\n- **Automatic Matching**: The tool identifies which identifier a resource needs based on its schema (e.g., `project_id`, `project`, `folder_id`, `org_id`).\n- **Inheritance**:\n    - A resource inside a Project context inherits the Project ID.\n    - A resource inside a Folder context inherits the Folder ID.\n- **Narrowest First**: If a resource is defined in a scope where multiple contexts apply (e.g., inside a Project which is inside a Folder), it inherits from the **most specific (narrowest)** context available.\n- **Explicit Override**: Explicitly provided attributes in the YAML always take precedence over inherited context values.\n\n### 3. Context Validation \u0026 Typo Detection\nTo ensure configuration correctness, nested blocks are strictly validated:\n- **Attribute vs. Resource**: Every key within a `Project` or `Folder` block must be either:\n    - A valid native attribute/block of the parent resource (e.g., `name` for a project).\n    - A valid resource type from the cloud provider schema.\n- **Error Detection**: Any key that is neither a known attribute nor a known resource type is treated as a typo and triggers a **Warning**.\n- **Missing Context**: Resources that require a project or folder identifier but are defined outside such a context (without an explicit identifier provided) will trigger a **Warning**.\n\n### 4. Flexible Placement\nWhile the tool encourages a clean hierarchy, it allows placing cross-context resources (like `google_cloud_identity_group`) inside a Project block for configuration convenience (e.g., defining project-relevant groups near the project). The transpiler will process these correctly, ignoring the project context where it doesn't apply to the resource's schema.\n\n## Handling Resource Renames (State Migration)\n\nIf you rename a resource in your YAML, the transpiler will generate a new HCL label. OpenTofu will see this as a \"delete and recreate\" action. To avoid downtime, you can use the built-in migration suite:\n\n1.  **Iterate Locally**: Use `tofu plan -out=plan.binary` and `tofu show -json plan.binary \u003e plan.json` to identify changes.\n2.  **Map Moves**: Use `cfg2hcl scan-plan plan.json` to generate a `mapping.yaml`.\n3.  **Apply Renames**: Run `cfg2hcl generate-migration mapping.yaml` and execute the resulting script to perform the `mv` commands safely.\n\nFor switching between local and cloud backends, always use the high-level `cfg2hcl migrate` command.\n\n### Scan Plan (`scan-plan`)\nAnalyze a Terraform/OpenTofu plan JSON file to identify resource renames and generate a mapping file.\n\n```bash\ncfg2hcl scan-plan plan.json --output mapping.yaml\n```\n\n**Parameters:**\n- `\u003cplan_json\u003e`: Path to the plan JSON file (required).\n- `--output \u003cFILE\u003e`: Path to output mapping YAML file (default: `mapping.yaml`).\n\n**Under the Hood:**\n- Parses the plan JSON to identify resources that are being destroyed and recreated with new addresses.\n- Generates a mapping file that correlates old and new resource addresses.\n- The mapping file can be used with `generate-migration` to create state move commands.\n\n### Generate Migration (`generate-migration`)\nGenerate a shell script with `tofu state mv` commands from a mapping YAML file.\n\n```bash\ncfg2hcl generate-migration mapping.yaml --output migrate.sh\n```\n\n**Parameters:**\n- `\u003cmapping\u003e`: Path to the mapping YAML file (default: `mapping.yaml`).\n- `--output \u003cFILE\u003e`: Path to output shell script (default: `migrate.sh`).\n\n**Under the Hood:**\n- Reads the mapping file generated by `scan-plan`.\n- Generates a shell script with `tofu state mv` commands to safely rename resources in the state.\n- The script can be reviewed and executed manually to perform the state migration.\n\n## Day 0: Migration Playbook\n\nThis section outlines the general process for migrating existing infrastructure into `cfg2hcl` management.\n\n### 1. State Discovery\nBegin by capturing the current infrastructure state. If you have an existing Terraform/OpenTofu project, generate a JSON state file and use the discovery tool:\n```bash\ntofu show -json \u003e state.json\ncfg2hcl discover-from-state --state-json state.json --output yaml/migration-discovery.yaml\n```\n\nAlternatively, if you want to discover infrastructure directly from GCP without Terraform state:\n```bash\ncfg2hcl discover-from-organization --customer-organization-id \"123456789012\" --output yaml/migration-discovery.yaml\n```\n\n### 2. Hierarchical Refinement\nThe discovery tool produces a relatively flat YAML structure. Organize this into the `cfg2hcl` hierarchical format:\n- Move projects into their respective folders.\n- Nest resources (Buckets, Networks, etc.) inside their projects to leverage **Attribute Inheritance**.\n- Remove redundant attributes (like `project_id`) that are now inherited from the context.\n\n### 3. Resource Optimization\nConvert standard resource definitions into optimized `cfg2hcl` patterns:\n- **Services**: Group `google_project_service` resources into a single `project_service` list.\n- **IAM**: Combine individual IAM members into compact `project_iam_member` or `folder_iam_member` blocks.\n- **Formatting**: Ensure attributes with sub-structures (e.g., `project_service` with `disable_on_destroy`) are correctly indented.\n\n### 4. Validation \u0026 Reconciliation\nGenerate the HCL and compare it with the live environment:\n1. Run `cfg2hcl transpile migration-discovery.yaml`.\n2. Run `tofu plan` in the `hcl/` directory.\n3. **Reconcile**: If the plan shows \"replace\" instead of \"no changes\", it means the HCL labels or resource IDs don't match.\n   - Use `import-id` in the YAML to link existing resources.\n   - Or use `tofu state mv` to align the existing state with the new HCL labels.\n\n### 5. Transition to Management\nOnce `tofu plan` shows no changes (or only intended updates), the migration is complete. You can now manage the infrastructure exclusively through the YAML configuration.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjirsch%2Frs-cfg2hcl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftjirsch%2Frs-cfg2hcl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftjirsch%2Frs-cfg2hcl/lists"}