Created
February 15, 2021 15:48
-
-
Save reinhrst/6bac4497f06efc3198fc0bb4d9e29a03 to your computer and use it in GitHub Desktop.
GetStack helper file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Run as "python getstack.py #filename#", it prints a filename on stdout that contains | |
| # the stack in #filename# with some edits | |
| # Useful in a commandline such as: | |
| # aws cloudformation update-stack --stack-name MyStack --template-body file://$(python getstack.py stack/stack.yaml) --parameters ParameterKey=XXXX,ParameterValue=YYYY --capabilities CAPABILITY_IAM | |
| # The following tags are supported | |
| # Note that all filenames used are relative to the location of the file that contains | |
| # the filename | |
| # All files are expected to have utf-8 encoding | |
| # | |
| # ---- __INCLUDE__: #includefilename# ---- | |
| # Should appear on a line by itself | |
| # the #includefilename# will be included in this script (recursively processed itself) | |
| # and indented by the number of spaces before the __INCLUDE__: | |
| # Note that a number may follow the __INCLUDE__ in order to make the tags unique | |
| # This is not a requirement but some YAML editors will complain if you have two | |
| # __INCLUDE__ keys at the same level, so you can use __INCLUDE__1, __INCLUDE__2, etc | |
| # | |
| # --- !!TIMESTAMP!! -- | |
| # This string is replaced by an identifierfriendly timestamp (e.g. 20210103T120354Z) | |
| # There is a guarantee that the same timestamp is used everywhere in the file | |
| from __future__ import annotations | |
| import datetime | |
| import logging | |
| import pathlib | |
| import re | |
| import tempfile | |
| logger = logging.getLogger() | |
| IMPORT_RE = re.compile( | |
| r"^(?P<indent> +)__INCLUDE__\d*: (?P<filename>.+)$", re.MULTILINE) | |
| def importfile(indent: int, filename: pathlib.Path) -> str: | |
| assert filename.is_absolute() | |
| data = process_file(filename) | |
| lines = [(" " * indent) + line if line else "" for line in data.split("\n")] | |
| return "\n".join(lines) | |
| def process_file(filename: pathlib.Path) -> str: | |
| logger.info('Processing %s', filename) | |
| assert filename.is_absolute() | |
| filepath = filename.parent | |
| data = filename.read_text(encoding="utf-8") | |
| return IMPORT_RE.sub( | |
| lambda match: importfile( | |
| len(match.group("indent")), | |
| (filepath / match.group("filename")).resolve()), | |
| data) | |
| if __name__ == "__main__": | |
| logging.basicConfig(level=logging.DEBUG) | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("filename") | |
| args = parser.parse_args() | |
| absolute_filename = pathlib.Path(args.filename).resolve() | |
| processed_stack = process_file(absolute_filename) | |
| processed_stack = processed_stack.replace( | |
| "!!TIMESTAMP!!", datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")) | |
| tmpfile = tempfile.NamedTemporaryFile( | |
| mode="wt", encoding="utf-8", suffix="-" + absolute_filename.name, delete=False) | |
| tmpfile.write(processed_stack) | |
| logger.info("Wrote %s", tmpfile.name) | |
| print(tmpfile.name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment