From 2a7a3684ac96434ab02d35b92779f6ea052c3a23 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Wed, 27 Jan 2021 18:56:54 +0000 Subject: [PATCH 01/18] feat: parse terraform plan --- terraplanfeed/cli.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/terraplanfeed/cli.py b/terraplanfeed/cli.py index dfeedb1..abb27c4 100644 --- a/terraplanfeed/cli.py +++ b/terraplanfeed/cli.py @@ -2,6 +2,7 @@ import os import sys +import json import click from terraplanfeed import __version__ @@ -17,6 +18,14 @@ def version_msg(): @click.command(context_settings=dict(help_option_names=["-h", "--help"])) @click.version_option(__version__, "-V", "--version", message=version_msg()) -def main(): +@click.argument("filename", type=click.Path(exists=True)) +def main(filename): """Parse Terraform plan in JSON format.""" - click.echo("Hello World") + # click.echo("Terraform JSON file: %s" % filename) + + """Open JSON file""" + with open(filename) as f: + data = json.load(f) + # print(data["resource_changes"]) + for r in data["resource_changes"]: + print(r["address"]) From 17766d54ee060a734892dbc9395ee35b397032a5 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Wed, 27 Jan 2021 18:57:46 +0000 Subject: [PATCH 02/18] Apply automatic changes --- CHANGELOG.md | 19 ++++++++++++++++++- terraplanfeed/__init__.py | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e48f49d..a1fc841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ ## [Unreleased] + +## [0.1.4] - 2021-01-27 +### Feat +- parse terraform plan + + + +## [0.1.3] - 2021-01-25 +### Fix +- gitignore + + ## [0.1.2] - 2021-01-25 ### Chore @@ -12,6 +24,9 @@ - requirements.txt - setup.py classifiers +### Pull Requests +- Merge pull request [#3](https://github.com/bcochofel/terraplanfeed/issues/3) from bcochofel/env_configuration + ## [0.1.1] - 2021-01-24 @@ -43,6 +58,8 @@ - Merge pull request [#1](https://github.com/bcochofel/terraplanfeed/issues/1) from bcochofel/package_skel -[Unreleased]: https://github.com/bcochofel/terraplanfeed/compare/0.1.2...HEAD +[Unreleased]: https://github.com/bcochofel/terraplanfeed/compare/0.1.4...HEAD +[0.1.4]: https://github.com/bcochofel/terraplanfeed/compare/0.1.3...0.1.4 +[0.1.3]: https://github.com/bcochofel/terraplanfeed/compare/0.1.2...0.1.3 [0.1.2]: https://github.com/bcochofel/terraplanfeed/compare/0.1.1...0.1.2 [0.1.1]: https://github.com/bcochofel/terraplanfeed/compare/0.1.0...0.1.1 diff --git a/terraplanfeed/__init__.py b/terraplanfeed/__init__.py index 1137067..ef7299a 100644 --- a/terraplanfeed/__init__.py +++ b/terraplanfeed/__init__.py @@ -1,2 +1,2 @@ """Main package for terraplanfeed.""" -__version__ = "0.1.2" +__version__ = "0.1.4" From 4cbc34433758ad5570607a80e659e3bb8ecce26f Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Wed, 27 Jan 2021 21:41:49 +0000 Subject: [PATCH 03/18] feat: module structure --- terraplanfeed/cli.py | 37 ++++++++++++++++++++-------- terraplanfeed/log.py | 50 ++++++++++++++++++++++++++++++++++++++ terraplanfeed/main.py | 24 ++++++++++++++++++ terraplanfeed/terraform.py | 12 +++++++++ 4 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 terraplanfeed/log.py create mode 100644 terraplanfeed/main.py create mode 100644 terraplanfeed/terraform.py diff --git a/terraplanfeed/cli.py b/terraplanfeed/cli.py index abb27c4..98600c1 100644 --- a/terraplanfeed/cli.py +++ b/terraplanfeed/cli.py @@ -2,10 +2,11 @@ import os import sys -import json import click from terraplanfeed import __version__ +from terraplanfeed.log import configure_logger +from terraplanfeed.main import terraplanfeed def version_msg(): @@ -19,13 +20,29 @@ def version_msg(): @click.command(context_settings=dict(help_option_names=["-h", "--help"])) @click.version_option(__version__, "-V", "--version", message=version_msg()) @click.argument("filename", type=click.Path(exists=True)) -def main(filename): +@click.option( + "-v", + "--verbose", + is_flag=True, + help="Print debug information", + default=False, +) +@click.option( + "-d", + "--debug-file", + type=click.Path(), + default=None, + help="Print debug information to this file", +) +def main(filename, verbose, debug_file): """Parse Terraform plan in JSON format.""" - # click.echo("Terraform JSON file: %s" % filename) - - """Open JSON file""" - with open(filename) as f: - data = json.load(f) - # print(data["resource_changes"]) - for r in data["resource_changes"]: - print(r["address"]) + + configure_logger( + stream_level="DEBUG" if verbose else "INFO", debug_file=debug_file + ) + + terraplanfeed(filename) + + +if __name__ == "__main__": + main() diff --git a/terraplanfeed/log.py b/terraplanfeed/log.py new file mode 100644 index 0000000..e51d204 --- /dev/null +++ b/terraplanfeed/log.py @@ -0,0 +1,50 @@ +"""Module for setting up logging.""" +import logging +import sys + +LOG_LEVELS = { + "DEBUG": logging.DEBUG, + "INFO": logging.INFO, + "WARNING": logging.WARNING, + "ERROR": logging.ERROR, + "CRITICAL": logging.CRITICAL, +} + +LOG_FORMATS = { + "DEBUG": "%(levelname)s %(name)s: %(message)s", + "INFO": "%(levelname)s: %(message)s", +} + + +def configure_logger(stream_level="DEBUG", debug_file=None): + """Configure logging. + Set up logging to stdout with given level. If ``debug_file`` is given set + up logging to file with DEBUG level. + """ + # Set up 'terraplanfeed' logger + logger = logging.getLogger("terraplanfeed") + logger.setLevel(logging.DEBUG) + + # Remove all attached handlers, in case there was + # a logger with using the name 'terraplanfeed' + del logger.handlers[:] + + # Create a file handler if a log file is provided + if debug_file is not None: + debug_formatter = logging.Formatter(LOG_FORMATS["DEBUG"]) + file_handler = logging.FileHandler(debug_file) + file_handler.setLevel(LOG_LEVELS["DEBUG"]) + file_handler.setFormatter(debug_formatter) + logger.addHandler(file_handler) + + # Get settings based on the given stream_level + log_formatter = logging.Formatter(LOG_FORMATS[stream_level]) + log_level = LOG_LEVELS[stream_level] + + # Create a stream handler + stream_handler = logging.StreamHandler(stream=sys.stdout) + stream_handler.setLevel(log_level) + stream_handler.setFormatter(log_formatter) + logger.addHandler(stream_handler) + + return logger diff --git a/terraplanfeed/main.py b/terraplanfeed/main.py new file mode 100644 index 0000000..094e5dd --- /dev/null +++ b/terraplanfeed/main.py @@ -0,0 +1,24 @@ +"""Main entrypoint for terraplanfeed command.""" +import logging +import sys +import os +import json + +from terraplanfeed.terraform import parseJson + +logger = logging.getLogger(__name__) + + +def terraplanfeed(filename): + """Execute terraplanfeed.""" + + """Open JSON file""" + logger.debug("parsing file %s", filename) + with open(filename) as f: + try: + data = json.load(f) + except json.decoder.JSONDecodeError: + logger.debug("%s", sys.exc_info()) + sys.exit(1) + + parseJson(data) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py new file mode 100644 index 0000000..85afbda --- /dev/null +++ b/terraplanfeed/terraform.py @@ -0,0 +1,12 @@ +"""Terraform handler.""" +import logging + +logger = logging.getLogger(__name__) + + +def parseJson(data): + """Parse Terraform plan in JSON""" + + logger.debug("processing changes...") + for r in data["resource_changes"]: + print(r["address"]) From 4831bd374270fc562f6a22d70d1c5e42e2b269e7 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Wed, 27 Jan 2021 21:42:46 +0000 Subject: [PATCH 04/18] Apply automatic changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1fc841..da690ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ## [0.1.4] - 2021-01-27 ### Feat +- module structure - parse terraform plan From ee16fcc93fa581d6e88c05fd6c2571b9090714e1 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Wed, 27 Jan 2021 22:03:53 +0000 Subject: [PATCH 05/18] fix: validate json file --- terraplanfeed/main.py | 10 +++++----- terraplanfeed/terraform.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/terraplanfeed/main.py b/terraplanfeed/main.py index 094e5dd..f9e0189 100644 --- a/terraplanfeed/main.py +++ b/terraplanfeed/main.py @@ -4,7 +4,7 @@ import os import json -from terraplanfeed.terraform import parseJson +from terraplanfeed.terraform import resourceChanges logger = logging.getLogger(__name__) @@ -16,9 +16,9 @@ def terraplanfeed(filename): logger.debug("parsing file %s", filename) with open(filename) as f: try: - data = json.load(f) - except json.decoder.JSONDecodeError: - logger.debug("%s", sys.exc_info()) + tf = json.load(f) + except ValueError as e: + logger.error("%s", e) sys.exit(1) - parseJson(data) + resourceChanges(tf) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index 85afbda..5962eee 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -4,9 +4,9 @@ logger = logging.getLogger(__name__) -def parseJson(data): +def resourceChanges(tfplan): """Parse Terraform plan in JSON""" logger.debug("processing changes...") - for r in data["resource_changes"]: + for r in tfplan["resource_changes"]: print(r["address"]) From 218579df74880332cd530a420395db556db167b4 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Wed, 27 Jan 2021 22:04:57 +0000 Subject: [PATCH 06/18] Apply automatic changes --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da690ce..ce4296e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ - module structure - parse terraform plan +### Fix +- validate json file + ## [0.1.3] - 2021-01-25 From a6f0fd89197b385fa1afd3b54f736fd8e4194f29 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Wed, 27 Jan 2021 22:17:14 +0000 Subject: [PATCH 07/18] chore: vscode settings for project --- .gitignore | 8 ++++---- .vscode/launch.json | 24 ++++++++++++++++++++++++ .vscode/settings.json | 5 +++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 90b9135..e447e4b 100644 --- a/.gitignore +++ b/.gitignore @@ -247,10 +247,10 @@ dmypy.json ### vscode ### .vscode/* -#!.vscode/settings.json -#!.vscode/tasks.json -#!.vscode/launch.json -#!.vscode/extensions.json +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json *.code-workspace # End of https://www.toptal.com/developers/gitignore/api/python,intellij,vscode diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dffea0c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Module", + "type": "python", + "request": "launch", + "module": "terraplanfeed", + "args": [ + "'${input:filename}'" + ] + } + ], + "inputs": [ + { + "id": "filename", + "type": "promptString", + "description": "Terraform plan in JSON format" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5443912 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.pythonPath": ".venv/bin/python3", + "editor.formatOnSave": true, + "python.formatting.provider": "black" +} \ No newline at end of file From 18d64f3799a0a3abde562da05652650fbbb63c17 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Wed, 27 Jan 2021 22:18:04 +0000 Subject: [PATCH 08/18] Apply automatic changes --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce4296e..ea383f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ## [0.1.4] - 2021-01-27 +### Chore +- vscode settings for project + ### Feat - module structure - parse terraform plan From 4cdab674b2708346c2292bdd5ddd3dc894ccb857 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Wed, 27 Jan 2021 22:35:00 +0000 Subject: [PATCH 09/18] docs: terraform link for json docs --- terraplanfeed/terraform.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index 5962eee..abbb23b 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -1,4 +1,8 @@ -"""Terraform handler.""" +"""Terraform handler. + +Check https://www.terraform.io/docs/internals/json-format.html +for more info +""" import logging logger = logging.getLogger(__name__) From 27257c15e5d822f2e25c3719f6c2a1f38869736d Mon Sep 17 00:00:00 2001 From: bcochofel Date: Wed, 27 Jan 2021 22:35:53 +0000 Subject: [PATCH 10/18] Apply automatic changes --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea383f0..6fff44c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ ### Chore - vscode settings for project +### Docs +- terraform link for json docs + ### Feat - module structure - parse terraform plan From f83af9f9c9504737923eb6080e8fbab54840c282 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Thu, 28 Jan 2021 18:33:14 +0000 Subject: [PATCH 11/18] feat: terraform functions for filtering data --- terraplanfeed/main.py | 6 +++--- terraplanfeed/terraform.py | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/terraplanfeed/main.py b/terraplanfeed/main.py index f9e0189..04b834a 100644 --- a/terraplanfeed/main.py +++ b/terraplanfeed/main.py @@ -4,7 +4,7 @@ import os import json -from terraplanfeed.terraform import resourceChanges +from terraplanfeed.terraform import parsePlan logger = logging.getLogger(__name__) @@ -13,7 +13,7 @@ def terraplanfeed(filename): """Execute terraplanfeed.""" """Open JSON file""" - logger.debug("parsing file %s", filename) + logger.debug("reading file %s", filename) with open(filename) as f: try: tf = json.load(f) @@ -21,4 +21,4 @@ def terraplanfeed(filename): logger.error("%s", e) sys.exit(1) - resourceChanges(tf) + parsePlan(tf) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index abbb23b..469214d 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -8,9 +8,37 @@ logger = logging.getLogger(__name__) -def resourceChanges(tfplan): +def getResourceChanges(data): + """Filter Resource Changes from Plan.""" + + logger.debug("filter resource_changes from plan") + if "resource_changes" in data.keys(): + return data["resource_changes"] + else: + logger.error("no resource_changes found") + return [] + + +def filterNoOp(data): + """Filter no-op actions.""" + + changes = [] + + logger.debug("filter no-op actions") + for res in data: + if res["change"]["actions"] != ["no-op"]: + changes.append(res) + + return changes + + +def parsePlan(tfplan): """Parse Terraform plan in JSON""" - logger.debug("processing changes...") - for r in tfplan["resource_changes"]: - print(r["address"]) + logger.debug("parsing file...") + + all_resources = getResourceChanges(tfplan) + # print(all_resources) + + resource_changing = filterNoOp(all_resources) + print(resource_changing) From 85913a2fb80901e504b6f67f57b8651183a0c572 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Thu, 28 Jan 2021 18:34:08 +0000 Subject: [PATCH 12/18] Apply automatic changes --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fff44c..9729c08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ -## [0.1.4] - 2021-01-27 +## [0.1.4] - 2021-01-28 ### Chore - vscode settings for project @@ -12,6 +12,7 @@ - terraform link for json docs ### Feat +- terraform functions for filtering data - module structure - parse terraform plan From ec894cfaa0b8a00e03a7a93ce47bcb378d5566c8 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Thu, 28 Jan 2021 19:07:44 +0000 Subject: [PATCH 13/18] feat: create resource attributes --- terraplanfeed/terraform.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index 469214d..8bf5b7c 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -23,7 +23,6 @@ def filterNoOp(data): """Filter no-op actions.""" changes = [] - logger.debug("filter no-op actions") for res in data: if res["change"]["actions"] != ["no-op"]: @@ -32,6 +31,24 @@ def filterNoOp(data): return changes +def parseResource(data): + """Parse Resource to retrive elements""" + + logger.debug("retrieve elements from resource") + rc = {"address": data["address"], "actions": data["change"]["actions"]} + return rc + + +def getAttributes(data): + """Get attributes from resource""" + + resources = [] + logger.debug("get attributes from resources") + for res in data: + resources.append(parseResource(res)) + return resources + + def parsePlan(tfplan): """Parse Terraform plan in JSON""" @@ -41,4 +58,7 @@ def parsePlan(tfplan): # print(all_resources) resource_changing = filterNoOp(all_resources) - print(resource_changing) + # print(resource_changing) + + resources = getAttributes(resource_changing) + print(resources) From 2a719eec611c9af4421d3e7fde7ba8005cc3ef8c Mon Sep 17 00:00:00 2001 From: bcochofel Date: Thu, 28 Jan 2021 19:08:26 +0000 Subject: [PATCH 14/18] Apply automatic changes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9729c08..8aef2ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - terraform link for json docs ### Feat +- create resource attributes - terraform functions for filtering data - module structure - parse terraform plan From bf6427a2624199612149441789b320c1bc62cb36 Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Fri, 29 Jan 2021 09:07:43 +0000 Subject: [PATCH 15/18] docs: docstrings update --- README.md | 11 ++++- terraplanfeed/__init__.py | 10 ++++- terraplanfeed/cli.py | 11 ++++- terraplanfeed/log.py | 7 +++- terraplanfeed/main.py | 12 +++++- terraplanfeed/terraform.py | 83 ++++++++++++++++++++++++++++++++------ 6 files changed, 115 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2d82ae8..408a4ed 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ This tool aims to parse Terraform plan files (in JSON format) and gives feedback Outputs can be: * stdout -* stdout in JSON * Github pull request comment * Azure DevOps pull request comment @@ -19,7 +18,7 @@ To create the Terraform plan file: ```bash terraform init terraform plan -out=plan.out -terraform show -no-color plan.out > plan.json +terraform show -no-color -json plan.out > plan.json ``` # Run and test locally @@ -36,6 +35,14 @@ Read the [pre-commit hooks](docs/pre-commit-hooks.md) document for more info. Read the [git-chglog](docs/git-chlog.md) document for more info. +# References + +* [Making a Python package](https://python-packaging-tutorial.readthedocs.io/en/latest/setup_py.html) +* [Documenting Python code](https://realpython.com/documenting-python-code/) +* [Python Docstrings Google](https://google.github.io/styleguide/pyguide.html) +* [Python Click](https://click.palletsprojects.com) +* [Terraform JSON output format](https://www.terraform.io/docs/internals/json-format.html) + [pre-commit]: https://github.com/pre-commit/pre-commit [pre-commit-badge]: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white [conventional-commits-badge]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg diff --git a/terraplanfeed/__init__.py b/terraplanfeed/__init__.py index ef7299a..ef43649 100644 --- a/terraplanfeed/__init__.py +++ b/terraplanfeed/__init__.py @@ -1,2 +1,10 @@ -"""Main package for terraplanfeed.""" +""" +Main package for terraplanfeed. + +This package receives a file in Terraform JSON output, parses to get the +changes, and creates output that can be sent to different output drivers. + +Modules: + terraform +""" __version__ = "0.1.4" diff --git a/terraplanfeed/cli.py b/terraplanfeed/cli.py index 98600c1..c5a8d5f 100644 --- a/terraplanfeed/cli.py +++ b/terraplanfeed/cli.py @@ -1,4 +1,13 @@ -"""Entry point for package.""" +""" +Entry point for package. + +Arguments: + -h, --help: prints help + -V, --version: prints version, location and python powering it + (required): terraform plan in json format + -v, --verbose: prints debug information + -d, --debug-file: filename to print debug information +""" import os import sys diff --git a/terraplanfeed/log.py b/terraplanfeed/log.py index e51d204..6b75da4 100644 --- a/terraplanfeed/log.py +++ b/terraplanfeed/log.py @@ -1,4 +1,9 @@ -"""Module for setting up logging.""" +""" +Module for setting up logging. + +Functions: + configure_logger: configures logger +""" import logging import sys diff --git a/terraplanfeed/main.py b/terraplanfeed/main.py index 04b834a..524c689 100644 --- a/terraplanfeed/main.py +++ b/terraplanfeed/main.py @@ -1,4 +1,11 @@ -"""Main entrypoint for terraplanfeed command.""" +""" +Main entrypoint for terraplanfeed command. + +Main code execution for terraplanfeed command. + +Functions: + terraplanfeed: main code execution +""" import logging import sys import os @@ -21,4 +28,5 @@ def terraplanfeed(filename): logger.error("%s", e) sys.exit(1) - parsePlan(tf) + resources = parsePlan(tf) + print(resources) diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index 8bf5b7c..6670d65 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -1,7 +1,17 @@ """Terraform handler. +This module handles terraform plan in json output format. + Check https://www.terraform.io/docs/internals/json-format.html for more info + +Functions: + getResourceChanges: filters resource_changes from plan file + filterNoOp: filters out no-op actions from resource_changes + parseResource: parses resource to get some metadata like, + name, address + getAttributes: creates a list of resources with some attributes + parsePlan: main function """ import logging @@ -9,7 +19,17 @@ def getResourceChanges(data): - """Filter Resource Changes from Plan.""" + """ + Filters Resource Changes from Plan. + + Retrieves the resource_changes portion from terraform plan. + + Args: + data (dict): dict from json.load('') + + Returns: + List of resource_changes + """ logger.debug("filter resource_changes from plan") if "resource_changes" in data.keys(): @@ -19,28 +39,57 @@ def getResourceChanges(data): return [] -def filterNoOp(data): - """Filter no-op actions.""" +def filterNoOp(resources): + """ + Filters no-op actions. + + Parses all the resource_changes and cleans out the ones with no-op actions + + Args: + data(list): list of resource_changes (output from getResourceChanges) + + Returns: + List of resources that are going to be changed + """ changes = [] logger.debug("filter no-op actions") - for res in data: + for res in resources: if res["change"]["actions"] != ["no-op"]: changes.append(res) return changes -def parseResource(data): - """Parse Resource to retrive elements""" +def parseResource(resource): + """ + Parse Resource to retrieve metadata. + + Args: + resource(): Resource object + + Returns: + Dict with resources attributes + """ logger.debug("retrieve elements from resource") - rc = {"address": data["address"], "actions": data["change"]["actions"]} + rc = { + "address": resource["address"], + "actions": resource["change"]["actions"], + } return rc def getAttributes(data): - """Get attributes from resource""" + """ + Get attributes from resource. + + Args: + data(list): list of resources + + Returns: + List of resources dict with attributes + """ resources = [] logger.debug("get attributes from resources") @@ -50,15 +99,25 @@ def getAttributes(data): def parsePlan(tfplan): - """Parse Terraform plan in JSON""" + """ + Parse Terraform plan in JSON. + + Args: + tfplan(dict): dict from json.load('') + + Returns: + List of resources dict with attributes + """ logger.debug("parsing file...") all_resources = getResourceChanges(tfplan) - # print(all_resources) + logger.debug(all_resources) resource_changing = filterNoOp(all_resources) - # print(resource_changing) + logger.debug(resource_changing) resources = getAttributes(resource_changing) - print(resources) + logger.debug(resources) + + return resources From c4d06ea5ea03c6ad37e4dc1c0b4f8494ff85c7e9 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Fri, 29 Jan 2021 09:08:40 +0000 Subject: [PATCH 16/18] Apply automatic changes --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aef2ed..e0907cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,12 @@ -## [0.1.4] - 2021-01-28 +## [0.1.4] - 2021-01-29 ### Chore - vscode settings for project ### Docs +- docstrings update - terraform link for json docs ### Feat From 2c38035ffceeeed8f5019071f96302c8eeb627aa Mon Sep 17 00:00:00 2001 From: Bruno Cochofel Date: Sat, 30 Jan 2021 13:53:51 +0000 Subject: [PATCH 17/18] feat(terraform): calculate resource name --- GitVersion.yml | 5 +++++ terraplanfeed/terraform.py | 44 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 GitVersion.yml diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000..0f67e0a --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,5 @@ +next-version: 0.1.0 +major-version-bump-message: '^?(BREAKING CHANGE|\+semver:\s?(breaking|major))' +minor-version-bump-message: '^?(feat.*:\s|\+semver:\s?(feature|minor))' +patch-version-bump-message: '^?(fix.*:\s|\+semver:\s?(fix|patch))' +no-bump-message: '\+semver:\s?(none|skip)' \ No newline at end of file diff --git a/terraplanfeed/terraform.py b/terraplanfeed/terraform.py index 6670d65..254870b 100644 --- a/terraplanfeed/terraform.py +++ b/terraplanfeed/terraform.py @@ -10,6 +10,7 @@ filterNoOp: filters out no-op actions from resource_changes parseResource: parses resource to get some metadata like, name, address + calculateName: tries to calculate resource name getAttributes: creates a list of resources with some attributes parsePlan: main function """ @@ -61,12 +62,50 @@ def filterNoOp(resources): return changes +def calculateName(resource): + """ + Tries to calculate the name of the resource. + + Args: + resource(dict): Resource object + + Returns: + String name + """ + + name = "" + beforeName = "" + afterName = "" + logger.debug("tries to calculate resource name") + if resource["change"]["before"] is not None: + if "name" in resource["change"]["before"]: + beforeName = resource["change"]["before"]["name"] + logger.debug("beforeName: %s", beforeName) + if resource["change"]["after"] is not None: + if "name" in resource["change"]["after"]: + afterName = resource["change"]["after"]["name"] + logger.debug("afterName: %s", afterName) + + if afterName and beforeName and (afterName != beforeName): + name = beforeName + " --> " + afterName + elif afterName and beforeName: + name = beforeName + elif beforeName and (afterName is not None): + name = beforeName + elif afterName and (beforeName is not None): + name = afterName + else: + name = "" + + return name + + def parseResource(resource): """ Parse Resource to retrieve metadata. Args: - resource(): Resource object + resource(dict): Resource object Returns: Dict with resources attributes @@ -74,8 +113,9 @@ def parseResource(resource): logger.debug("retrieve elements from resource") rc = { - "address": resource["address"], "actions": resource["change"]["actions"], + "name": calculateName(resource), + "address": resource["address"], } return rc From 0e094d08ef7e731ae09bf35043670deb5ba10b30 Mon Sep 17 00:00:00 2001 From: bcochofel Date: Sat, 30 Jan 2021 13:54:43 +0000 Subject: [PATCH 18/18] Apply automatic changes --- CHANGELOG.md | 9 +++++---- terraplanfeed/__init__.py | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0907cb..6e2c478 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ ## [Unreleased] - -## [0.1.4] - 2021-01-29 + +## [0.2.0] - 2021-01-30 ### Chore - vscode settings for project @@ -17,6 +17,7 @@ - terraform functions for filtering data - module structure - parse terraform plan +- **terraform:** calculate resource name ### Fix - validate json file @@ -71,8 +72,8 @@ - Merge pull request [#1](https://github.com/bcochofel/terraplanfeed/issues/1) from bcochofel/package_skel -[Unreleased]: https://github.com/bcochofel/terraplanfeed/compare/0.1.4...HEAD -[0.1.4]: https://github.com/bcochofel/terraplanfeed/compare/0.1.3...0.1.4 +[Unreleased]: https://github.com/bcochofel/terraplanfeed/compare/0.2.0...HEAD +[0.2.0]: https://github.com/bcochofel/terraplanfeed/compare/0.1.3...0.2.0 [0.1.3]: https://github.com/bcochofel/terraplanfeed/compare/0.1.2...0.1.3 [0.1.2]: https://github.com/bcochofel/terraplanfeed/compare/0.1.1...0.1.2 [0.1.1]: https://github.com/bcochofel/terraplanfeed/compare/0.1.0...0.1.1 diff --git a/terraplanfeed/__init__.py b/terraplanfeed/__init__.py index ef43649..04ebe48 100644 --- a/terraplanfeed/__init__.py +++ b/terraplanfeed/__init__.py @@ -7,4 +7,4 @@ Modules: terraform """ -__version__ = "0.1.4" +__version__ = "0.2.0"