From ed100ee0d20d1a7058d82652562bbf5a95f1b64b Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 13 Jan 2024 12:48:52 -0500 Subject: [PATCH 1/5] correct input reading logic This addresses https://github.com/dineshba/tf-summarize/issues/20 and ensures input is read from the plan file -- and not via STDIN -- if a plan file argument is provided. This also seeks to improve some of the error messaging to be a bit more clear. --- main.go | 2 +- reader/reader.go | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index 5fc1815..91223be 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,7 @@ func main() { err := validateFlags(*tree, *separateTree, *drawable, *md, args) logIfErrorAndExit("invalid input flags: %s\n", err, flag.Usage) - newReader, err := reader.CreateReader(os.Stdin, args) + newReader, err := reader.CreateReader(args) logIfErrorAndExit("error creating input reader: %s\n", err, flag.Usage) input, err := newReader.Read() diff --git a/reader/reader.go b/reader/reader.go index 5caead1..4319fa3 100644 --- a/reader/reader.go +++ b/reader/reader.go @@ -2,9 +2,10 @@ package reader import ( "bufio" + "errors" "fmt" "io" - "os" + "strings" ) type Reader interface { @@ -22,19 +23,22 @@ func readFile(f io.Reader) ([]byte, error) { input = append(input, line...) } if err != io.EOF { - return nil, fmt.Errorf("error reading file: %s", err.Error()) + return nil, fmt.Errorf("error reading input: %s", err.Error()) + } + if len(input) == 0 { + return nil, errors.New("no input data; expected input via a non-empty file or via STDIN") } return input, nil } -func CreateReader(stdin *os.File, args []string) (Reader, error) { - stat, _ := stdin.Stat() - if (stat.Mode() & os.ModeCharDevice) == 0 { - return NewStdinReader(), nil +func CreateReader(args []string) (Reader, error) { + if len(args) > 1 { + return nil, fmt.Errorf("expected input via a single filename argument or via STDIN; received multiple arguments: %s", strings.Join(args, ", ")) } - if len(args) < 1 { - return nil, fmt.Errorf("should have either stdin input through pipe or first argument should be file") + + if len(args) == 1 { + return NewFileReader(args[0]), nil } - fileName := args[0] - return NewFileReader(fileName), nil + + return NewStdinReader(), nil } From f99306aa4bc016cc778c6c284e17aa09cf07ca1d Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Sat, 13 Jan 2024 13:39:22 -0500 Subject: [PATCH 2/5] demo issue 20 fix via GH Actions Ideally, tf-summarize would feature a suite of automated tests verifying its functionality. In absenece of that, this demos the issue #20 fix via GH Actions. --- .github/workflows/build.yml | 95 +++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index deeca95..eb6994d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,34 +2,89 @@ name: Build on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] jobs: - build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: -exclude=G204 ./... + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.21" + + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + + - name: Test + run: go test -v ./... + + - name: Build + run: go build + + demo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.21" + + - name: Build + run: | + go build -o example/tf-summarize + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_wrapper: false + + - name: Print tf-summarize version and help + run: | + ./tf-summarize -v + ./tf-summarize -h + working-directory: ./example + + - name: Terraform Init + run: terraform init + working-directory: ./example + + - name: Terraform Plan + run: | + terraform plan -out=tfplan -refresh=false # -refresh=false is only for demo workflow + terraform show -json tfplan > tfplan.json + working-directory: ./example - - name: Run Gosec Security Scanner - uses: securego/gosec@master - with: - args: -exclude=G204 ./... + - name: summary in table format + run: terraform show -json tfplan | ./tf-summarize + working-directory: ./example - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.21' + - name: summary in table format with plan JSON file passed + run: | + ./tf-summarize tfplan.json + working-directory: ./example - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - version: latest + - name: summary in tree format + run: terraform show -json tfplan | ./tf-summarize -tree + working-directory: ./example - - name: Test - run: go test -v ./... + - name: summary in separate tree format + run: terraform show -json tfplan | ./tf-summarize -separate-tree + working-directory: ./example - - name: Build - run: go build + - name: summary in draw visual tree format + run: terraform show -json tfplan | ./tf-summarize -tree -draw + working-directory: ./example From 40f8d1bd71529351c5b051a032fc5f3d646f0960 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Mon, 15 Jan 2024 07:44:11 -0500 Subject: [PATCH 3/5] use consistent TF version when invoking TF - ensure the generation of the `example` directory data is done in a consistent, reproducible fashion - ensure GH Actions uses the same version of TF expected by the `example` directory - add plan and plan JSON files to source control, for testing purposes --- .github/workflows/demo.yml | 97 +++++++++++++++++++------------------ Makefile | 22 ++++++++- example/.terraform-version | 1 + example/tfplan | Bin 0 -> 5306 bytes example/tfplan.json | 1 + 5 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 example/.terraform-version create mode 100644 example/tfplan create mode 100644 example/tfplan.json diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index 065aa68..bb89155 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -11,49 +11,54 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_wrapper: false - - - name: Install terraform-plan-summary - run: | - REPO="dineshba/tf-summarize" - curl -LO https://github.com/$REPO/releases/latest/download/tf-summarize_linux_amd64.zip - tmpDir=$(mktemp -d -t tmp.XXXXXXXXXX) - mv tf-summarize_linux_amd64.zip $tmpDir - cd $tmpDir - unzip tf-summarize_linux_amd64.zip - chmod +x tf-summarize - echo $PWD >> $GITHUB_PATH - - - name: Print tf-summarize version and help - run: | - tf-summarize -v - tf-summarize -h - - - name: Terraform Init - run: terraform init - working-directory: ./example - - - name: Terraform Plan - run: terraform plan -out=tfplan -refresh=false # -refresh=false is only for demo workflow - working-directory: ./example - - - name: summary in table format - run: terraform show -json tfplan | tf-summarize - working-directory: ./example - - - name: summary in tree format - run: terraform show -json tfplan | tf-summarize -tree - working-directory: ./example - - - name: summary in separate tree format - run: terraform show -json tfplan | tf-summarize -separate-tree - working-directory: ./example - - - name: summary in draw visual tree format - run: terraform show -json tfplan | tf-summarize -tree -draw - working-directory: ./example + - uses: actions/checkout@v3 + + - name: Set Terraform version + id: set-terraform-version + run: echo "terraform-version=$(cat example/.terraform-version)" >> $GITHUB_OUTPUT + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_wrapper: false + terraform_version: ${{ steps.set-terraform-version.outputs.terraform-version }} + + - name: Install terraform-plan-summary + run: | + REPO="dineshba/tf-summarize" + curl -LO https://github.com/$REPO/releases/latest/download/tf-summarize_linux_amd64.zip + tmpDir=$(mktemp -d -t tmp.XXXXXXXXXX) + mv tf-summarize_linux_amd64.zip $tmpDir + cd $tmpDir + unzip tf-summarize_linux_amd64.zip + chmod +x tf-summarize + echo $PWD >> $GITHUB_PATH + + - name: Print tf-summarize version and help + run: | + tf-summarize -v + tf-summarize -h + + - name: Terraform Init + run: terraform init + working-directory: ./example + + - name: Terraform Plan + run: terraform plan -out=tfplan -refresh=false # -refresh=false is only for demo workflow + working-directory: ./example + + - name: summary in table format + run: terraform show -json tfplan | tf-summarize + working-directory: ./example + + - name: summary in tree format + run: terraform show -json tfplan | tf-summarize -tree + working-directory: ./example + + - name: summary in separate tree format + run: terraform show -json tfplan | tf-summarize -separate-tree + working-directory: ./example + + - name: summary in draw visual tree format + run: terraform show -json tfplan | tf-summarize -tree -draw + working-directory: ./example diff --git a/Makefile b/Makefile index 440fb42..861ea7c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +TERRAFORM_VERSION:=$(shell cat example/.terraform-version) + .PHONY: help help: ## prints help (only for tasks with comment) @grep -E '^[a-zA-Z._-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' @@ -17,4 +19,22 @@ test: lint i: install ## build and install to /usr/local/bin/ lint: - golangci-lint run --timeout 10m -v \ No newline at end of file + golangci-lint run --timeout 10m -v + +define generate-example + docker run \ + --interactive \ + --tty \ + --volume $(shell pwd):/src \ + --workdir /src/example \ + --entrypoint /bin/sh \ + hashicorp/terraform:$(1) \ + -c \ + "terraform init && \ + terraform plan -out tfplan && \ + terraform show -json tfplan > tfplan.json" +endef + +example: + $(call generate-example,$(TERRAFORM_VERSION)) +.PHONY: example diff --git a/example/.terraform-version b/example/.terraform-version new file mode 100644 index 0000000..65087b4 --- /dev/null +++ b/example/.terraform-version @@ -0,0 +1 @@ +1.1.4 diff --git a/example/tfplan b/example/tfplan new file mode 100644 index 0000000000000000000000000000000000000000..8ab498263a9420a3c5ef3324f1607397e72caef8 GIT binary patch literal 5306 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 d>Bi2v{>zs&z9(h literal 0 HcmV?d00001 diff --git a/example/tfplan.json b/example/tfplan.json new file mode 100644 index 0000000..a151ff1 --- /dev/null +++ b/example/tfplan.json @@ -0,0 +1 @@ +{"format_version":"1.0","terraform_version":"1.1.4","planned_values":{"root_module":{"resources":[{"address":"github_repository.terraform_plan_summary","mode":"managed","type":"github_repository","name":"terraform_plan_summary","provider_name":"registry.terraform.io/integrations/github","schema_version":0,"values":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"A command-line utility to print the summary of the terraform plan","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"terraform-plan-summary","pages":[],"template":[],"topics":["summary","terraform"],"visibility":"public","vulnerability_alerts":false},"sensitive_values":{"branches":[],"pages":[],"template":[],"topics":[false,false]}}],"child_modules":[{"resources":[{"address":"module.github[\"demo-repository\"].github_branch.development","mode":"managed","type":"github_branch","name":"development","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"branch":"development","repository":"demo-repository","source_branch":"main"},"sensitive_values":{}},{"address":"module.github[\"demo-repository\"].github_branch.main","mode":"managed","type":"github_branch","name":"main","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"branch":"main","repository":"demo-repository","source_branch":"main"},"sensitive_values":{}},{"address":"module.github[\"demo-repository\"].github_repository.repository","mode":"managed","type":"github_repository","name":"repository","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"description of the repo","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"demo-repository","pages":[],"template":[],"topics":["tags"],"visibility":"public","vulnerability_alerts":false},"sensitive_values":{"branches":[],"pages":[],"template":[],"topics":[false]}}],"address":"module.github[\"demo-repository\"]"},{"resources":[{"address":"module.github[\"terraform-plan-summary\"].github_branch.demo","mode":"managed","type":"github_branch","name":"demo","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"sensitive_values":false},{"address":"module.github[\"terraform-plan-summary\"].github_branch.development","mode":"managed","type":"github_branch","name":"development","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"branch":"development","repository":"terraform-plan-summary","source_branch":"main"},"sensitive_values":{}},{"address":"module.github[\"terraform-plan-summary\"].github_branch.main","mode":"managed","type":"github_branch","name":"main","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"branch":"main","repository":"terraform-plan-summary","source_branch":"main"},"sensitive_values":{}},{"address":"module.github[\"terraform-plan-summary\"].github_repository.repository","mode":"managed","type":"github_repository","name":"repository","provider_name":"registry.terraform.io/hashicorp/github","schema_version":0,"values":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"A command-line utility to print the summary of the terraform plan","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"terraform-plan-summary","pages":[],"template":[],"topics":["summary","terraform"],"visibility":"public","vulnerability_alerts":false},"sensitive_values":{"branches":[],"pages":[],"template":[],"topics":[false,false]}}],"address":"module.github[\"terraform-plan-summary\"]"}]}},"resource_drift":[{"address":"module.github[\"terraform-plan-summary\"].github_branch.demo","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_branch","name":"demo","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["delete"],"before":{"branch":"demo","etag":"W/\"2c138304ec0f031d3ffd19d45dae737be855a74a8d7e48f4fae4fc9213a6dbf6\"","id":"terraform-plan-summary:demo","ref":"refs/heads/demo","repository":"terraform-plan-summary","sha":"2e3d2c0b4513373c72b96b29592b62581e271af9","source_branch":"main","source_sha":null},"after":null,"after_unknown":{},"before_sensitive":{},"after_sensitive":false}},{"address":"module.github[\"terraform-plan-summary\"].github_branch.main","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_branch","name":"main","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["delete"],"before":{"branch":"main","etag":"W/\"4d429c1f4818d4314dcd07dd1e034b2bab0014a46bf9088635e37fd6decc64b8\"","id":"terraform-plan-summary:main","ref":"refs/heads/main","repository":"terraform-plan-summary","sha":"ad0cb343cc26f08985e5517bd2da8f0483beaa4b","source_branch":"main","source_sha":null},"after":null,"after_unknown":{},"before_sensitive":{},"after_sensitive":false}},{"address":"module.github[\"terraform-plan-summary\"].github_repository.repository","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_repository","name":"repository","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["delete"],"before":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":false,"branches":[{"name":"main","protected":false},{"name":"trail","protected":false}],"default_branch":"main","delete_branch_on_merge":false,"description":"A command-line utility to print the summary of the terraform plan","etag":"W/\"7536d6c2714d2e49890a3d1ebed0a31e89b6412f973e0d631089836e25229f29\"","full_name":"dineshba/terraform-plan-summary","git_clone_url":"git://github.com/dineshba/terraform-plan-summary.git","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":"","html_url":"https://github.com/dineshba/terraform-plan-summary","http_clone_url":"https://github.com/dineshba/terraform-plan-summary.git","id":"terraform-plan-summary","ignore_vulnerability_alerts_during_read":null,"is_template":false,"license_template":null,"name":"terraform-plan-summary","node_id":"R_kgDOGq54_w","pages":[],"private":false,"repo_id":447641855,"ssh_clone_url":"git@github.com:dineshba/terraform-plan-summary.git","svn_url":"https://github.com/dineshba/terraform-plan-summary","template":[],"topics":["summary","terraform"],"visibility":"public","vulnerability_alerts":true},"after":null,"after_unknown":{},"before_sensitive":{"branches":[{},{}],"pages":[],"template":[],"topics":[false,false]},"after_sensitive":false}}],"resource_changes":[{"address":"github_repository.terraform_plan_summary","mode":"managed","type":"github_repository","name":"terraform_plan_summary","provider_name":"registry.terraform.io/integrations/github","change":{"actions":["create"],"before":null,"after":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"A command-line utility to print the summary of the terraform plan","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"terraform-plan-summary","pages":[],"template":[],"topics":["summary","terraform"],"visibility":"public","vulnerability_alerts":false},"after_unknown":{"branches":true,"default_branch":true,"etag":true,"full_name":true,"git_clone_url":true,"html_url":true,"http_clone_url":true,"id":true,"node_id":true,"pages":[],"private":true,"repo_id":true,"ssh_clone_url":true,"svn_url":true,"template":[],"topics":[false,false]},"before_sensitive":false,"after_sensitive":{"branches":[],"pages":[],"template":[],"topics":[false,false]}}},{"address":"module.github[\"demo-repository\"].github_branch.development","module_address":"module.github[\"demo-repository\"]","mode":"managed","type":"github_branch","name":"development","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"branch":"development","repository":"demo-repository","source_branch":"main"},"after_unknown":{"etag":true,"id":true,"ref":true,"sha":true,"source_sha":true},"before_sensitive":false,"after_sensitive":{}}},{"address":"module.github[\"demo-repository\"].github_branch.main","module_address":"module.github[\"demo-repository\"]","mode":"managed","type":"github_branch","name":"main","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"branch":"main","repository":"demo-repository","source_branch":"main"},"after_unknown":{"etag":true,"id":true,"ref":true,"sha":true,"source_sha":true},"before_sensitive":false,"after_sensitive":{}}},{"address":"module.github[\"demo-repository\"].github_repository.repository","module_address":"module.github[\"demo-repository\"]","mode":"managed","type":"github_repository","name":"repository","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"description of the repo","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"demo-repository","pages":[],"template":[],"topics":["tags"],"visibility":"public","vulnerability_alerts":false},"after_unknown":{"branches":true,"default_branch":true,"etag":true,"full_name":true,"git_clone_url":true,"html_url":true,"http_clone_url":true,"id":true,"node_id":true,"pages":[],"private":true,"repo_id":true,"ssh_clone_url":true,"svn_url":true,"template":[],"topics":[false]},"before_sensitive":false,"after_sensitive":{"branches":[],"pages":[],"template":[],"topics":[false]}}},{"address":"module.github[\"terraform-plan-summary\"].github_branch.demo","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_branch","name":"demo","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["no-op"],"before":null,"after":null,"after_unknown":{},"before_sensitive":false,"after_sensitive":false},"action_reason":"delete_because_no_resource_config"},{"address":"module.github[\"terraform-plan-summary\"].github_branch.development","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_branch","name":"development","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"branch":"development","repository":"terraform-plan-summary","source_branch":"main"},"after_unknown":{"etag":true,"id":true,"ref":true,"sha":true,"source_sha":true},"before_sensitive":false,"after_sensitive":{}}},{"address":"module.github[\"terraform-plan-summary\"].github_branch.main","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_branch","name":"main","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"branch":"main","repository":"terraform-plan-summary","source_branch":"main"},"after_unknown":{"etag":true,"id":true,"ref":true,"sha":true,"source_sha":true},"before_sensitive":false,"after_sensitive":{}}},{"address":"module.github[\"terraform-plan-summary\"].github_repository.repository","module_address":"module.github[\"terraform-plan-summary\"]","mode":"managed","type":"github_repository","name":"repository","provider_name":"registry.terraform.io/hashicorp/github","change":{"actions":["create"],"before":null,"after":{"allow_auto_merge":false,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_squash_merge":true,"archive_on_destroy":null,"archived":false,"auto_init":null,"delete_branch_on_merge":false,"description":"A command-line utility to print the summary of the terraform plan","gitignore_template":null,"has_downloads":true,"has_issues":true,"has_projects":true,"has_wiki":true,"homepage_url":null,"ignore_vulnerability_alerts_during_read":null,"is_template":null,"license_template":null,"name":"terraform-plan-summary","pages":[],"template":[],"topics":["summary","terraform"],"visibility":"public","vulnerability_alerts":false},"after_unknown":{"branches":true,"default_branch":true,"etag":true,"full_name":true,"git_clone_url":true,"html_url":true,"http_clone_url":true,"id":true,"node_id":true,"pages":[],"private":true,"repo_id":true,"ssh_clone_url":true,"svn_url":true,"template":[],"topics":[false,false]},"before_sensitive":false,"after_sensitive":{"branches":[],"pages":[],"template":[],"topics":[false,false]}}}],"configuration":{"provider_config":{"github":{"name":"github","version_constraint":"4.23.0","expressions":{"owner":{"constant_value":"dineshba"}}}},"root_module":{"resources":[{"address":"github_repository.terraform_plan_summary","mode":"managed","type":"github_repository","name":"terraform_plan_summary","provider_config_key":"github","expressions":{"description":{"constant_value":"A command-line utility to print the summary of the terraform plan"},"has_downloads":{"constant_value":true},"has_issues":{"constant_value":true},"has_projects":{"constant_value":true},"has_wiki":{"constant_value":true},"name":{"constant_value":"terraform-plan-summary"},"topics":{"constant_value":["summary","terraform"]},"visibility":{"constant_value":"public"},"vulnerability_alerts":{"constant_value":false}},"schema_version":0}],"module_calls":{"github":{"source":"./github","expressions":{"description":{"references":["each.value.description","each.value"]},"name":{"references":["each.key"]},"topics":{"references":["each.value.topics","each.value"]}},"for_each_expression":{"references":["local.repos"]},"module":{"resources":[{"address":"github_branch.development","mode":"managed","type":"github_branch","name":"development","provider_config_key":"github:github","expressions":{"branch":{"constant_value":"development"},"repository":{"references":["github_repository.repository.name","github_repository.repository"]}},"schema_version":0},{"address":"github_branch.main","mode":"managed","type":"github_branch","name":"main","provider_config_key":"github:github","expressions":{"branch":{"constant_value":"main"},"repository":{"references":["github_repository.repository.name","github_repository.repository"]}},"schema_version":0},{"address":"github_repository.repository","mode":"managed","type":"github_repository","name":"repository","provider_config_key":"github:github","expressions":{"description":{"references":["var.description"]},"has_downloads":{"constant_value":true},"has_issues":{"constant_value":true},"has_projects":{"constant_value":true},"has_wiki":{"constant_value":true},"name":{"references":["var.name"]},"topics":{"references":["var.topics"]},"visibility":{"constant_value":"public"},"vulnerability_alerts":{"constant_value":false}},"schema_version":0}],"variables":{"description":{},"name":{},"topics":{}}}}}}}} From b30b0cba283b659bd9770a88d5d34a944894b287 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Mon, 15 Jan 2024 07:45:52 -0500 Subject: [PATCH 4/5] add automated test verifying STDIN vs file-provided input This adds a basic automated test verifying the validity of the issue #20 fix. --- .gitignore | 2 + example/tfplan | Bin 5306 -> 0 bytes main_test.go | 95 +++++++++++++++++++++++++++++++++++++++++++++ testdata/basic.txt | 9 +++++ 4 files changed, 106 insertions(+) delete mode 100644 example/tfplan create mode 100644 main_test.go create mode 100644 testdata/basic.txt diff --git a/.gitignore b/.gitignore index 5064a9e..704d484 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ tf-summarize **/.envrc **/.terraform *.swp + +example/tfplan diff --git a/example/tfplan b/example/tfplan deleted file mode 100644 index 8ab498263a9420a3c5ef3324f1607397e72caef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5306 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 d>Bi2v{>zs&z9(h diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..80ec18a --- /dev/null +++ b/main_test.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "log" + "os" + "os/exec" + "strings" + "testing" +) + +const ( + testVersion string = "test" + testExecutable string = "tf-summarize-test" +) + +func TestMain(m *testing.M) { + // compile a 'tf-summarize' for use in running tests + exe := exec.Command("go", "build", "-ldflags", fmt.Sprintf("-X main.version=%s", testVersion), "-o", testExecutable) + err := exe.Run() + if err != nil { + os.Exit(1) + } + + m.Run() + + // delete the compiled tf-summarize + err = os.Remove(testExecutable) + if err != nil { + log.Fatal(err) + } +} + +func TestVersionArg(t *testing.T) { + args := []string{ + "-v", + } + + for _, arg := range args { + t.Run(fmt.Sprintf("when tf-summarize is passed '%s'", arg), func(t *testing.T) { + output, err := exec.Command(fmt.Sprintf("./%s", testExecutable), arg).CombinedOutput() + if err != nil { + t.Errorf("expected '%s' not to cause error; got '%v'", arg, err) + } + + if !strings.Contains(string(output), testVersion) { + t.Errorf("expected '%s' to output version '%s'; got '%s'", arg, testVersion, output) + } + }) + } +} + +func TestTFSummarize(t *testing.T) { + tests := []struct { + command string + expectedError error + expectedOutput string + }{{ + command: fmt.Sprintf("./%s -md example/tfplan.json", testExecutable), + expectedOutput: "basic.txt", + }, { + command: fmt.Sprintf("cat example/tfplan.json | ./%s -md", testExecutable), + expectedOutput: "basic.txt", + }} + + for _, test := range tests { + t.Run(fmt.Sprintf("when tf-summarize is passed '%q'", test.command), func(t *testing.T) { + output, err := exec.Command("/bin/sh", "-c", test.command).CombinedOutput() + if err != nil && test.expectedError == nil { + t.Errorf("expected '%s' not to error; got '%v'", test.command, err) + } + + b, err := os.ReadFile(fmt.Sprintf("testdata/%s", test.expectedOutput)) + if err != nil { + t.Errorf("error reading file '%s': '%v'", test.expectedOutput, err) + } + + expected := string(b) + + if test.expectedError != nil && err == nil { + t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), err) + } + + if test.expectedError != nil && err != nil && test.expectedError.Error() != err.Error() { + t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), err.Error()) + } + + if string(output) != expected { + t.Logf("expected output: \n%s", expected) + t.Logf("got output: \n%s", output) + t.Errorf("received unexpected output from '%s'", test.command) + } + }) + } +} diff --git a/testdata/basic.txt b/testdata/basic.txt new file mode 100644 index 0000000..bb145c0 --- /dev/null +++ b/testdata/basic.txt @@ -0,0 +1,9 @@ +| CHANGE | RESOURCE | +|--------|------------------------------------------------------------------------| +| add | `github_repository.terraform_plan_summary` | +| | `module.github["demo-repository"].github_branch.development` | +| | `module.github["demo-repository"].github_branch.main` | +| | `module.github["demo-repository"].github_repository.repository` | +| | `module.github["terraform-plan-summary"].github_branch.development` | +| | `module.github["terraform-plan-summary"].github_branch.main` | +| | `module.github["terraform-plan-summary"].github_repository.repository` | From 7a34e31d10733ae8c22b2169a878eb58f4b7df83 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Wed, 24 Jan 2024 15:46:10 -0500 Subject: [PATCH 5/5] remove `demo` job from Build GH Actions workflow Per code review request, @dineshba would prefer this be kept in a separate file. --- .github/workflows/build.yml | 56 ------------------------------------- 1 file changed, 56 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb6994d..009e368 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,59 +32,3 @@ jobs: - name: Build run: go build - - demo: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: "1.21" - - - name: Build - run: | - go build -o example/tf-summarize - - - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_wrapper: false - - - name: Print tf-summarize version and help - run: | - ./tf-summarize -v - ./tf-summarize -h - working-directory: ./example - - - name: Terraform Init - run: terraform init - working-directory: ./example - - - name: Terraform Plan - run: | - terraform plan -out=tfplan -refresh=false # -refresh=false is only for demo workflow - terraform show -json tfplan > tfplan.json - working-directory: ./example - - - name: summary in table format - run: terraform show -json tfplan | ./tf-summarize - working-directory: ./example - - - name: summary in table format with plan JSON file passed - run: | - ./tf-summarize tfplan.json - working-directory: ./example - - - name: summary in tree format - run: terraform show -json tfplan | ./tf-summarize -tree - working-directory: ./example - - - name: summary in separate tree format - run: terraform show -json tfplan | ./tf-summarize -separate-tree - working-directory: ./example - - - name: summary in draw visual tree format - run: terraform show -json tfplan | ./tf-summarize -tree -draw - working-directory: ./example