Add notification_sns support, stack group option handling cleanup

This commit is contained in:
Stefan Reimer 2019-07-27 22:30:03 +00:00
parent c28d9c751d
commit 3fcca2b782
4 changed files with 27 additions and 28 deletions

View File

@ -1,5 +1,9 @@
# Changelog
## 0.7.0
- Add support for SNS Notifcations to Cloudformation create and update operations
- Refactored recursive handling of options withing stack groups
## 0.6.2
- Fixed custom root directory to allow automated template tests

View File

@ -2,7 +2,7 @@ import logging
__author__ = "Stefan Reimer"
__email__ = "stefan@zero-downtimet.net"
__version__ = "0.6.2"
__version__ = "0.7.0"
# Set up logging to ``/dev/null`` like a library is supposed to.

View File

@ -33,17 +33,23 @@ class StackStatus(object):
class Stack(object):
def __init__(self, name, path, rel_path, tags=None, parameters=None, options=None, region='global', profile=None, template=None, ctx={}):
self.id = (profile, region, name)
def __init__(self, name, template, path, rel_path, sg_config={}, ctx={}):
self.stackname = name
self.template = template
self.path = path
self.rel_path = rel_path
self.tags = tags
self.parameters = parameters
self.options = options
self.region = region
self.profile = profile
self.template = template
self.ctx = ctx
self.tags = sg_config.get('tags', {})
self.parameters = sg_config.get('parameters', {})
self.options = sg_config.get('options', {})
self.region = sg_config.get('region', 'global')
self.profile = sg_config.get('profile', '')
self.onfailure = sg_config.get('onfailure', "DELETE")
self.notfication_sns = sg_config.get('notification_sns', [])
self.id = (self.profile, self.region, self.stackname)
self.md5 = None
self.mode = 'CloudBender'
self.provides = template
@ -51,19 +57,17 @@ class Stack(object):
self.cfn_parameters = []
self.cfn_data = None
self.connection_manager = BotoConnection(self.profile, self.region)
self.ctx = ctx
self.status = None
self.dependencies = set()
self.default_lock = None
self.multi_delete = True
self.onfailure = "DELETE"
def dump_config(self):
logger.debug("<Stack {}: {}>".format(self.id, vars(self)))
def read_config(self):
_config = read_config_file(self.path)
for p in ["region", "stackname", "template", "default_lock", "multi_delete", "provides", "onfailure"]:
for p in ["region", "stackname", "template", "default_lock", "multi_delete", "provides", "onfailure", "notification_sns"]:
if p in _config:
setattr(self, p, _config[p])
@ -345,6 +349,7 @@ class Stack(object):
'TemplateBody': self.cfn_template,
'Parameters': self.cfn_parameters,
'OnFailure': self.onfailure,
'NotificationARNs': self.notfication_sns,
'Tags': [{"Key": str(k), "Value": str(v)} for k, v in self.tags.items()],
'Capabilities': ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND']},
profile=self.profile, region=self.region)
@ -366,6 +371,7 @@ class Stack(object):
{'StackName': self.stackname,
'TemplateBody': self.cfn_template,
'Parameters': self.cfn_parameters,
'NotificationARNs': self.notfication_sns,
'Tags': [{"Key": str(k), "Value": str(v)} for k, v in self.tags.items()],
'Capabilities': ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND']},
profile=self.profile, region=self.region)

View File

@ -26,7 +26,7 @@ class StackGroup(object):
for sg in self.sgs:
sg.dump_config()
logger.debug("<StackGroup {}: {}>".format(self.name, vars(self)))
logger.debug("<StackGroup {}: {}>".format(self.name, self.config))
for s in self.stacks:
s.dump_config()
@ -46,14 +46,9 @@ class StackGroup(object):
self.name = os.path.split(self.path)[1]
# Merge config with parent config
_config = dict_merge(parent_config, _config)
self.config = dict_merge(parent_config, _config)
tags = _config.get('tags', {})
parameters = _config.get('parameters', {})
options = _config.get('options', {})
region = _config.get('region', 'global')
profile = _config.get('profile', '')
stackname_prefix = _config.get('stacknameprefix', '')
stackname_prefix = self.config.get('stacknameprefix', '')
logger.debug("StackGroup {} added.".format(self.name))
@ -65,23 +60,17 @@ class StackGroup(object):
if stackname_prefix:
stackname = stackname_prefix + stackname
new_stack = Stack(
name=stackname, template=template, path=stack_path, rel_path=str(self.rel_path),
tags=dict(tags), parameters=dict(parameters), options=dict(options),
region=str(region), profile=str(profile), ctx=self.ctx)
new_stack = Stack(name=stackname, template=template, path=stack_path, rel_path=str(self.rel_path), sg_config=self.config, ctx=self.ctx)
new_stack.read_config()
self.stacks.append(new_stack)
# Create StackGroups recursively
for sub_group in [f.path for f in os.scandir(self.path) if f.is_dir()]:
sg = StackGroup(sub_group, self.ctx)
sg.read_config(_config)
sg.read_config(self.config)
self.sgs.append(sg)
# Return raw, merged config to parent
return _config
def get_stacks(self, name=None, recursive=True, match_by='name'):
""" Returns [stack] matching stack_name or [all] """
stacks = []