From 80e8ff9463b589a34ac2e3c6282e2a41036c1744 Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Tue, 25 Feb 2020 20:40:12 +0000 Subject: [PATCH] New outputs function --- CHANGES.md | 3 +++ cloudbender/__init__.py | 2 +- cloudbender/cli.py | 15 +++++++++++++++ cloudbender/stack.py | 24 ++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d2eaf47..417c677 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # Changelog +## 0.7.8 +- Add new function `outputs`, to query already deployed stack for their outputs + ## 0.7.7 - Add support for CLOUDBENDER_PROJECT_ROOT env variable to specify your root project - Switch most os.path operations to pathlib to fix various corner cases caused by string matching diff --git a/cloudbender/__init__.py b/cloudbender/__init__.py index 676b45b..edb3b34 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.7.7" +__version__ = "0.7.8" # Set up logging to ``/dev/null`` like a library is supposed to. diff --git a/cloudbender/cli.py b/cloudbender/cli.py index 8712fbb..b026894 100644 --- a/cloudbender/cli.py +++ b/cloudbender/cli.py @@ -80,6 +80,20 @@ def validate(cb, stack_names, multi): s.validate() +@click.command() +@click.argument("stack_names", nargs=-1) +@click.option("--multi", is_flag=True, help="Allow more than one stack to match") +@click.option("--include", default='.*', help="regex matching wanted outputs, default '.*'") +@click.option("--values", is_flag=True, help="Only output values, most useful if only one outputs is returned") +@click.pass_obj +def outputs(cb, stack_names, multi, include, values): + """ Prints all stack outputs """ + + stacks = _find_stacks(cb, stack_names, multi) + for s in stacks: + s.get_outputs(include, values) + + @click.command() @click.argument("stack_name") @click.argument("change_set_name") @@ -225,6 +239,7 @@ cli.add_command(provision) cli.add_command(delete) cli.add_command(clean) cli.add_command(create_change_set) +cli.add_command(outputs) if __name__ == '__main__': cli(obj={}) diff --git a/cloudbender/stack.py b/cloudbender/stack.py index 7bf4a21..4ae3312 100644 --- a/cloudbender/stack.py +++ b/cloudbender/stack.py @@ -292,6 +292,30 @@ class Stack(object): else: logger.info("Passed.") + def get_outputs(self, include='.*', values=False): + """ Returns outputs of the stack as key=value """ + + try: + stacks = self.connection_manager.call( + "cloudformation", + "describe_stacks", + {'StackName': self.stackname}, + profile=self.profile, region=self.region)['Stacks'] + + try: + logger.debug("Stack outputs for {} in {}:".format(self.stackname, self.region)) + for output in stacks[0]['Outputs']: + if re.search(include, output['OutputKey']): + if values: + print("{}".format(output['OutputValue'])) + else: + print("{}={}".format(output['OutputKey'], output['OutputValue'])) + except KeyError: + pass + + except ClientError as e: + raise e + def resolve_parameters(self): """ Renders parameters for the stack based on the source template and the environment configuration """