From 540d4c2faa346c8e25b6300ec1b31704f1e95855 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Mon, 11 Jan 2021 14:34:50 +0000 Subject: [PATCH] Minimum Python >= 3.7, drop oyaml, add support for short intrinsic AWS functions --- CHANGES.md | 5 +++++ cloudbender/__init__.py | 2 +- cloudbender/stack.py | 17 +++++++++++++---- dev-requirements.txt | 1 - requirements.txt | 1 - setup.py | 3 ++- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 042d309..ba20e99 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Changelog +## 0.9.7 +- CloudBender now requires Python >= 3.7 +- drop oyaml requirement +- support for short intrinsic functions like !Ref, !Sub etc. by ignoring custom constructors before sending them to AWS to resolve + ## 0.9.6 - only upload templates if render is successful - support for jinja user-data diff --git a/cloudbender/__init__.py b/cloudbender/__init__.py index 6bb0dca..5a5a1e2 100644 --- a/cloudbender/__init__.py +++ b/cloudbender/__init__.py @@ -2,7 +2,7 @@ import logging __author__ = "Stefan Reimer" __email__ = "stefan@zero-downtimet.net" -__version__ = "0.9.6" +__version__ = "0.9.7" # Set up logging to ``/dev/null`` like a library is supposed to. diff --git a/cloudbender/stack.py b/cloudbender/stack.py index d524f52..6942189 100644 --- a/cloudbender/stack.py +++ b/cloudbender/stack.py @@ -1,7 +1,7 @@ import os import re import hashlib -import oyaml as yaml +import yaml import time import pathlib import pprint @@ -32,6 +32,15 @@ import logging logger = logging.getLogger(__name__) +# Ignore any ! during re-loading of CFN templates +class SafeLoaderIgnoreUnknown(yaml.SafeLoader): + def ignore_unknown(self, node): + return node.tag + + +SafeLoaderIgnoreUnknown.add_constructor(None, SafeLoaderIgnoreUnknown.ignore_unknown) + + class Stack(object): def __init__(self, name, template, path, rel_path, ctx): self.stackname = name @@ -135,7 +144,7 @@ class Stack(object): try: self.cfn_template = template.render(_config) - self.cfn_data = yaml.safe_load(self.cfn_template) + self.cfn_data = yaml.load(self.cfn_template, Loader=SafeLoaderIgnoreUnknown) except Exception as e: # In case we rendered invalid yaml this helps to debug if self.cfn_template: @@ -184,7 +193,7 @@ class Stack(object): logger.info("Piped mode: Added parameters for remote stack references") # Re-read updated template - self.cfn_data = yaml.safe_load(self.cfn_template) + self.cfn_data = yaml.load(self.cfn_template, Loader=SafeLoaderIgnoreUnknown) # Check for empty top level Parameters, Outputs and Conditions and remove for key in ['Parameters', 'Outputs', 'Conditions']: @@ -318,7 +327,7 @@ class Stack(object): logger.warn("Could not find template file: {}".format(yaml_file)) raise e - self.cfn_data = yaml.safe_load(self.cfn_template) + self.cfn_data = yaml.load(self.cfn_template, Loader=SafeLoaderIgnoreUnknown) self._parse_metadata() else: logger.debug('Using cached cfn template %s.', self.stackname) diff --git a/dev-requirements.txt b/dev-requirements.txt index 39f9a48..efafd58 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,6 +1,5 @@ boto3 Jinja2 -oyaml click pyminifier cfn-lint diff --git a/requirements.txt b/requirements.txt index 59a158f..3c1550d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ boto3 Jinja2 -oyaml click pyminifier cfn-lint>=0.34 diff --git a/setup.py b/setup.py index 9c30fcf..cf53429 100644 --- a/setup.py +++ b/setup.py @@ -47,6 +47,7 @@ setup( name='cloudbender', version=find_version("cloudbender/__init__.py"), description='Toolset to render and manage AWS Cloudformation', + python_requires='>=3.7', long_description=long_description, long_description_content_type="text/markdown", author='Stefan Reimer', @@ -56,7 +57,7 @@ setup( package_data={ 'cloudbender': ['templates/*.md'], }, include_package_data=True, entry_points={'console_scripts': [ "cloudbender = cloudbender.cli:cli" ]}, - install_requires=['boto3', 'Jinja2', 'oyaml', 'click', 'cfn-lint>=0.34', 'pyminifier'], + install_requires=['boto3', 'Jinja2', 'click', 'cfn-lint>=0.34', 'pyminifier'], tests_require=["pytest-cov", "moto", "mock", 'pytest'], cmdclass={"test": PyTest}, classifiers=[