diff --git a/README.md b/README.md index f0977da..18185f0 100644 --- a/README.md +++ b/README.md @@ -27,5 +27,6 @@ Commands: delete Deletes stacks or stack groups provision Creates or updates stacks or stack groups render Renders template and its parameters + sync Renders template and provisions it right away validate Validates already rendered templates using cfn-lint ``` diff --git a/cloudbender/cli.py b/cloudbender/cli.py index acb5ccc..36877c2 100644 --- a/cloudbender/cli.py +++ b/cloudbender/cli.py @@ -36,12 +36,37 @@ def render(cb, stack_names, multi): """ Renders template and its parameters """ stacks = _find_stacks(cb, stack_names, multi) - for s in stacks: s.render() s.write_template_file() +@click.command() +@click.argument("stack_names", nargs=-1) +@click.option("--multi", is_flag=True, help="Allow more than one stack to match") +@click.pass_obj +def sync(cb, stack_names, multi): + """ Renders template and provisions it right away """ + + stacks = _find_stacks(cb, stack_names, multi) + for step in sort_stacks(cb, stacks): + if step: + with ThreadPoolExecutor(max_workers=len(step)) as group: + futures = [] + for stack in step: + stack.render() + stack.write_template_file() + + status = stack.get_status() + if not status: + futures.append(group.submit(stack.create)) + else: + futures.append(group.submit(stack.update)) + + for future in as_completed(futures): + future.result() + + @click.command() @click.argument("stack_names", nargs=-1) @click.option("--multi", is_flag=True, help="Allow more than one stack to match") @@ -182,6 +207,7 @@ def _find_stacks(cb, stack_names, multi=False): cli.add_command(render) +cli.add_command(sync) cli.add_command(validate) cli.add_command(provision) cli.add_command(delete) diff --git a/cloudbender/stack.py b/cloudbender/stack.py index 003c066..45e0cc5 100644 --- a/cloudbender/stack.py +++ b/cloudbender/stack.py @@ -93,10 +93,16 @@ class Stack(object): 'CloudBender.Version': __version__ } - jenv.globals['_config'] = {'cfn': self.template_vars, 'Metadata': template_metadata} + cb = False + if self.template_vars['Mode'] == "CloudBender": + cb = True + + _config = {'cb': cb, 'cfn': self.template_vars, 'Metadata': template_metadata} + + jenv.globals['_config'] = _config # First render pass to calculate a md5 checksum - template_metadata['Template.Hash'] = hashlib.md5(template.render({'cfn': self.template_vars, 'Metadata': template_metadata}).encode('utf-8')).hexdigest() + template_metadata['Template.Hash'] = hashlib.md5(template.render(_config).encode('utf-8')).hexdigest() # Reset and set Metadata for final render pass jenv.globals['get_custom_att'](context={'_config': self.template_vars}, reset=True) @@ -113,7 +119,7 @@ class Stack(object): pass logger.info('Rendering %s', template.filename) - rendered = template.render({'cfn': self.template_vars, 'Metadata': template_metadata}) + rendered = template.render(_config) try: self.data = yaml.load(rendered)