From a3f240ef026d0a97bef6b578adb74d4e10cca15d Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Mon, 21 Feb 2022 21:38:47 +0100 Subject: [PATCH] feat: implement todo identifiers (#246) --- .dictionary | 1 + README.md | 6 +- ansibledoctor/annotation.py | 23 ++-- ansibledoctor/config.py | 15 ++- ansibledoctor/doc_parser.py | 43 ++++++-- ansibledoctor/templates/hugo-book/_todo.j2 | 19 ++++ ansibledoctor/templates/hugo-book/index.md.j2 | 9 +- ansibledoctor/templates/readme/README.md.j2 | 9 +- ansibledoctor/templates/readme/_todo.j2 | 19 ++++ docs/content/_index.md | 4 +- docs/content/configuration/_index.md | 13 --- docs/content/configuration/cli.md | 33 ------ docs/content/configuration/defaults.md | 47 -------- docs/content/configuration/env.md | 24 ----- docs/content/setup/docker.md | 10 +- docs/content/setup/pip.md | 10 +- docs/content/usage/_index.md | 38 ------- docs/content/usage/configuration.md | 100 ++++++++++++++++++ docs/content/usage/getting-started.md | 84 +++++++++++++++ docs/data/menu/main.yml | 15 +-- example/README.md | 17 +-- example/demo-role/defaults/main.yml | 24 ++--- example/demo-role/meta/main.yml | 7 +- example/demo-role/tasks/main.yml | 9 ++ 24 files changed, 345 insertions(+), 234 deletions(-) create mode 100644 ansibledoctor/templates/hugo-book/_todo.j2 create mode 100644 ansibledoctor/templates/readme/_todo.j2 delete mode 100644 docs/content/configuration/_index.md delete mode 100644 docs/content/configuration/cli.md delete mode 100644 docs/content/configuration/defaults.md delete mode 100644 docs/content/configuration/env.md create mode 100644 docs/content/usage/configuration.md create mode 100644 docs/content/usage/getting-started.md diff --git a/.dictionary b/.dictionary index 339669d..8ac31f4 100644 --- a/.dictionary +++ b/.dictionary @@ -7,3 +7,4 @@ PyPI SELinux xoxys ansible-.+ +toc diff --git a/README.md b/README.md index 487a1bf..3711f15 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ Annotation based documentation for your Ansible roles This project is based on the idea (and at some parts on the code) of [ansible-autodoc](https://github.com/AndresBott/ansible-autodoc) by Andres Bott so credits goes to him for his work. -_ansible-doctor_ is a simple annotation like documentation generator based on Jinja2 templates. While _ansible-doctor_ comes with a default template called `readme`, it is also possible to write your own templates. This gives you the ability to customize the output and render the data to every format you like (e.g. HTML or XML). +_ansible-doctor_ is a simple annotation like documentation generator based on Jinja2 templates. While _ansible-doctor_ comes with a default template called `readme`, it is also possible to write custom templates to customize the output or render the data to other formats like HTML or XML as well. -_ansible-doctor_ is designed to work within your CI pipeline to complete your testing and deployment workflow. Releases are available as Python Packages on [GitHub](https://github.com/thegeeklab/ansible-doctor/releases) or [PyPI](https://pypi.org/project/ansible-doctor/) and as Docker Image on [Docker Hub](https://hub.docker.com/r/thegeeklab/ansible-doctor). +_ansible-doctor_ is designed to work within a CI pipeline to complete the existing testing and deployment workflow. Releases are available as Python Packages on [GitHub](https://github.com/thegeeklab/ansible-doctor/releases) or [PyPI](https://pypi.org/project/ansible-doctor/) and as Docker Image on [Docker Hub](https://hub.docker.com/r/thegeeklab/ansible-doctor). -You can find the full documentation at [https://ansible-doctor.geekdocs.de](https://ansible-doctor.geekdocs.de/). +The full documentation is available at [https://ansible-doctor.geekdocs.de](https://ansible-doctor.geekdocs.de/). ## Contributors diff --git a/ansibledoctor/annotation.py b/ansibledoctor/annotation.py index ece4dbb..a2c86c4 100644 --- a/ansibledoctor/annotation.py +++ b/ansibledoctor/annotation.py @@ -67,17 +67,28 @@ class Annotation: ) if item: self.logger.info(str(item)) - self._populate_item(item.get_obj().items()) + self._populate_item( + item.get_obj().items(), self._annotation_definition["name"] + ) num += 1 self._file_handler.close() - def _populate_item(self, item): + def _populate_item(self, item, name): + allow_multiple = self.config.ANNOTATIONS.get(name)["allow_multiple"] + for key, value in item: - try: - anyconfig.merge(self._all_items[key], value, ac_merge=anyconfig.MS_DICTS) - except ValueError as e: - self.log.sysexit_with_message("Unable to merge annotation values:\n{}".format(e)) + if allow_multiple: + if key not in self._all_items: + self._all_items[key] = [] + self._all_items[key].append(value) + else: + try: + anyconfig.merge(self._all_items[key], value, ac_merge=anyconfig.MS_DICTS) + except ValueError as e: + self.log.sysexit_with_message( + "Unable to merge annotation values:\n{}".format(e) + ) def _get_annotation_data(self, num, line, name, rfile): """ diff --git a/ansibledoctor/config.py b/ansibledoctor/config.py index 25844c8..c93edbf 100644 --- a/ansibledoctor/config.py +++ b/ansibledoctor/config.py @@ -109,27 +109,32 @@ class Config(): "meta": { "name": "meta", "automatic": True, - "subtypes": [] + "subtypes": ["value"], + "allow_multiple": False }, "todo": { "name": "todo", "automatic": True, - "subtypes": [] + "subtypes": ["value"], + "allow_multiple": True }, "var": { "name": "var", "automatic": True, - "subtypes": ["value", "example", "description"] + "subtypes": ["value", "example", "description"], + "allow_multiple": False }, "example": { "name": "example", "automatic": True, - "subtypes": [] + "subtypes": [], + "allow_multiple": False }, "tag": { "name": "tag", "automatic": True, - "subtypes": [] + "subtypes": [], + "allow_multiple": True }, } diff --git a/ansibledoctor/doc_parser.py b/ansibledoctor/doc_parser.py index 0d0b82d..18a4bd3 100644 --- a/ansibledoctor/doc_parser.py +++ b/ansibledoctor/doc_parser.py @@ -30,6 +30,22 @@ class Parser: self._parse_var_files() self._populate_doc_data() + def _yaml_remove_comments(self, d): + if isinstance(d, dict): + for k, v in d.items(): + self._yaml_remove_comments(k) + self._yaml_remove_comments(v) + elif isinstance(d, list): + for elem in d: + self._yaml_remove_comments(elem) + try: + attr = "comment" if isinstance( + d, ruamel.yaml.scalarstring.ScalarString + ) else ruamel.yaml.comments.Comment.attrib + delattr(d, attr) + except AttributeError: + pass + def _parse_var_files(self): for rfile in self._files_registry.get_files(): if any(fnmatch.fnmatch(rfile, "*/defaults/*." + ext) for ext in YAML_EXTENSIONS): @@ -40,8 +56,11 @@ class Parser: UnsafeTag.yaml_constructor, constructor=ruamel.yaml.SafeConstructor ) - loader = ruamel.yaml.YAML(typ="rt") - data = defaultdict(dict, (loader.load(yaml_file) or {})) + + raw = ruamel.yaml.YAML(typ="rt").load(yaml_file) + self._yaml_remove_comments(raw) + + data = defaultdict(dict, raw or {}) for key, value in data.items(): self._data["var"][key] = {"value": {key: value}} except ( @@ -58,7 +77,10 @@ class Parser: if any("meta/main." + ext in rfile for ext in YAML_EXTENSIONS): with open(rfile, "r", encoding="utf8") as yaml_file: try: - data = defaultdict(dict, ruamel.yaml.safe_load(yaml_file)) + raw = ruamel.yaml.YAML(typ="rt").load(yaml_file) + self._yaml_remove_comments(raw) + + data = defaultdict(dict, raw) if data.get("galaxy_info"): for key, value in data.get("galaxy_info").items(): self._data["meta"][key] = {"value": value} @@ -82,7 +104,10 @@ class Parser: if any(fnmatch.fnmatch(rfile, "*/tasks/*." + ext) for ext in YAML_EXTENSIONS): with open(rfile, "r", encoding="utf8") as yaml_file: try: - data = ruamel.yaml.safe_load(yaml_file) + raw = ruamel.yaml.YAML(typ="rt").load(yaml_file) + self._yaml_remove_comments(raw) + + data = defaultdict(dict, raw) except ( ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError ) as e: @@ -98,12 +123,12 @@ class Parser: def _populate_doc_data(self): """Generate the documentation data object.""" tags = defaultdict(dict) - for annotaion in self.config.get_annotations_names(automatic=True): - self.logger.info("Finding annotations for: @" + annotaion) - self._annotation_objs[annotaion] = Annotation( - name=annotaion, files_registry=self._files_registry + for annotation in self.config.get_annotations_names(automatic=True): + self.logger.info("Finding annotations for: @" + annotation) + self._annotation_objs[annotation] = Annotation( + name=annotation, files_registry=self._files_registry ) - tags[annotaion] = self._annotation_objs[annotaion].get_details() + tags[annotation] = self._annotation_objs[annotation].get_details() try: anyconfig.merge(self._data, tags, ac_merge=anyconfig.MS_DICTS) diff --git a/ansibledoctor/templates/hugo-book/_todo.j2 b/ansibledoctor/templates/hugo-book/_todo.j2 new file mode 100644 index 0000000..6bbee86 --- /dev/null +++ b/ansibledoctor/templates/hugo-book/_todo.j2 @@ -0,0 +1,19 @@ +{% set todo = role.todo | default({}) %} +{% if todo %} +## Open Tasks + +{% for key, item in todo | dictsort %} +{% for line in item %} +{% if line.value is defined and line.value | save_join(" ") | striptags and key == "default" %} +- {{ line.value | save_join(" ") | striptags }} +{% endif %} +{% endfor %} +{% endfor %} +{% for key, item in todo | dictsort %} +{% for line in item %} +{% if line.value is defined and line.value | save_join(" ") | striptags and key != "default" %} +- ({{ key }}): {{ line.value | save_join(" ") | striptags }} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} diff --git a/ansibledoctor/templates/hugo-book/index.md.j2 b/ansibledoctor/templates/hugo-book/index.md.j2 index 68cb306..806fbc7 100644 --- a/ansibledoctor/templates/hugo-book/index.md.j2 +++ b/ansibledoctor/templates/hugo-book/index.md.j2 @@ -11,10 +11,13 @@ type: docs {% endif %} {# TOC #} -{% include '_toc.j2' %} +{% include '_toc.j2' %} {# Vars #} -{% include '_vars.j2' %} +{% include '_vars.j2' %} + +{# Todo #} +{% include '_todo.j2' %} {# Meta #} -{% include '_meta.j2' %} +{% include '_meta.j2' %} diff --git a/ansibledoctor/templates/readme/README.md.j2 b/ansibledoctor/templates/readme/README.md.j2 index 85bd641..b4e66c2 100644 --- a/ansibledoctor/templates/readme/README.md.j2 +++ b/ansibledoctor/templates/readme/README.md.j2 @@ -8,10 +8,13 @@ {% endif %} {# TOC #} -{% include '_toc.j2' %} +{% include '_toc.j2' %} {# Vars #} -{% include '_vars.j2' %} +{% include '_vars.j2' %} + +{# Todo #} +{% include '_todo.j2' %} {# Meta #} -{% include '_meta.j2' %} +{% include '_meta.j2' %} diff --git a/ansibledoctor/templates/readme/_todo.j2 b/ansibledoctor/templates/readme/_todo.j2 new file mode 100644 index 0000000..6bbee86 --- /dev/null +++ b/ansibledoctor/templates/readme/_todo.j2 @@ -0,0 +1,19 @@ +{% set todo = role.todo | default({}) %} +{% if todo %} +## Open Tasks + +{% for key, item in todo | dictsort %} +{% for line in item %} +{% if line.value is defined and line.value | save_join(" ") | striptags and key == "default" %} +- {{ line.value | save_join(" ") | striptags }} +{% endif %} +{% endfor %} +{% endfor %} +{% for key, item in todo | dictsort %} +{% for line in item %} +{% if line.value is defined and line.value | save_join(" ") | striptags and key != "default" %} +- ({{ key }}): {{ line.value | save_join(" ") | striptags }} +{% endif %} +{% endfor %} +{% endfor %} +{% endif %} diff --git a/docs/content/_index.md b/docs/content/_index.md index fa3835a..9bfa96e 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -14,6 +14,6 @@ title: Documentation This project is based on the idea (and at some parts on the code) of [ansible-autodoc](https://github.com/AndresBott/ansible-autodoc) by Andres Bott so credits goes to him for his work. -_ansible-doctor_ is a simple annotation like documentation generator based on Jinja2 templates. While _ansible-doctor_ comes with a default template called `readme`, it is also possible to write your own templates. This gives you the ability to customize the output and render the data to every format you like (e.g. HTML or XML). +_ansible-doctor_ is a simple annotation like documentation generator based on Jinja2 templates. While _ansible-doctor_ comes with a default template called `readme`, it is also possible to write custom templates to customize the output or render the data to other formats like HTML or XML as well. -_ansible-doctor_ is designed to work within your CI pipeline to complete your testing and deployment workflow. Releases are available as Python Packages at [GitHub](https://github.com/thegeeklab/ansible-doctor/releases) or [PyPI](https://pypi.org/project/ansible-doctor/) and as Docker Image at [Docker Hub](https://hub.docker.com/r/thegeeklab/ansible-doctor). +_ansible-doctor_ is designed to work within a CI pipeline to complete the existing testing and deployment workflow. Releases are available as Python Packages on [GitHub](https://github.com/thegeeklab/ansible-doctor/releases) or [PyPI](https://pypi.org/project/ansible-doctor/) and as Docker Image on [Docker Hub](https://hub.docker.com/r/thegeeklab/ansible-doctor). diff --git a/docs/content/configuration/_index.md b/docs/content/configuration/_index.md deleted file mode 100644 index 1dc0445..0000000 --- a/docs/content/configuration/_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Configuration ---- - -_ansible-doctor_ comes with default settings which should be sufficient for most users to start, but you can adjust most settings to your needs. - -Changes can be made on different locations which will be processed in the following order (last wins): - -- default configuration (build-in) -- global configuration file (path depends on your operating system) -- folder-based configuration file (.ansibledoctor.yml|.ansibledoctor.yaml|.ansibledoctor) in current working directory -- environment variables -- CLI options diff --git a/docs/content/configuration/cli.md b/docs/content/configuration/cli.md deleted file mode 100644 index 48194ae..0000000 --- a/docs/content/configuration/cli.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: CLI options ---- - -You can get all available CLI options by running `ansible-doctor --help`: - - - -{{< highlight Shell "linenos=table" >}} -$ ansible-doctor --help -usage: ansible-doctor [-h] [-c CONFIG_FILE] [-o OUTPUT_DIR] [-f] [-d] [-n] [-v] [-q] [--version] [role_dir] - -Generate documentation from annotated Ansible roles using templates - -positional arguments: - role_dir role directory (default: current working dir) - -optional arguments: - -h, --help show this help message and exit - -c CONFIG_FILE, --config CONFIG_FILE - location of configuration file - -o OUTPUT_DIR, --output OUTPUT_DIR - output base dir - -f, --force force overwrite output file - -d, --dry-run dry run without writing - -n, --no-role-detection - disable automatic role detection - -v increase log level - -q decrease log level - --version show program's version number and exit -{{< /highlight >}} - - diff --git a/docs/content/configuration/defaults.md b/docs/content/configuration/defaults.md deleted file mode 100644 index 9418fe9..0000000 --- a/docs/content/configuration/defaults.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Default settings ---- - - - - -{{< highlight YAML "linenos=table" >}} ---- -# default is your current working dir -role_dir: -# default is the basename of 'role_name' -role_name: -# Auto-detect if the given directory is a role, can be disabled -# to parse loose files instead. -role_detection: True -# don't write anything to file system -dry_run: False - -logging: - # possible options debug | info | warning | error | critical - level: "warning" - # you can enable json logging if a parsable output is required - json: False - -# path to write rendered template file -# default is your current working dir -output_dir: -# default is in-build templates dir -template_dir: -template: readme - -# don't ask to overwrite if output file exists -force_overwrite: False -# load custom header from given file and append template output -# to it before write. -custom_header: "" - -exclude_files: [] -# Examples -# exclude_files: -# - molecule/ -# - files/**/*.py -{{< /highlight >}} - - - diff --git a/docs/content/configuration/env.md b/docs/content/configuration/env.md deleted file mode 100644 index 398d18b..0000000 --- a/docs/content/configuration/env.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Environment Variables ---- - - - -{{< highlight Shell "linenos=table" >}} -ANSIBLE_DOCTOR_CONFIG_FILE= -ANSIBLE_DOCTOR_ROLE_DETECTION=true -ANSIBLE_DOCTOR_ROLE_DIR= -ANSIBLE_DOCTOR_ROLE_NAME= -ANSIBLE_DOCTOR_DRY_RUN=false -ANSIBLE_DOCTOR_LOG_LEVEL=warning -ANSIBLE_DOCTOR_LOG_JSON=false -ANSIBLE_DOCTOR_OUTPUT_DIR= -ANSIBLE_DOCTOR_TEMPLATE_DIR= -ANSIBLE_DOCTOR_TEMPLATE=readme -ANSIBLE_DOCTOR_FORCE_OVERWRITE=false -ANSIBLE_DOCTOR_CUSTOM_HEADER= -ANSIBLE_DOCTOR_EXCLUDE_FILES= -ANSIBLE_DOCTOR_EXCLUDE_FILES=molecule/,files/**/*.py -{{< /highlight >}} - - diff --git a/docs/content/setup/docker.md b/docs/content/setup/docker.md index 318a0d7..44fbf26 100644 --- a/docs/content/setup/docker.md +++ b/docs/content/setup/docker.md @@ -2,9 +2,7 @@ title: Using docker --- - - -{{< highlight Shell "linenos=table" >}} +```Shell docker run \ -e ANSIBLE_DOCTOR_ROLE_DIR=example/demo-role/ \ -e ANSIBLE_DOCTOR_OUTPUT_DIR=example/ \ @@ -15,11 +13,9 @@ docker run \ -v $(pwd):/doctor \ -w /doctor \ thegeeklab/ansible-doctor -{{< /highlight >}} - - +``` {{< hint info >}} **Info**\ -Keep in mind, that you have to pass SELinux labels (:Z or :z) to your mount option if you are working on SELinux enabled systems. +Keep in mind, that SELinux labels (`:Z` or `:z`) need to be passed as mount option on SELinux enabled systems. {{< /hint >}} diff --git a/docs/content/setup/pip.md b/docs/content/setup/pip.md index 5be5015..57c3105 100644 --- a/docs/content/setup/pip.md +++ b/docs/content/setup/pip.md @@ -2,10 +2,7 @@ title: Using pip --- - - - -{{< highlight Shell "linenos=table" >}} +```Shell # From PyPI as unprivileged user $ pip install ansible-doctor --user @@ -14,7 +11,4 @@ $ sudo pip install ansible-doctor # From Wheel file $ pip install https://github.com/thegeeklab/ansible-doctor/releases/download/v0.1.1/ansible_doctor-0.1.1-py2.py3-none-any.whl -{{< /highlight >}} - - - +``` diff --git a/docs/content/usage/_index.md b/docs/content/usage/_index.md index 85530f7..6486c07 100644 --- a/docs/content/usage/_index.md +++ b/docs/content/usage/_index.md @@ -1,41 +1,3 @@ --- title: Usage --- - -```Shell -ansible-doctor FOLDER -``` - -If you don't pass a folder to _ansible-doctor_ your current working directory will be used. The first step is to identify if the given folder is an Ansible role. This check is very simple, if the folder contains a sub-directory called `tasks` is MUST be an Ansible role! :) - -After the successful check, _ansible-doctor_ will try to read some static files into a dictionary: - -- defaults/main.yml -- meta/main.yml - -This will be the base result set which is used as data source for every output template. Without any work, you will get at least a documentation about available variables and some meta information. Theses basic information can be expanded with a set of available annotations. In general, an annotation is a comment with an identifier. This identifier is followed by colon separated options and ends with a value. - - - - -{{< highlight Yaml "linenos=table" >}} -# @identifier option1:option2: - -# @var docker_registry_password:example: "%8gv_5GA?" -# @var docker_registry_password:description: Very secure password to login to the docker registry -# @var docker_registry_password:description: > -# You can also write it as multi line description -# Very secure password to login to the docker registry. -# @end -docker_registry_password: "secret" -{{< /highlight >}} - - - - -These list of predefined identifiers is currently available: - -- `@meta` -- `@todo` -- `@var` -- `@tag` diff --git a/docs/content/usage/configuration.md b/docs/content/usage/configuration.md new file mode 100644 index 0000000..2c3f275 --- /dev/null +++ b/docs/content/usage/configuration.md @@ -0,0 +1,100 @@ +--- +title: Configuration +--- + +_ansible-doctor_ comes with default settings which should be sufficient for most users to start, but most of the settings can be adjusted. + +{{< toc >}} + +Configuration options can be set in different places, which are processed in the following order (last wins): + +- Standard configuration (built-in) +- Global configuration file (the path depends on the operating system) +- Folder-based configuration file (`.ansibledoctor.yml|.ansibledoctor.yaml|.ansibledoctor`) in the current working directory +- Environment Variables +- CLI options + +## Defaults + +```YAML +--- +# default is the current working directory +role_dir: +# default is the basename of 'role_name' +role_name: +# Auto-detect if the given directory is a role, can be disabled +# to parse loose files instead. +role_detection: True +# don't write anything to file system +dry_run: False + +logging: + # possible options debug | info | warning | error | critical + level: "warning" + # json logging can be enabled if a parsable output is required + json: False + +# path to write rendered template file +# default is the current working directory +output_dir: +# default is in-build templates directory +template_dir: +template: readme + +# don't ask to overwrite if output file exists +force_overwrite: False +# load custom header from given file and append template output +# to it before write. +custom_header: "" + +exclude_files: [] +# Examples +# exclude_files: +# - molecule/ +# - files/**/*.py +``` + +## CLI + +```Shell +$ ansible-doctor --help +usage: ansible-doctor [-h] [-c CONFIG_FILE] [-o OUTPUT_DIR] [-f] [-d] [-n] [-v] [-q] [--version] [role_dir] + +Generate documentation from annotated Ansible roles using templates + +positional arguments: + role_dir role directory (default: current working dir) + +optional arguments: + -h, --help show this help message and exit + -c CONFIG_FILE, --config CONFIG_FILE + location of configuration file + -o OUTPUT_DIR, --output OUTPUT_DIR + output base dir + -f, --force force overwrite output file + -d, --dry-run dry run without writing + -n, --no-role-detection + disable automatic role detection + -v increase log level + -q decrease log level + --version show program's version number and exit +``` + +## Environment Variables + +```Shell +ANSIBLE_DOCTOR_CONFIG_FILE= +ANSIBLE_DOCTOR_ROLE_DETECTION=true +ANSIBLE_DOCTOR_ROLE_DIR= +ANSIBLE_DOCTOR_ROLE_NAME= +ANSIBLE_DOCTOR_DRY_RUN=false +ANSIBLE_DOCTOR_LOG_LEVEL=warning +ANSIBLE_DOCTOR_LOG_JSON=false +ANSIBLE_DOCTOR_OUTPUT_DIR= +ANSIBLE_DOCTOR_TEMPLATE_DIR= +ANSIBLE_DOCTOR_TEMPLATE=readme +ANSIBLE_DOCTOR_FORCE_OVERWRITE=false +ANSIBLE_DOCTOR_CUSTOM_HEADER= +ANSIBLE_DOCTOR_EXCLUDE_FILES= +ANSIBLE_DOCTOR_EXCLUDE_FILES=molecule/,files/**/*.py +``` diff --git a/docs/content/usage/getting-started.md b/docs/content/usage/getting-started.md new file mode 100644 index 0000000..319aff1 --- /dev/null +++ b/docs/content/usage/getting-started.md @@ -0,0 +1,84 @@ +--- +title: Getting Started +--- + +{{< toc >}} + +## Getting Started + +```Shell +ansible-doctor FOLDER +``` + +If no folder is passed to _ansible-doctor_, the current working directory is used. The first step is to determine if the specified folder is an Ansible role. This check is very simple and only verifies if there is a sub-directory named `tasks` in the specified folder. After a successful check, _ansible-doctor_ registers all files of the role to search them for annotations. + +Without any further work _ansible-doctor_ can already create a documentation of the available variables and some meta information if the role contains [meta information](https://galaxy.ansible.com/docs/contributing/creating_role.html#role-metadata). This basic information can be extended with a set of available annotations. + +## Annotations + +In general, an annotation is a comment with an identifier followed by colon separated options and a value. A [complex example](https://github.com/thegeeklab/ansible-doctor/tree/main/example) is available on the GitHub repository. + +### `@meta` + +Identifier to add role metadata information. The general structure for this identifier is `# @identifier option1: `. + +option1 +: scope that can be chosen freely, but the built-in template only handles a few scopes `["dependencies", "license", "author"]` + +**Example:** + +```YAML +# @meta description: > +# Role to demonstrate ansible-doctor. It is also possible to overwrite +# the default description with an annotation. +# @end + +# @meta author: [John Doe](https://blog.example.com) +``` + +### `@var` + +Identifier to add extra documentation to Ansible variables. The general structure for this identifier is `# @identifier option1:option2: `. + +option1 +: the name of the variable to which additional information should be added + +option2 +: supports `["value", "example", "description"]` as information scopes + +**Example:** + +```YAML +# @var docker_registry_password:value: "secure_overwrite" +# @var docker_registry_password: "secure_overwrite" + +# @var docker_registry_password:example: "%8gv_5GA?" + +# @var docker_registry_password:description: Very secure password to login to the docker registry. +# @var docker_registry_password:description: > +# Multi line description are possible as well. +# Very secure password to login to the docker registry. +# @end +docker_registry_password: "secret" +``` + +### `@todo` + +Identifier to open tasks that need to be addressed. The general structure for this identifier is `# @identifier option1: `. + +option1 +: scope that can be chosen freely, e.g. `bug`, `improvement` + +**Example:** + +```YAML +# @todo bug: Some bug that is known and need to be fixed. +# @todo bug: > +# Multi line description are possible as well. +# Some bug that is known and need to be fixed. +# @end + +# @todo improvement: Some things that need to be improved. + +# @todo default: Unscoped general todo. +``` diff --git a/docs/data/menu/main.yml b/docs/data/menu/main.yml index da79e25..19e81ce 100644 --- a/docs/data/menu/main.yml +++ b/docs/data/menu/main.yml @@ -6,14 +6,9 @@ main: ref: "/setup/pip" - name: Using docker ref: "/setup/docker" - - name: Configuration - ref: "/configuration" - sub: - - name: Default settings - ref: "/configuration/defaults" - - name: CLI options - ref: "/configuration/cli" - - name: Environment variables - ref: "/configuration/env" - name: Usage - ref: "/usage" + sub: + - name: Getting Started + ref: "/usage/getting-started" + - name: Configuration + ref: "/usage/configuration" diff --git a/example/README.md b/example/README.md index ed27639..a28b675 100644 --- a/example/README.md +++ b/example/README.md @@ -57,7 +57,7 @@ demo_role_empty: '' ### demo_role_empty_dict -... or you can use a valid json. In this case, the json will be automatically prefixed with the annotation key and you can use e.g. `to_nice_yaml` filter in your templates. To get this working, you have to prefix your json with a `$` char. +... or valid json can be used. In this case, the json will be automatically prefixed with the annotation key and filters like `to_nice_yaml` can be used in templates. To get it working, the json need to be prefixed with a `$`. #### Default value @@ -105,9 +105,7 @@ demo_role_single: b ### demo_role_undefined_var -If you want to add an explicit notice, that a var is not set by default, this is one option. Make sure to flag it as json value: `@var demo_role_undefined_var: $ "_unset_"` - -Test paragarph +To highlight a variable that has not set a value by default, this is one way to achieve it. Make sure to flag it as json value: `@var demo_role_undefined_var: $ "_unset_"` #### Default value @@ -117,7 +115,7 @@ demo_role_undefined_var: _unset_ ### demo_role_unset -You can set values as string, but there is no magic or autoformatting... +Values can be plain strings, but there is no magic or autoformatting... #### Default value @@ -131,6 +129,13 @@ demo_role_unset: demo_role_unset: some_value ``` +## Open Tasks + +- Unscoped general todo. +- (bug): Some bug that is known and need to be fixed. +- (bug): Multi line description are possible as well. Some bug that is known and need to be fixed. +- (improvement): Some things that need to be improved. + ## Dependencies None. @@ -141,4 +146,4 @@ MIT ## Author -Robert Kaussow +John Doe diff --git a/example/demo-role/defaults/main.yml b/example/demo-role/defaults/main.yml index bfe6896..b2763b2 100644 --- a/example/demo-role/defaults/main.yml +++ b/example/demo-role/defaults/main.yml @@ -1,5 +1,5 @@ --- -# @var demo_role_unset:description: You can set values as string, but there is no magic or autoformatting... +# @var demo_role_unset:description: Values can be plain strings, but there is no magic or autoformatting... # @var demo_role_unset:example: demo_role_unset: some_value demo_role_unset: @@ -7,10 +7,8 @@ demo_role_empty: "" demo_role_single: "b" # @var demo_role_empty_dict:description: > -# ... or you can use a valid json. In this case, -# the json will be automatically prefixed with the annotation key -# and you can use e.g. `to_nice_yaml` filter in your templates. -# To get this working, you have to prefix your json with a `$` char. +# ... or valid json can be used. In this case, the json will be automatically prefixed with the annotation key +# and filters like `to_nice_yaml` can be used in templates. To get it working, the json need to be prefixed with a `$`. # @end # @var demo_role_empty_dict:example: $ {"key1": {"sub": "some value"}, "key2": {"sublist": ["subval1", "subval2"]}} demo_role_empty_dict: {} @@ -30,9 +28,14 @@ demo_role_dict: key1: sub: some value +# @var demo_role_undefined_var:description: > +# To highlight a variable that has not set a value by default, this is one way to achieve it. +# Make sure to flag it as json value: `@var demo_role_undefined_var: $ "_unset_"` +# @end +# @var demo_role_undefined_var: $ "_unset_" + # @var demo_role_other_tags:description: > -# If a variable need some more explanation, -# this is a good place to do so. +# If a variable need some more explanation, this is a good place to do so. # @end # @var demo_role_other_tags:example: $> # [ @@ -41,10 +44,3 @@ demo_role_dict: # ] # @end demo_role_other_tags: [] -# @var demo_role_undefined_var:description: > -# If you want to add an explicit notice, that a var is not set by default, this is one option. -# Make sure to flag it as json value: `@var demo_role_undefined_var: $ "_unset_"` -# -# Test paragarph -# @end -# @var demo_role_undefined_var: $ "_unset_" diff --git a/example/demo-role/meta/main.yml b/example/demo-role/meta/main.yml index 133222a..932da90 100644 --- a/example/demo-role/meta/main.yml +++ b/example/demo-role/meta/main.yml @@ -1,11 +1,12 @@ --- # @meta description: > -# Role to demonstrate ansible-doctor. It is also possible to overwrite -# the default description with an annotation. +# Role to demonstrate ansible-doctor. It is also possible to overwrite +# the default description with an annotation. # @end +# @meta author: [John Doe](https://blog.example.com) galaxy_info: description: Role to demonstrate ansible-doctor. - author: Robert Kaussow + author: John Doe license: MIT min_ansible_version: 2.4 platforms: diff --git a/example/demo-role/tasks/main.yml b/example/demo-role/tasks/main.yml index ed97d53..c558725 100644 --- a/example/demo-role/tasks/main.yml +++ b/example/demo-role/tasks/main.yml @@ -1 +1,10 @@ --- +# @todo bug: Some bug that is known and need to be fixed. +# @todo bug: > +# Multi line description are possible as well. +# Some bug that is known and need to be fixed. +# @end + +# @todo improvement: Some things that need to be improved. + +# @todo default: Unscoped general todo.