Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cmd/match] add new match command #16

Merged
merged 1 commit into from
Oct 29, 2024

Conversation

ryan-ph
Copy link
Contributor

@ryan-ph ryan-ph commented Oct 28, 2024

This new command is similar to akashi diff, except it outputs resource paths without any extra metadata (i.e. emojis, explanations, etc.). Specifically, it will output any resource paths from the plan output which match the Akashi ruleset (or do not match if the --invert flag is provided).

As Akashi currently does not support specifying full addresses for modules, this will be useful in parsing full addresses to use in conjunction with the -target flag for resource targeting. The functionality is distinct enough from akashi diff, that it seems like it justifies creating a distinct command rather than refactoring and piggybacking on any existing commands.

Test Plan

Unit tests

Create a TF directory with the following resources:

resource "google_storage_bucket" "auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}

resource "google_storage_bucket" "nonexist-auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}

resource "google_storage_bucket" "exist-auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}

This should produce the following plan output:

$ terraform plan -no-color
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_storage_bucket.auto-expire will be created
  + resource "google_storage_bucket" "auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "my-proj"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # google_storage_bucket.exist-auto-expire will be created
  + resource "google_storage_bucket" "exist-auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "my-proj"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # google_storage_bucket.nonexist-auto-expire will be created
  + resource "google_storage_bucket" "nonexist-auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "my-proj"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Specify the following Akashi policy

createdResources:
  strict: true
  requireName: true
  default:
    enforceAll: true
    ignoreExtraArgs: true
  resources:
    - type: google_storage_bucket
      name: auto-expire
    - type: google_storage_bucket
      name: exist-auto-expire

updatedResources:
  strict: true
  requireName: true
  default:
    enforceAll: true
    ignoreExtraArgs: true
  resources:
    - type: google_storage_bucket
      name: nonexist-auto-expire

Running akashi match produces the following:

google_storage_bucket.auto-expire
google_storage_bucket.exist-auto-expire

$ ./akashi match /tmp/tf-test/akashi.yaml -f /tmp/tf-test/plan.state --invert
google_storage_bucket.nonexist-auto-expire

$ ./akashi match /tmp/tf-test/akashi.yaml -f /tmp/tf-test/plan.state -s ,
google_storage_bucket.auto-expire,google_storage_bucket.exist-auto-expire

This new command is similar to `akashi diff`, except it outputs resource
paths without any extra metadata (i.e. emojis, explanations, etc.).
Specifically, it will output any resource paths from the plan output
which match the Akashi ruleset (or do not match if the `--invert` flag
is provided).

As Akashi currently does not support specifying full addresses for
modules, this will be useful in parsing full addresses to use in
conjunction with the `-target` flag for resource targeting. The
functionality is distinct enough from `akashi diff`, that it seems like
it justifies creating a distinct command rather than refactoring and
piggybacking on any existing commands.

Test Plan
---------

Unit tests

Create a TF directory with the following resources:
```terraform
resource "google_storage_bucket" "auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}

resource "google_storage_bucket" "nonexist-auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}

resource "google_storage_bucket" "exist-auto-expire" {
  name          = "no-public-access-bucket"
  location      = "US"
  project       = "my-proj"
  force_destroy = true

  public_access_prevention = "enforced"
}
```

This should produce the following plan output:
```
$ terraform plan -no-color
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_storage_bucket.auto-expire will be created
  + resource "google_storage_bucket" "auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "kouzoh-p-ryanpham"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # google_storage_bucket.exist-auto-expire will be created
  + resource "google_storage_bucket" "exist-auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "kouzoh-p-ryanpham"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # google_storage_bucket.nonexist-auto-expire will be created
  + resource "google_storage_bucket" "nonexist-auto-expire" {
      + effective_labels            = (known after apply)
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "US"
      + name                        = "no-public-access-bucket"
      + project                     = "kouzoh-p-ryanpham"
      + project_number              = (known after apply)
      + public_access_prevention    = "enforced"
      + rpo                         = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + terraform_labels            = (known after apply)
      + uniform_bucket_level_access = (known after apply)
      + url                         = (known after apply)

      + soft_delete_policy (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

Plan: 3 to add, 0 to change, 0 to destroy.
```

Specify the following Akashi policy
```yaml
createdResources:
  strict: true
  requireName: true
  default:
    enforceAll: true
    ignoreExtraArgs: true
  resources:
    - type: google_storage_bucket
      name: auto-expire
    - type: google_storage_bucket
      name: exist-auto-expire

updatedResources:
  strict: true
  requireName: true
  default:
    enforceAll: true
    ignoreExtraArgs: true
  resources:
    - type: google_storage_bucket
      name: nonexist-auto-expire
```

Running `akashi match` produces the following:
```
google_storage_bucket.auto-expire
google_storage_bucket.exist-auto-expire

$ ./akashi match /tmp/tf-test/akashi.yaml -f /tmp/tf-test/plan.state --invert
google_storage_bucket.nonexist-auto-expire

$ ./akashi match /tmp/tf-test/akashi.yaml -f /tmp/tf-test/plan.state -s ,
google_storage_bucket.auto-expire,google_storage_bucket.exist-auto-expire
```
@ryan-ph ryan-ph force-pushed the ryan-ph/output-matching-resources branch from 0fbd16f to 325d22b Compare October 28, 2024 19:03
Copy link
Owner

@drlau drlau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks for your contribution!

@drlau drlau merged commit 1593d5c into drlau:master Oct 29, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants