From e0c724c68f3d3f69f3eae09c0da9cb2cf0f8f21e Mon Sep 17 00:00:00 2001 From: Stefan Reimer Date: Tue, 5 Jul 2022 16:56:59 +0200 Subject: [PATCH] feat: remove graph feature, write Pulumi docs to file --- cloudbender/cli.py | 5 +-- cloudbender/stack.py | 65 ++++++++---------------------- cloudbender/templates/stack-doc.md | 12 +++--- 3 files changed, 26 insertions(+), 56 deletions(-) diff --git a/cloudbender/cli.py b/cloudbender/cli.py index 6aca635..2031d89 100644 --- a/cloudbender/cli.py +++ b/cloudbender/cli.py @@ -155,14 +155,13 @@ def outputs(cb, stack_names, multi, include, values): @click.command() @click.argument("stack_names", nargs=-1) @click.option("--multi", is_flag=True, help="Allow more than one stack to match") -@click.option("--graph", is_flag=True, help="Create Dot Graph file") @click.pass_obj -def docs(cb, stack_names, multi, graph): +def docs(cb, stack_names, multi): """Outputs docs for stack(s). For Pulumi stacks prints out docstring. For CloudFormation templates render a markdown file. Same idea as helm-docs.""" stacks = _find_stacks(cb, stack_names, multi) for s in stacks: - s.docs(graph=graph) + s.docs() @click.command() diff --git a/cloudbender/stack.py b/cloudbender/stack.py index 6db71b1..8036769 100644 --- a/cloudbender/stack.py +++ b/cloudbender/stack.py @@ -25,7 +25,6 @@ from .pulumi import pulumi_ws, resolve_outputs import cfnlint.core import cfnlint.template -import cfnlint.graph from . import templates @@ -580,11 +579,17 @@ class Stack(object): ) @pulumi_ws - def docs(self, template=False, graph=False): + def docs(self, template=False): """Read rendered template, parse documentation fragments, eg. parameter description and create a mardown doc file for the stack. Same idea as helm-docs for the values.yaml """ + doc_file = os.path.join( + self.ctx["docs_path"], self.rel_path, self.stackname + ".md" + ) + ensure_dir(os.path.join(self.ctx["docs_path"], self.rel_path)) + + # For pulumi we use the embedded docstrings if self.mode == "pulumi": try: pulumi_stack = self._get_pulumi_stack() @@ -594,26 +599,23 @@ class Stack(object): pass if vars(self._pulumi_code)["__doc__"]: - output = render_docs( + docs_out = render_docs( vars(self._pulumi_code)["__doc__"], resolve_outputs(outputs) ) else: - output = "No template documentation found." + docs_out = "No stack documentation available." # collect all __doc__ from available _execute_ functions headerAdded = False for k in vars(self._pulumi_code).keys(): if k.startswith("_execute_"): if not headerAdded: - output = output + "\n# Available `execute` functions: \n" + docs_out = docs_out + "\n# Available *execute* functions: \n" headerAdded = True docstring = vars(self._pulumi_code)[k].__doc__ - output = output + "\n* {}\n{}".format( - k.lstrip("_execute_"), docstring - ) - - print(output) + docs_out = docs_out + f"\n* {docstring}" + # Cloudformation we use the stack-doc template similar to helm-docs else: try: self.read_template_file() @@ -655,45 +657,12 @@ class Stack(object): except (FileNotFoundError, KeyError, TypeError): pass - doc_file = os.path.join( - self.ctx["docs_path"], self.rel_path, self.stackname + ".md" - ) - ensure_dir(os.path.join(self.ctx["docs_path"], self.rel_path)) + docs_out = template.render(**data) - with open(doc_file, "w") as doc_contents: - doc_contents.write(template.render(**data)) - logger.info( - "Wrote documentation for %s to %s", self.stackname, doc_file - ) - - # Write Graph in Dot format - if graph: - filename = os.path.join( - self.ctx["template_path"], self.rel_path, self.stackname + ".yaml" - ) - - lint_args = ["--template", filename] - (args, filenames, formatter) = cfnlint.core.get_args_filenames( - lint_args - ) - (template, rules, matches) = cfnlint.core.get_template_rules( - filename, args - ) - template_obj = cfnlint.template.Template( - filename, template, [self.region] - ) - - path = os.path.join( - self.ctx["docs_path"], self.rel_path, self.stackname + ".dot" - ) - g = cfnlint.graph.Graph(template_obj) - try: - g.to_dot(path) - logger.info("DOT representation of the graph written to %s", path) - except ImportError: - logger.error( - "Could not write the graph in DOT format. Please install either `pygraphviz` or `pydot` modules." - ) + # Finally write docs to file + with open(doc_file, "w") as doc_contents: + doc_contents.write(docs_out) + logger.info("Wrote documentation for %s to %s", self.stackname, doc_file) def resolve_parameters(self): """Renders parameters for the stack based on the source template and the environment configuration""" diff --git a/cloudbender/templates/stack-doc.md b/cloudbender/templates/stack-doc.md index b7d5d0c..ea8b040 100644 --- a/cloudbender/templates/stack-doc.md +++ b/cloudbender/templates/stack-doc.md @@ -14,15 +14,17 @@ | Parameter | Type | Default | Format | Description | set value @ {{ timestamp }} | |-----------|------|---------|--------|-------------|-------------------------| {% for p in parameters.keys() %} -{% if parameters[p]['AllowedValues'] or parameters[p]['AllowedPattern'] %} -{% set format = '`%s%s`' % (parameters[p]['AllowedValues'], parameters[p]['AllowedPattern']) %} +{% if 'AllowedValues' in parameters[p] or 'AllowedPattern' in parameters[p] %} +{% set format = '`%s%s`' % (parameters[p].get('AllowedValues', ""), parameters[p].get('AllowedPattern', "")) %} {% endif %} -{% if parameters[p]['Default'] and parameters[p]['Type'].lower() == "string" %} +{% if 'Default' in parameters[p] %} +{% if parameters[p]['Type'].lower() == "string" %} {% set def = '`"%s"`' % parameters[p]['Default'] %} {% else %} {% set def = parameters[p]['Default'] %} {% endif %} -| {{ p }} | {{ parameters[p]['Type'] | lower }} | {{ def }} | {{ format }} | {{ parameters[p]['Description'] }} | {{ parameters[p]['value'] }} | +{% endif %} +| {{ p }} | {{ parameters[p]['Type'] | lower }} | {{ def | d("") }} | {{ format | d("") }} | {{ parameters[p]['Description'] }} | {{ parameters[p]['value'] | d("") }} | {% endfor %} {% endif %} @@ -31,6 +33,6 @@ | Output | Description | Value @ {{ timestamp }} | |--------|-------------|-------------------------| {% for p in outputs.keys() | sort%} -| {{ p }} | {{ outputs[p]['Description'] }} | {{ outputs[p]['last_value'] }} | +| {{ p }} | {{ outputs[p]['Description'] }} | {{ outputs[p]['last_value'] | d("") }} | {% endfor %} {% endif %}