Skip to content

Commit

Permalink
Add scenario guides (#21)
Browse files Browse the repository at this point in the history
* Add filter guide.

* Began with HostTech guide.

* Continue with HostTech guide.
  • Loading branch information
felixfontein authored May 17, 2021
1 parent 104aebf commit 33c3dcf
Show file tree
Hide file tree
Showing 3 changed files with 345 additions and 0 deletions.
6 changes: 6 additions & 0 deletions docs/docsite/extra-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
sections:
- title: Guides
toctree:
- filter_guide
- hosttech_guide
95 changes: 95 additions & 0 deletions docs/docsite/rst/filter_guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
.. _ansible_collections.community.dns.docsite.filter_guide:

Community.Dns Filter Guide
==========================

The :ref:`community.dns collection <plugins_in_community.dns>` offers several filters for working with DNS names:

- ``community.dns.get_public_suffix``: given a domain name, returns the public suffix;
- ``community.dns.get_registrable_domain``: given a domain name, returns the registrable domain name;
- ``community.dns.remove_public_suffix``: given a domain name, returns the part before the public suffix;
- ``community.dns.remove_registrable_domain``: given a domain name, returns the part before the registrable domain name.

These filters allow to work with `public suffixes <https://en.wikipedia.org/wiki/Public_Suffix_List>`_; a *public suffix* is a DNS suffix under which users can (or could) directly register names. They use the `Public Suffix List <https://publicsuffix.org/>`_, a Mozilla initiative maintained as a community resource which tries to list all such public suffixes. Common examples for public suffixes are ``.com``, ``.net``, but also longer suffixes such as ``.co.uk`` or ``.github.io``.

The label directly before the public suffix together with the suffix is called the *registrable domain name* or *registered domain name*, since these are usually the names that people can register. Examples for registrable domain names are ``example.com`` and ``example.co.uk``, while ``www.example.com`` is not a registrable domain name. A public suffix itself is also not a registrable domain name, as for example ``github.io``.

Working with public suffixes
----------------------------

The ``community.dns.get_public_suffix`` and ``community.dns.remove_public_suffix`` filters allow to extract and remove public suffixes from DNS names:

.. code-block:: yaml+jinja

- assert:
that:
- >-
"www.ansible.com" | community.dns.get_public_suffix == ".com"
- >-
"some.random.prefixes.ansible.co.uk" | community.dns.get_public_suffix == ".co.uk"
- >-
"www.ansible.com" | community.dns.remove_public_suffix == "www.ansible"
- >-
"some.random.prefixes.ansible.co.uk" | community.dns.remove_public_suffix == "some.random.prefixes.ansible"

The filters also allow additional options (keyword arguments):

:keep_unknown_suffix:

A boolean with default value ``true``. This treats unknown TLDs as valid public suffixes. So for example the public suffix of ``example.tlddoesnotexist`` is ``.tlddoesnotexist`` if this is ``true``. If set to ``false``, it will return an empty string in this case. This option corresponds to whether the global wildcard rule ``*`` in the Public Suffix List is used or not.

:icann_only:

A boolean with default value ``false``. This controls whether only entries from the ICANN section of the Public Suffix List are used, or also entries from the Private section. For example, ``.co.uk`` is in the ICANN section, but ``github.io`` is in the Private section.

:normalize_result:

(Only for ``community.dns.get_public_suffix``) A boolean with default value ``false``. This controls whether the result is reconstructed from the normalized name used during lookup. During normalization, ulabels are converted to alabels, and every label is converted to lowercase. For example, the ulabel ``ëçãmplê`` is converted to ``xn--mpl-llatwb`` (puny-code), and ``Example.COM`` is converted to ``example.com``.

:keep_leading_period:

(Only for ``community.dns.get_public_suffix``) A boolean with default value ``true``. This controls whether the leading period of a public suffix is preserved or not.

:keep_trailing_period:

(Only for ``community.dns.remove_public_suffix``) A boolean with default value ``false``. This controls whether the trailing period of the prefix (that is, the part before the public suffix) is preserved or not.

Working with registrable domain names
-------------------------------------

The ``community.dns.get_registrable_domain`` and ``community.dns.remove_registrable_domain`` filters allow to extract and remove registrable domain names from DNS names:

.. code-block:: yaml+jinja

- assert:
that:
- >-
"www.ansible.com" | community.dns.get_registrable_domain == "ansible.com"
- >-
"some.random.prefixes.ansible.co.uk" | community.dns.get_registrable_domain == "ansible.co.uk"
- >-
"www.ansible.com" | community.dns.remove_registrable_domain == "www"
- >-
"some.random.prefixes.ansible.co.uk" | community.dns.remove_registrable_domain == "some.random.prefixes"

The filters also allow additional options (keyword arguments):

:keep_unknown_suffix:

A boolean with default value ``true``. This treats unknown TLDs as valid public suffixes. So for example the public suffix of ``example.tlddoesnotexist`` is ``.tlddoesnotexist`` if this is ``true``, and hence the registrable domain of ``www.example.tlddoesnotexist`` is ``example.tlddoesnotexist``. If set to ``false``, the registrable domain of ``www.example.tlddoesnotexist`` is ``tlddoesnotexist``. This option corresponds to whether the global wildcard rule ``*`` in the Public Suffix List is used or not.

:icann_only:

A boolean with default value ``false``. This controls whether only entries from the ICANN section of the Public Suffix List are used, or also entries from the Private section. For example, ``.co.uk`` is in the ICANN section, but ``github.io`` is in the Private section.

:only_if_registerable:

A boolean with default value ``true``. This controls the behavior in case there is no label in front of the public suffix. This is the case if the DNS name itself is a public suffix. If set to ``false``, in this case the public suffix is treated as a registrable domain. If set to ``true`` (default), the registrable domain of a public suffix is interpreted as an empty string.

:normalize_result:

(Only for ``community.dns.get_registrable_domain``) A boolean with default value ``false``. This controls whether the result is reconstructed from the normalized name used during lookup. During normalization, ulabels are converted to alabels, and every label is converted to lowercase. For example, the ulabel ``ëçãmplê`` is converted to ``xn--mpl-llatwb`` (puny-code), and ``Example.COM`` is converted to ``example.com``.

:keep_trailing_period:

(Only for ``community.dns.remove_registrable_domain``) A boolean with default value ``false``. This controls whether the trailing period of the prefix (that is, the part before the registrable domain) is preserved or not.
244 changes: 244 additions & 0 deletions docs/docsite/rst/hosttech_guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
.. _ansible_collections.community.dns.docsite.hosttech_guide:

HostTech DNS Guide
==================

The :ref:`community.dns collection <plugins_in_community.dns>` offers several modules for working with the `HostTech DNS service <https://www.hosttech.ch/>`_.
The modules support both the old `WSDL-based API <https://ns1.hosttech.eu/public/api?wsdl>`_ and the new `JSON REST based API <https://api.ns1.hosttech.eu/api/documentation/>`_.

The collection provides four modules for working with HostTech DNS:

- ``community.dns.hosttech_dns_record``: create/update/delete DNS records
- ``community.dns.hosttech_dns_record_info``: retrieve information on DNS records
- ``community.dns.hosttech_dns_records``: bulk synchronize DNS records
- ``community.dns.hosttech_dns_zone_info``: retrieve zone information

Authentication, Requirements and APIs
-------------------------------------

HostTech currently has two APIs for working with DNS records: the old WSDL-based API, and the new JSON-based REST API. We recommend using the new REST API if possible.

JSON REST API
~~~~~~~~~~~~~

To use the JSON REST API, you need to create a API token. You can manage API tokens in the "DNS Editor" in the "API" section. You must provide the token to the ``hosttech_token`` option of the modules:

.. code-block:: yaml+jinja

- community.dns.hosttech_dns_record:
hosttech_token: '{{ token }}'
...

In the examples in this guide, we will leave the authentication options away. Please note that you can set them globally with ``module_defaults`` (see :ref:`module_defaults`).

WSDL API
~~~~~~~~

To use the WSDL API, you need to set API credentials. These can be found and changed in the "Servercenter" and there in the "Solutions" section under settings for the "DNS Tool". The username is fixed, but the password can be changed. The credentials must be provided to the ``hosttech_username`` and ``hosttech_password`` options of the modules.

You also need to install the `lxml Python module <https://pypi.org/project/lxml/>`_ to work with the WSDL API. This can be done before using the modules:

.. code-block:: yaml+jinja

- name: Make sure lxml is installed
pip:
name: lxml

- community.dns.hosttech_dns_record:
hosttech_username: '{{ username }}'
hosttech_password: '{{ password }}'
...

In the examples in this guide, we will leave the authentication options away. Please note that you can set them globally with ``module_defaults`` (see :ref:`module_defaults`).

Working with DNS zones
----------------------

The ``community.dns.hosttech_dns_zone_info`` module allows to query information on a zone. The zone can be identified both by its name and by its ID (which is an integer):

.. code-block:: yaml+jinja

- name: Query zone information by name
community.dns.hosttech_dns_zone_info:
zone: example.com
register: result

- name: Query zone information by name
community.dns.hosttech_dns_zone_info:
zone_id: 42
register: result

The module returns both the zone name and zone ID, so this module can be used to convert from zone ID to zone name and vice versa:

.. code-block:: yaml+jinja

- ansible.builtin.debug:
msg: |
The zone ID: {{ result.zone_id }}
The zone name: {{ result.zone_name }}

Working with DNS records
------------------------

Querying DNS records
~~~~~~~~~~~~~~~~~~~~

The ``community.dns.hosttech_dns_record_info`` module allows to query DNS records from the API. It can be used to query a single record:

.. code-block:: yaml+jinja

- name: Query single record
community.dns.hosttech_dns_record_info:
zone: example.com
type: A # IPv4 addresses
what: single_record # default value
# Either specify a record name:
record: www.example.com
# Or a record prefix ('' is the zone itself):
prefix: www
register: result

- name: Show IPv4 addresses if record exists
ansible.builtin.debug:
msg: >
IPv4s are {{ result.set.value | join(', ') }},
TTL is {{ result.set.ttl }}
when: result.set

- name: Show that record is not set
ansible.builtin.debug:
msg: There is no A record for www.example.com
when: not result.set

In all examples in this section, you can replace ``zone: example.com`` by ``zone_id: 42`` with the zone's integer ID.

You can also query a list of all records for a record name or prefix:

.. code-block:: yaml+jinja

- name: Query all records for www.example.com
community.dns.hosttech_dns_record_info:
zone: example.com
what: all_types_for_record
# Either specify a record name:
record: www.example.com
# Or a record prefix ('' is the zone itself):
prefix: www
register: result

- name: Show all records for www.example.com
ansible.builtin.debug:
msg: >
{{ item.type }} record with TTL {{ item.ttl }} has
values {{ item.value | join(', ') }}
loop: result.sets

Finally you can query all records for a zone:

.. code-block:: yaml+jinja

- name: Query all records for a zone
community.dns.hosttech_dns_record_info:
zone: example.com
what: all_records
register: result

- name: Show all records for the example.com zone
ansible.builtin.debug:
msg: >
{{ item.type }} record for {{ item.record }} with
TTL {{ item.ttl }} has values {{ item.value | join(', ') }}
loop: result.sets

Creating and updating DNS records
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``community.dns.hosttech_dns_record`` module allows to set, update and remove DNS records. Setting and updating can be done as follows:

.. code-block:: yaml+jinja

- name: Make sure record is set to the given value
community.dns.hosttech_dns_record:
zone: example.com
type: A # IPv4 addresses
# Either specify a record name:
record: www.example.com
# Or a record prefix ('' is the zone itself):
prefix: www
# The following makes sure that existing values
# (that differ form the one given) are updated:
overwrite: true
value:
- 1.1.1.1
- 8.8.8.8

If you want to assert that a record has a certain value (and fail if it has a different value), leave away the ``overwrite: true``.

To delete values, you can either overwrite the values with value ``[]``, or use ``state: absent``:

.. code-block:: yaml+jinja

- name: Remove A values for www.example.com
community.dns.hosttech_dns_record:
zone: example.com
type: A # IPv4 addresses
record: www.example.com
overwrite: true
value: []

- name: Remove specific AAAA values for www.example.com
community.dns.hosttech_dns_record:
zone: example.com
type: AAAA # IPv6 addresses
prefix: www
state: absent
ttl: 300
value:
- '::1'

In the second example, ``overwrite: true`` is not present, but an explicit value and TTL are given. This makes the module remove the current value only if there's a AAAA record for ``www.example.com`` whose current value is ``::1`` and whose TTL is 300. If another value is set, the module will not make any change. This can be useful to not accidentally remove values you do not want to change.

Bulk synchronization of DNS records
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you want to set/update multiple records at once, or even make sure that the precise set of records you are providing are present and nothing else, you can use the ``community.dns.hosttech_dns_records`` module.

The following example shows up to set/update multiple records at once:

.. code-block:: yaml+jinja

- name: Make sure that multiple records are present
community.dns.hosttech_dns_records:
zone: example.com
records:
- prefix: www
type: A
value:
- 1.1.1.1
- 8.8.8.8
- prefix: www
type: AAAA
value:
- '::1'

The next example shows how to make sure that only the given records are available and all other records are deleted. Note that for the ``type: NS`` record we used ``ignore: true``, which allows us to skip the value. It tells the module that it should not touch the ``NS`` record for ``example.com``.

.. code-block:: yaml+jinja

- name: Make sure that multiple records are present
community.dns.hosttech_dns_records:
zone: example.com
prune: true
records:
- prefix: www
type: A
value:
- 1.1.1.1
- 8.8.8.8
- prefix: www
type: AAAA
value:
- '::1'
- prefix: ''
type: NS
ignore: true

0 comments on commit 33c3dcf

Please sign in to comment.