{"id":17276750,"url":"https://github.com/isometry/terraform-provider-deepmerge","last_synced_at":"2026-04-19T01:03:39.741Z","repository":{"id":233341045,"uuid":"787063447","full_name":"isometry/terraform-provider-deepmerge","owner":"isometry","description":"Deepmerge functions for Terraform 1.8+","archived":false,"fork":false,"pushed_at":"2024-04-22T11:28:13.000Z","size":84,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-22T12:46:28.662Z","etag":null,"topics":["deepmerge","terraform-functions","terraform-provider"],"latest_commit_sha":null,"homepage":"https://registry.terraform.io/providers/isometry/deepmerge/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/isometry.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-15T20:22:41.000Z","updated_at":"2024-04-23T12:50:52.387Z","dependencies_parsed_at":"2024-04-22T12:43:32.235Z","dependency_job_id":null,"html_url":"https://github.com/isometry/terraform-provider-deepmerge","commit_stats":null,"previous_names":["isometry/terraform-provider-deepmerge"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isometry%2Fterraform-provider-deepmerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isometry%2Fterraform-provider-deepmerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isometry%2Fterraform-provider-deepmerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isometry%2Fterraform-provider-deepmerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/isometry","download_url":"https://codeload.github.com/isometry/terraform-provider-deepmerge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242179426,"owners_count":20084947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["deepmerge","terraform-functions","terraform-provider"],"created_at":"2024-10-15T09:01:04.038Z","updated_at":"2026-04-19T01:03:39.728Z","avatar_url":"https://github.com/isometry.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![CodeQL](https://github.com/isometry/terraform-provider-deepmerge/actions/workflows/codeql.yml/badge.svg)](https://github.com/isometry/terraform-provider-deepmerge/actions/workflows/codeql.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/isometry/terraform-provider-deepmerge)](https://goreportcard.com/report/github.com/isometry/terraform-provider-deepmerge)\n[![Terraform Registry Version](https://img.shields.io/badge/dynamic/json?color=blue\u0026label=registry\u0026query=$.version\u0026url=https://registry.terraform.io/v1/providers/isometry/deepmerge)](https://registry.terraform.io/providers/isometry/deepmerge/latest)\n![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/isometry/terraform-provider-deepmerge/total)\n\n# Terraform Provider Deepmerge\n\nDeep merge functionality for complex Terraform configurations, supporting recursive merging of maps and objects with fine-grained control over merge behavior.\n\n## Why Use This Provider?\n\nTerraform's built-in `merge()` function only performs shallow merging, which means nested structures are completely replaced rather than intelligently combined. This provider enables:\n\n- **Recursive merging** of deeply nested structures\n- **Flexible merge strategies** with multiple modes of operation\n- **List concatenation** instead of replacement\n- **Null value handling** for optional configurations\n- **Type-safe merging** that preserves your data structure integrity\n\n### Common Use Cases\n\n- **Environment-specific configurations**: Merge base configurations with environment overrides\n- **Module defaults**: Provide sensible defaults that users can partially override\n- **Multi-team configurations**: Combine configurations from different teams or sources\n- **Dynamic resource generation**: Build complex resources from modular configuration fragments\n\n## Requirements\n\n- [Terraform](https://developer.hashicorp.com/terraform/downloads) \u003e= 1.8\n- [OpenTofu](https://opentofu.org/docs/intro/install/) \u003e= 1.7\n\n## Installation\n\n```hcl\nterraform {\n  required_providers {\n    deepmerge = {\n      source  = \"isometry/deepmerge\"\n      version = \"~\u003e 1.0\"\n    }\n  }\n}\n\nprovider \"deepmerge\" {}\n```\n\n## Merge Modes\n\nA distinctive feature of `mergo` is its use of string arguments to control merge strategies. Simply append one or more control strings after your maps to change how the merge operates:\n\n| Mode                                 | Description                                | Use Case                              |\n| ------------------------------------ | ------------------------------------------ | ------------------------------------- |\n| `\"override\"` / `\"replace\"` (default) | Later values replace earlier ones          | Standard configuration layering       |\n| `\"no_override\"`                      | Earlier values are preserved               | Setting immutable defaults            |\n| `\"no_null_override\"`                 | Null values don't replace existing values  | Optional configuration fields         |\n| `\"append\"` / `\"append_lists\"`        | Lists are concatenated instead of replaced | Accumulating features, rules, or tags |\n| `\"union\"` / `\"union_lists\"`          | Lists are merged as sets (unique elements) | Deduplicating tags, IPs, or identifiers |\n\n### Examples by Mode\n\n#### Default Behavior (Override)\n\n```hcl\nlocals {\n  config1 = { a = 1, b = { x = 10, y = 20 } }\n  config2 = { a = 2, b = { y = 30, z = 40 } }\n\n  result = provider::deepmerge::mergo(local.config1, local.config2)\n  # Result: { a = 2, b = { x = 10, y = 30, z = 40 } }\n}\n```\n\n#### No Override Mode\n\n```hcl\nlocals {\n  defaults    = { timeout = 30, retries = 3, debug = false }\n  user_config = { timeout = 60, debug = true, custom = \"value\" }\n\n  result = provider::deepmerge::mergo(local.defaults, local.user_config, \"no_override\")\n  # Result: { timeout = 30, retries = 3, debug = false, custom = \"value\" }\n  # Note: defaults are preserved, only new keys from user_config are added\n}\n```\n\n#### No Null Override Mode\n\n```hcl\nlocals {\n  base      = { name = \"service\", port = 8080, optional_setting = \"enabled\" }\n  overrides = { port = 9090, optional_setting = null }\n\n  result = provider::deepmerge::mergo(local.base, local.overrides, \"no_null_override\")\n  # Result: { name = \"service\", port = 9090, optional_setting = \"enabled\" }\n  # Note: null doesn't override the existing value\n}\n```\n\n#### Append Mode\n\n```hcl\nlocals {\n  base_rules = {\n    firewall = {\n      allowed_ports = [22, 80, 443]\n      denied_ips    = [\"192.168.1.100\"]\n    }\n  }\n\n  additional_rules = {\n    firewall = {\n      allowed_ports = [8080, 9090]\n      denied_ips    = [\"192.168.1.101\", \"192.168.1.102\"]\n    }\n  }\n\n  result = provider::deepmerge::mergo(local.base_rules, local.additional_rules, \"append\")\n  # Result: {\n  #   firewall = {\n  #     allowed_ports = [22, 80, 443, 8080, 9090]\n  #     denied_ips    = [\"192.168.1.100\", \"192.168.1.101\", \"192.168.1.102\"]\n  #   }\n  # }\n}\n```\n\n#### Union Lists Mode\n\n```hcl\nlocals {\n  base_tags = {\n    security = {\n      allowed_ports = [22, 80, 443]\n      tags = [\"security\", \"prod\", \"critical\"]\n    }\n  }\n\n  additional_tags = {\n    security = {\n      allowed_ports = [8080, 80, 9090]\n      tags = [\"monitoring\", \"prod\", \"audit\"]\n    }\n  }\n\n  result = provider::deepmerge::mergo(local.base_tags, local.additional_tags, \"union_lists\")\n  # Result: {\n  #   security = {\n  #     allowed_ports = [22, 80, 443, 8080, 9090]  # Unique elements only\n  #     tags = [\"security\", \"prod\", \"critical\", \"monitoring\", \"audit\"]  # Duplicates removed\n  #   }\n  # }\n}\n```\n\n## Practical Examples\n\nSee [docs/functions/mergo.md](docs/functions/mergo.md) for detailed examples.\n\n## Comparison with Terraform's `merge()` Function\n\n| Feature          | Terraform `merge()`        | `deepmerge::mergo()`            |\n| ---------------- | -------------------------- | ------------------------------- |\n| Shallow merge    | ✅                         | ✅                              |\n| Deep merge       | ❌                         | ✅                              |\n| List handling    | Replace only               | Replace or append               |\n| Null handling    | Overwrites                 | Configurable                    |\n| Merge strategies | None                       | Multiple modes                  |\n| Performance      | Faster for flat structures | Optimized for nested structures |\n\n### When to Use Each\n\n**Use Terraform's `merge()` when:**\n\n- Working with flat maps\n- Performance is critical for large, flat structures\n- You want complete replacement of nested values\n\n**Use `deepmerge::mergo()` when:**\n\n- Working with nested configurations\n- You need fine-grained control over merge behavior\n- Building layered configurations\n- Handling optional/nullable values\n\n## Troubleshooting\n\n### Common Issues\n\n- **Unexpected list behavior**: By default, lists are replaced. Use `\"append\"` mode to concatenate them.\n\n- **Null values overriding**: Use `\"no_null_override\"` mode to prevent nulls from replacing existing values.\n\n- **Large data structures**: For *very* large nested structures, consider breaking them into smaller, manageable pieces.\n\n## Documentation\n\n- [Provider Documentation](docs/index.md)\n- [Function Reference](docs/functions/mergo.md)\n\n## Developing the Provider\n\nIf you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (see [Requirements](#requirements) above).\n\nTo compile the provider, run `go install`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory.\n\nTo generate or update documentation, run `go generate`.\n\nIn order to run the full suite of Acceptance tests, run `make testacc`.\n\n_Note:_ Acceptance tests create real resources, and often cost money to run.\n\n```shell\nmake testacc\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis provider is distributed under the [Mozilla Public License 2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisometry%2Fterraform-provider-deepmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisometry%2Fterraform-provider-deepmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisometry%2Fterraform-provider-deepmerge/lists"}