feat: implement todo identifiers (#246)

This commit is contained in:
Robert Kaussow 2022-02-21 21:38:47 +01:00 committed by GitHub
parent 5081356781
commit a3f240ef02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 345 additions and 234 deletions

View File

@ -7,3 +7,4 @@ PyPI
SELinux
xoxys
ansible-.+
toc

View File

@ -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

View File

@ -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:
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))
self.log.sysexit_with_message(
"Unable to merge annotation values:\n{}".format(e)
)
def _get_annotation_data(self, num, line, name, rfile):
"""

View File

@ -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
},
}

View File

@ -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)

View File

@ -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 %}

View File

@ -16,5 +16,8 @@ type: docs
{# Vars #}
{% include '_vars.j2' %}
{# Todo #}
{% include '_todo.j2' %}
{# Meta #}
{% include '_meta.j2' %}

View File

@ -13,5 +13,8 @@
{# Vars #}
{% include '_vars.j2' %}
{# Todo #}
{% include '_todo.j2' %}
{# Meta #}
{% include '_meta.j2' %}

View File

@ -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 %}

View File

@ -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).

View File

@ -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

View File

@ -1,33 +0,0 @@
---
title: CLI options
---
You can get all available CLI options by running `ansible-doctor --help`:
<!-- prettier-ignore-start -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- prettier-ignore-end -->

View File

@ -1,47 +0,0 @@
---
title: Default settings
---
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

View File

@ -1,24 +0,0 @@
---
title: Environment Variables
---
<!-- prettier-ignore-start -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- prettier-ignore-end -->

View File

@ -2,9 +2,7 @@
title: Using docker
---
<!-- prettier-ignore-start -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- prettier-ignore-end -->
```
{{< 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 >}}

View File

@ -2,10 +2,7 @@
title: Using pip
---
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< 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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
```

View File

@ -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.
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<!-- spellchecker-disable -->
{{< highlight Yaml "linenos=table" >}}
# @identifier option1:option2: <value>
# @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 >}}
<!-- spellchecker-enable -->
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
These list of predefined identifiers is currently available:
- `@meta`
- `@todo`
- `@var`
- `@tag`

View File

@ -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
```

View File

@ -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: <value>`.
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: <value>`.
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: <value>`.
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.
```

View File

@ -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"

View File

@ -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 <mail@example.com>
John Doe

View File

@ -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_"

View File

@ -3,9 +3,10 @@
# 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 <mail@example.com>
author: John Doe
license: MIT
min_ansible_version: 2.4
platforms:

View File

@ -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.