mirror of
https://github.com/thegeeklab/ansible-doctor.git
synced 2024-11-21 20:30:43 +00:00
feat: implement todo identifiers (#246)
This commit is contained in:
parent
5081356781
commit
a3f240ef02
@ -7,3 +7,4 @@ PyPI
|
|||||||
SELinux
|
SELinux
|
||||||
xoxys
|
xoxys
|
||||||
ansible-.+
|
ansible-.+
|
||||||
|
toc
|
||||||
|
@ -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.
|
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
|
## Contributors
|
||||||
|
|
||||||
|
@ -67,17 +67,28 @@ class Annotation:
|
|||||||
)
|
)
|
||||||
if item:
|
if item:
|
||||||
self.logger.info(str(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
|
num += 1
|
||||||
|
|
||||||
self._file_handler.close()
|
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:
|
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:
|
try:
|
||||||
anyconfig.merge(self._all_items[key], value, ac_merge=anyconfig.MS_DICTS)
|
anyconfig.merge(self._all_items[key], value, ac_merge=anyconfig.MS_DICTS)
|
||||||
except ValueError as e:
|
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):
|
def _get_annotation_data(self, num, line, name, rfile):
|
||||||
"""
|
"""
|
||||||
|
@ -109,27 +109,32 @@ class Config():
|
|||||||
"meta": {
|
"meta": {
|
||||||
"name": "meta",
|
"name": "meta",
|
||||||
"automatic": True,
|
"automatic": True,
|
||||||
"subtypes": []
|
"subtypes": ["value"],
|
||||||
|
"allow_multiple": False
|
||||||
},
|
},
|
||||||
"todo": {
|
"todo": {
|
||||||
"name": "todo",
|
"name": "todo",
|
||||||
"automatic": True,
|
"automatic": True,
|
||||||
"subtypes": []
|
"subtypes": ["value"],
|
||||||
|
"allow_multiple": True
|
||||||
},
|
},
|
||||||
"var": {
|
"var": {
|
||||||
"name": "var",
|
"name": "var",
|
||||||
"automatic": True,
|
"automatic": True,
|
||||||
"subtypes": ["value", "example", "description"]
|
"subtypes": ["value", "example", "description"],
|
||||||
|
"allow_multiple": False
|
||||||
},
|
},
|
||||||
"example": {
|
"example": {
|
||||||
"name": "example",
|
"name": "example",
|
||||||
"automatic": True,
|
"automatic": True,
|
||||||
"subtypes": []
|
"subtypes": [],
|
||||||
|
"allow_multiple": False
|
||||||
},
|
},
|
||||||
"tag": {
|
"tag": {
|
||||||
"name": "tag",
|
"name": "tag",
|
||||||
"automatic": True,
|
"automatic": True,
|
||||||
"subtypes": []
|
"subtypes": [],
|
||||||
|
"allow_multiple": True
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,22 @@ class Parser:
|
|||||||
self._parse_var_files()
|
self._parse_var_files()
|
||||||
self._populate_doc_data()
|
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):
|
def _parse_var_files(self):
|
||||||
for rfile in self._files_registry.get_files():
|
for rfile in self._files_registry.get_files():
|
||||||
if any(fnmatch.fnmatch(rfile, "*/defaults/*." + ext) for ext in YAML_EXTENSIONS):
|
if any(fnmatch.fnmatch(rfile, "*/defaults/*." + ext) for ext in YAML_EXTENSIONS):
|
||||||
@ -40,8 +56,11 @@ class Parser:
|
|||||||
UnsafeTag.yaml_constructor,
|
UnsafeTag.yaml_constructor,
|
||||||
constructor=ruamel.yaml.SafeConstructor
|
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():
|
for key, value in data.items():
|
||||||
self._data["var"][key] = {"value": {key: value}}
|
self._data["var"][key] = {"value": {key: value}}
|
||||||
except (
|
except (
|
||||||
@ -58,7 +77,10 @@ class Parser:
|
|||||||
if any("meta/main." + ext in rfile for ext in YAML_EXTENSIONS):
|
if any("meta/main." + ext in rfile for ext in YAML_EXTENSIONS):
|
||||||
with open(rfile, "r", encoding="utf8") as yaml_file:
|
with open(rfile, "r", encoding="utf8") as yaml_file:
|
||||||
try:
|
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"):
|
if data.get("galaxy_info"):
|
||||||
for key, value in data.get("galaxy_info").items():
|
for key, value in data.get("galaxy_info").items():
|
||||||
self._data["meta"][key] = {"value": value}
|
self._data["meta"][key] = {"value": value}
|
||||||
@ -82,7 +104,10 @@ class Parser:
|
|||||||
if any(fnmatch.fnmatch(rfile, "*/tasks/*." + ext) for ext in YAML_EXTENSIONS):
|
if any(fnmatch.fnmatch(rfile, "*/tasks/*." + ext) for ext in YAML_EXTENSIONS):
|
||||||
with open(rfile, "r", encoding="utf8") as yaml_file:
|
with open(rfile, "r", encoding="utf8") as yaml_file:
|
||||||
try:
|
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 (
|
except (
|
||||||
ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError
|
ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError
|
||||||
) as e:
|
) as e:
|
||||||
@ -98,12 +123,12 @@ class Parser:
|
|||||||
def _populate_doc_data(self):
|
def _populate_doc_data(self):
|
||||||
"""Generate the documentation data object."""
|
"""Generate the documentation data object."""
|
||||||
tags = defaultdict(dict)
|
tags = defaultdict(dict)
|
||||||
for annotaion in self.config.get_annotations_names(automatic=True):
|
for annotation in self.config.get_annotations_names(automatic=True):
|
||||||
self.logger.info("Finding annotations for: @" + annotaion)
|
self.logger.info("Finding annotations for: @" + annotation)
|
||||||
self._annotation_objs[annotaion] = Annotation(
|
self._annotation_objs[annotation] = Annotation(
|
||||||
name=annotaion, files_registry=self._files_registry
|
name=annotation, files_registry=self._files_registry
|
||||||
)
|
)
|
||||||
tags[annotaion] = self._annotation_objs[annotaion].get_details()
|
tags[annotation] = self._annotation_objs[annotation].get_details()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
anyconfig.merge(self._data, tags, ac_merge=anyconfig.MS_DICTS)
|
anyconfig.merge(self._data, tags, ac_merge=anyconfig.MS_DICTS)
|
||||||
|
19
ansibledoctor/templates/hugo-book/_todo.j2
Normal file
19
ansibledoctor/templates/hugo-book/_todo.j2
Normal 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 %}
|
@ -16,5 +16,8 @@ type: docs
|
|||||||
{# Vars #}
|
{# Vars #}
|
||||||
{% include '_vars.j2' %}
|
{% include '_vars.j2' %}
|
||||||
|
|
||||||
|
{# Todo #}
|
||||||
|
{% include '_todo.j2' %}
|
||||||
|
|
||||||
{# Meta #}
|
{# Meta #}
|
||||||
{% include '_meta.j2' %}
|
{% include '_meta.j2' %}
|
||||||
|
@ -13,5 +13,8 @@
|
|||||||
{# Vars #}
|
{# Vars #}
|
||||||
{% include '_vars.j2' %}
|
{% include '_vars.j2' %}
|
||||||
|
|
||||||
|
{# Todo #}
|
||||||
|
{% include '_todo.j2' %}
|
||||||
|
|
||||||
{# Meta #}
|
{# Meta #}
|
||||||
{% include '_meta.j2' %}
|
{% include '_meta.j2' %}
|
||||||
|
19
ansibledoctor/templates/readme/_todo.j2
Normal file
19
ansibledoctor/templates/readme/_todo.j2
Normal 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 %}
|
@ -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.
|
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).
|
||||||
|
@ -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
|
|
@ -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 -->
|
|
@ -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 -->
|
|
@ -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 -->
|
|
@ -2,9 +2,7 @@
|
|||||||
title: Using docker
|
title: Using docker
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
```Shell
|
||||||
<!-- spellchecker-disable -->
|
|
||||||
{{< highlight Shell "linenos=table" >}}
|
|
||||||
docker run \
|
docker run \
|
||||||
-e ANSIBLE_DOCTOR_ROLE_DIR=example/demo-role/ \
|
-e ANSIBLE_DOCTOR_ROLE_DIR=example/demo-role/ \
|
||||||
-e ANSIBLE_DOCTOR_OUTPUT_DIR=example/ \
|
-e ANSIBLE_DOCTOR_OUTPUT_DIR=example/ \
|
||||||
@ -15,11 +13,9 @@ docker run \
|
|||||||
-v $(pwd):/doctor \
|
-v $(pwd):/doctor \
|
||||||
-w /doctor \
|
-w /doctor \
|
||||||
thegeeklab/ansible-doctor
|
thegeeklab/ansible-doctor
|
||||||
{{< /highlight >}}
|
```
|
||||||
<!-- spellchecker-enable -->
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
|
||||||
{{< hint info >}}
|
{{< hint info >}}
|
||||||
**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 >}}
|
{{< /hint >}}
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
title: Using pip
|
title: Using pip
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
```Shell
|
||||||
<!-- markdownlint-disable -->
|
|
||||||
<!-- spellchecker-disable -->
|
|
||||||
{{< highlight Shell "linenos=table" >}}
|
|
||||||
# From PyPI as unprivileged user
|
# From PyPI as unprivileged user
|
||||||
$ pip install ansible-doctor --user
|
$ pip install ansible-doctor --user
|
||||||
|
|
||||||
@ -14,7 +11,4 @@ $ sudo pip install ansible-doctor
|
|||||||
|
|
||||||
# From Wheel file
|
# 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
|
$ 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 -->
|
|
||||||
|
@ -1,41 +1,3 @@
|
|||||||
---
|
---
|
||||||
title: Usage
|
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`
|
|
||||||
|
100
docs/content/usage/configuration.md
Normal file
100
docs/content/usage/configuration.md
Normal 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
|
||||||
|
```
|
84
docs/content/usage/getting-started.md
Normal file
84
docs/content/usage/getting-started.md
Normal 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.
|
||||||
|
```
|
@ -6,14 +6,9 @@ main:
|
|||||||
ref: "/setup/pip"
|
ref: "/setup/pip"
|
||||||
- name: Using docker
|
- name: Using docker
|
||||||
ref: "/setup/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
|
- name: Usage
|
||||||
ref: "/usage"
|
sub:
|
||||||
|
- name: Getting Started
|
||||||
|
ref: "/usage/getting-started"
|
||||||
|
- name: Configuration
|
||||||
|
ref: "/usage/configuration"
|
||||||
|
@ -57,7 +57,7 @@ demo_role_empty: ''
|
|||||||
|
|
||||||
### demo_role_empty_dict
|
### 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
|
#### Default value
|
||||||
|
|
||||||
@ -105,9 +105,7 @@ demo_role_single: b
|
|||||||
|
|
||||||
### demo_role_undefined_var
|
### 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_"`
|
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_"`
|
||||||
|
|
||||||
Test paragarph
|
|
||||||
|
|
||||||
#### Default value
|
#### Default value
|
||||||
|
|
||||||
@ -117,7 +115,7 @@ demo_role_undefined_var: _unset_
|
|||||||
|
|
||||||
### demo_role_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
|
#### Default value
|
||||||
|
|
||||||
@ -131,6 +129,13 @@ demo_role_unset:
|
|||||||
demo_role_unset: some_value
|
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
|
## Dependencies
|
||||||
|
|
||||||
None.
|
None.
|
||||||
@ -141,4 +146,4 @@ MIT
|
|||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
Robert Kaussow <mail@example.com>
|
John Doe
|
||||||
|
@ -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
|
# @var demo_role_unset:example: demo_role_unset: some_value
|
||||||
demo_role_unset:
|
demo_role_unset:
|
||||||
|
|
||||||
@ -7,10 +7,8 @@ demo_role_empty: ""
|
|||||||
demo_role_single: "b"
|
demo_role_single: "b"
|
||||||
|
|
||||||
# @var demo_role_empty_dict:description: >
|
# @var demo_role_empty_dict:description: >
|
||||||
# ... or you can use a valid json. In this case,
|
# ... or valid json can be used. In this case, the json will be automatically prefixed with the annotation key
|
||||||
# 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 `$`.
|
||||||
# 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.
|
|
||||||
# @end
|
# @end
|
||||||
# @var demo_role_empty_dict:example: $ {"key1": {"sub": "some value"}, "key2": {"sublist": ["subval1", "subval2"]}}
|
# @var demo_role_empty_dict:example: $ {"key1": {"sub": "some value"}, "key2": {"sublist": ["subval1", "subval2"]}}
|
||||||
demo_role_empty_dict: {}
|
demo_role_empty_dict: {}
|
||||||
@ -30,9 +28,14 @@ demo_role_dict:
|
|||||||
key1:
|
key1:
|
||||||
sub: some value
|
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: >
|
# @var demo_role_other_tags:description: >
|
||||||
# If a variable need some more explanation,
|
# If a variable need some more explanation, this is a good place to do so.
|
||||||
# this is a good place to do so.
|
|
||||||
# @end
|
# @end
|
||||||
# @var demo_role_other_tags:example: $>
|
# @var demo_role_other_tags:example: $>
|
||||||
# [
|
# [
|
||||||
@ -41,10 +44,3 @@ demo_role_dict:
|
|||||||
# ]
|
# ]
|
||||||
# @end
|
# @end
|
||||||
demo_role_other_tags: []
|
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_"
|
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
# Role to demonstrate ansible-doctor. It is also possible to overwrite
|
# Role to demonstrate ansible-doctor. It is also possible to overwrite
|
||||||
# the default description with an annotation.
|
# the default description with an annotation.
|
||||||
# @end
|
# @end
|
||||||
|
# @meta author: [John Doe](https://blog.example.com)
|
||||||
galaxy_info:
|
galaxy_info:
|
||||||
description: Role to demonstrate ansible-doctor.
|
description: Role to demonstrate ansible-doctor.
|
||||||
author: Robert Kaussow <mail@example.com>
|
author: John Doe
|
||||||
license: MIT
|
license: MIT
|
||||||
min_ansible_version: 2.4
|
min_ansible_version: 2.4
|
||||||
platforms:
|
platforms:
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user