{"id":18008241,"url":"https://github.com/drlau/akashi","last_synced_at":"2025-03-26T12:32:05.284Z","repository":{"id":39867134,"uuid":"286056369","full_name":"drlau/akashi","owner":"drlau","description":"Validate \"terraform plan\" changes against a customizable ruleset","archived":false,"fork":false,"pushed_at":"2024-10-29T00:42:35.000Z","size":115,"stargazers_count":29,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T19:12:24.954Z","etag":null,"topics":["go","golang","terraform"],"latest_commit_sha":null,"homepage":"","language":"Go","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/drlau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-08T14:15:52.000Z","updated_at":"2025-01-20T14:40:42.000Z","dependencies_parsed_at":"2024-06-19T05:16:30.443Z","dependency_job_id":"2246d205-0a5a-46d2-ab38-cd109f1a5734","html_url":"https://github.com/drlau/akashi","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drlau%2Fakashi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drlau%2Fakashi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drlau%2Fakashi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drlau%2Fakashi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drlau","download_url":"https://codeload.github.com/drlau/akashi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245654321,"owners_count":20650846,"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":["go","golang","terraform"],"created_at":"2024-10-30T01:17:59.366Z","updated_at":"2025-03-26T12:32:04.943Z","avatar_url":"https://github.com/drlau.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Akashi / 証\n\nAkashi is a Go tool that can be used to parse `terraform plan` outputs and validate the changes.\n\nStill a WIP project. Supports `terraform` v0.12 currently.\n\n- [x] Created and destroyed resources\n- [x] JSON Output\n- [x] stdout output\n- [x] Map / Array rules\n- [x] Updated resources\n- [ ] Index matching\n- [ ] Module matching\n- [ ] Multiple rule matching\n- [ ] Other validations(regex, int in range, etc)\n- [ ] Combining multiple rulesets\n- [ ] Customizable output\n\n## Why\n\nBy parsing the `terraform plan` result, you can validate changes shown in the `plan` output before actually applying. Also, it can be used to track unexpected changes during routine operations that may have occured from misconfiguration or infrastructure drift.\n\nFor example, say you had a `google_container_node_pool` with `autoscaling` configured, and due to some incident you had to modify the `autoscaling` configuration outside of `terraform`. Some time later, you update the `version` of your `google_container_node_pool` as a routine operation. Due to the declarative nature of `terraform`, the previous configuration of `autoscaling` would be applied and overwrite the modified configuration set during the incident. This might be unintentional and would not be caught from parsing the `terraform` configuration, but can be caught by validating the `terraform plan` output.\n\n## Installation\n\n```bash\ngo get -u github.com/drlau/akashi\n```\n\n## Usage\n\n```\nUsage:\n  akashi \u003ccompare | diff\u003e \u003cpath to ruleset\u003e [flags]\n```\n\nBy default, `akashi` will read a `terraform plan` output from `stdin`, so you should pipe the result of `terraform plan`:\n\n```bash\nterraform plan | akashi \u003ccompare | diff\u003e \u003cpath to ruleset\u003e\n```\n\nIf you produced a plan output with `terraform plan -out=\u003cfile\u003e`, `akashi` can parse it by specifying `--json`. Note that this file is encoded and needs to be decoded by `terraform` before `akashi` can parse it properly:\n\n```bash\nterraform state show -json \u003cfile\u003e | akashi \u003ccompare | diff\u003e \u003cpath to ruleset\u003e --json\n```\n\nIf the `terraform plan` output or the decoded json is in a file, you can read directly from the file by specifying the path with `-f`.\n\n## Ruleset schema\n\n**NOTE**: Ruleset schema is in the early stages and is subject to change in later versions.\n\nRulesets are written in YAML and have the following schema:\n\n```yaml\n# Rules to apply to created resources.\ncreatedResources:\n  # Set to true if you want all created resources to match a rule.\n  # Default is false.\n  strict: true\n\n  # Set to true if you want to validate the ruleset specifies names for\n  # created resources.\n  # Default is false.\n  requireName: true\n\n  # Default compare options to apply to all resources.\n  # If a resource specifies the same option, the resource's value will be used.\n  default:\n    # Set to true if you want every enforcedValue to be present in a resource's plan.\n    # If set to true, if an enforcedValue is missing, it will count as a failure.\n    # Default is false.\n    enforceAll: true\n\n    # Set to true if you want to ignore extra arguments in a resource's plan\n    # that don't match any enforcedValue or ignoredArg.\n    # If set to false, any extra arguments will count as a failure.\n    # Default is false.\n    ignoreExtraArgs: true\n\n    # Set to true if you want to ignore computed arguments in a resource's plan.\n    # Default is false.\n    ignoreComputed: true\n\n    # Set to true if you want every enforcedValue and ignoredArg to be present in a resource's plan.\n    # If set to true, if any enforcedValue or ignoredArg is missing, it will count as a failure.\n    # Default is false.\n    requireAll: true\n\n    # Set to true if you want to automatically fail before comparison\n    # if a matching resource is found.\n    # Default is false.\n    autoFail: true\n\n  # List of rules.\n  resources:\n    -\n      # Resource name to match on.\n      # At least one of \"name\" or \"type\" must be set.\n      # Default is empty.\n      name: resource-name\n\n      # Resource type to match on.\n      # At least one of \"name\" or \"type\" must be set.\n      # Default is empty.\n      type: resource-type\n\n      # The same compare options from \"default\" can be specified per resource.\n      # The resource level option will take priority over the option specified in \"default\"\n      # If omitted, the option specified in \"default\" is used.\n      # If not specified in \"default\", the value is false.\n      enforceAll: true\n      ignoreExtraArgs: true\n      ignoreComputed: true\n      requireAll: true\n      autoFail: true\n\n      # List of arguments to ignore.\n      # Default is empty.\n      ignored:\n        - ignored-arg-1\n        - ignored-arg-2\n\n      # List of arguments to enforce.\n      # Default is empty.\n      enforced:\n        stringEnforced:\n          value: string\n        intEnforced:\n          value: 1\n        boolEnforced:\n          value: true\n        mapEnforced:\n          value:\n            mapKey: mapValue\n        arrayEnforced:\n          value:\n          - array1\n          - array2\n        stringMatchAny:\n          matchAny:\n          - validValue1\n          - validValue2\n\n# Rules to apply to destroyed resources.\n# Has the exact same schema as createdResources.\ndestroyedResources:\n\n# Rules to apply to updated resources.\nupdatedResources:\n  # Set to true if you want all updated resources to match a rule.\n  # Default is false.\n  strict: true\n\n  # Set to true if you want to validate the ruleset specifies names for\n  # updated resources.\n  # Default is false.\n  requireName: true\n\n  # Default compare options to apply to all resources.\n  # If a resource specifies the same option, the resource's value will be used.\n  # All options for created and destroyed resources work here, but also has a few additional options that can be enabled\n  default:\n    # Set to true if you want to ignore all unchanged attributes\n    # Default is false.\n    ignoreNoOp: true\n\n  # List of rules.\n  resources:\n  -\n    # Similar to created and destroyed resources, matching can be done on a name and/or type of resource\n    name: resource-name\n    type: resource-type\n\n    # Every compare option can also be specified at resource level, overriding the top level default\n    ignoreNoOp: true\n\n    # Rules to enforce on the attributes before the planned changes\n    # Consists of ignored and enforced, with the same behaviour as created and destroyed resources\n    before:\n      # List of arguments to ignore.\n      # Default is empty.\n      ignored:\n        - ignored-arg-1\n        - ignored-arg-2\n\n      # List of arguments to enforce.\n      # Default is empty.\n      enforced:\n        stringEnforced:\n          value: string\n\n    # Rules to enforce on the attributes after the planned changes\n    # Same schema as before.\n    after:\n```\n\n### Example\n\nSay you provision `google_compute_instance` and you want to validate that all new instances are created in zone `us-central1-a`, and you don't care about any other argument. To validate that, you would create the following ruleset:\n\n```yaml\ncreatedResources:\n  default:\n    enforceAll: true\n    ignoreExtraArgs: true\n  resources:\n    - type: google_compute_instance\n      enforced:\n        zone:\n          value: us-central1-a\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrlau%2Fakashi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrlau%2Fakashi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrlau%2Fakashi/lists"}