summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/dns/docs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:03:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:03:42 +0000
commit66cec45960ce1d9c794e9399de15c138acb18aed (patch)
tree59cd19d69e9d56b7989b080da7c20ef1a3fe2a5a /ansible_collections/community/dns/docs
parentInitial commit. (diff)
downloadansible-upstream.tar.xz
ansible-upstream.zip
Adding upstream version 7.3.0+dfsg.upstream/7.3.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/dns/docs')
-rw-r--r--ansible_collections/community/dns/docs/docsite/extra-docs.yml11
-rw-r--r--ansible_collections/community/dns/docs/docsite/links.yml27
-rw-r--r--ansible_collections/community/dns/docs/docsite/rst/filter_guide.rst104
-rw-r--r--ansible_collections/community/dns/docs/docsite/rst/hetzner_guide.rst484
-rw-r--r--ansible_collections/community/dns/docs/docsite/rst/hosttech_guide.rst338
5 files changed, 964 insertions, 0 deletions
diff --git a/ansible_collections/community/dns/docs/docsite/extra-docs.yml b/ansible_collections/community/dns/docs/docsite/extra-docs.yml
new file mode 100644
index 00000000..616f2570
--- /dev/null
+++ b/ansible_collections/community/dns/docs/docsite/extra-docs.yml
@@ -0,0 +1,11 @@
+---
+# Copyright (c) Ansible Project
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+sections:
+ - title: Guides
+ toctree:
+ - filter_guide
+ - hetzner_guide
+ - hosttech_guide
diff --git a/ansible_collections/community/dns/docs/docsite/links.yml b/ansible_collections/community/dns/docs/docsite/links.yml
new file mode 100644
index 00000000..05a8e831
--- /dev/null
+++ b/ansible_collections/community/dns/docs/docsite/links.yml
@@ -0,0 +1,27 @@
+---
+# Copyright (c) Ansible Project
+# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+edit_on_github:
+ repository: ansible-collections/community.dns
+ branch: main
+ path_prefix: ''
+
+extra_links:
+ - description: Submit a bug report
+ url: https://github.com/ansible-collections/community.dns/issues/new?assignees=&labels=&template=bug_report.md
+ - description: Request a feature
+ url: https://github.com/ansible-collections/community.dns/issues/new?assignees=&labels=&template=feature_request.md
+
+communication:
+ matrix_rooms:
+ - topic: General usage and support questions
+ room: '#users:ansible.im'
+ irc_channels:
+ - topic: General usage and support questions
+ network: Libera
+ channel: '#ansible'
+ mailing_lists:
+ - topic: Ansible Project List
+ url: https://groups.google.com/g/ansible-project
diff --git a/ansible_collections/community/dns/docs/docsite/rst/filter_guide.rst b/ansible_collections/community/dns/docs/docsite/rst/filter_guide.rst
new file mode 100644
index 00000000..a2169369
--- /dev/null
+++ b/ansible_collections/community/dns/docs/docsite/rst/filter_guide.rst
@@ -0,0 +1,104 @@
+..
+ Copyright (c) Ansible Project
+ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+ SPDX-License-Identifier: GPL-3.0-or-later
+
+.. _ansible_collections.community.dns.docsite.filter_guide:
+
+Community.Dns Filter Guide
+==========================
+
+.. contents:: Contents
+ :local:
+ :depth: 1
+
+The :ref:`community.dns collection <plugins_in_community.dns>` offers several filters for working with DNS names:
+
+- :ref:`community.dns.get_public_suffix <ansible_collections.community.dns.get_public_suffix_filter>`: given a domain name, returns the public suffix;
+- :ref:`community.dns.get_registrable_domain <ansible_collections.community.dns.get_registrable_domain_filter>`: given a domain name, returns the registrable domain name;
+- :ref:`community.dns.remove_public_suffix <ansible_collections.community.dns.remove_public_suffix_filter>`: given a domain name, returns the part before the public suffix;
+- :ref:`community.dns.remove_registrable_domain <ansible_collections.community.dns.remove_registrable_domain_filter>`: 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 :ref:`community.dns.get_public_suffix <ansible_collections.community.dns.get_public_suffix_filter>` and :ref:`community.dns.remove_public_suffix <ansible_collections.community.dns.remove_public_suffix_filter>` 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 :ref:`community.dns.get_public_suffix <ansible_collections.community.dns.get_public_suffix_filter>`) 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 :ref:`community.dns.get_public_suffix <ansible_collections.community.dns.get_public_suffix_filter>`) 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 :ref:`community.dns.remove_public_suffix <ansible_collections.community.dns.remove_public_suffix_filter>`) 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 :ref:`community.dns.get_registrable_domain <ansible_collections.community.dns.get_registrable_domain_filter>` and :ref:`community.dns.remove_registrable_domain <ansible_collections.community.dns.remove_registrable_domain_filter>` 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 :ref:`community.dns.get_registrable_domain <ansible_collections.community.dns.get_registrable_domain_filter>`) 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 :ref:`community.dns.remove_registrable_domain <ansible_collections.community.dns.remove_registrable_domain_filter>`) 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.
diff --git a/ansible_collections/community/dns/docs/docsite/rst/hetzner_guide.rst b/ansible_collections/community/dns/docs/docsite/rst/hetzner_guide.rst
new file mode 100644
index 00000000..cbb029dc
--- /dev/null
+++ b/ansible_collections/community/dns/docs/docsite/rst/hetzner_guide.rst
@@ -0,0 +1,484 @@
+..
+ Copyright (c) Ansible Project
+ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+ SPDX-License-Identifier: GPL-3.0-or-later
+
+.. _ansible_collections.community.dns.docsite.hetzner_guide:
+
+Hetzner DNS Guide
+=================
+
+.. contents:: Contents
+ :local:
+ :depth: 2
+
+The :ref:`community.dns collection <plugins_in_community.dns>` offers several modules for working with the `Hetzner DNS service <https://docs.hetzner.com/dns-console/dns/>`_.
+The modules use the `JSON REST based API <https://dns.hetzner.com/api-docs/>`_.
+
+The collection provides six modules for working with Hetzner DNS:
+
+- :ref:`community.dns.hetzner_dns_record <ansible_collections.community.dns.hetzner_dns_record_module>`: create/update/delete single DNS records
+- :ref:`community.dns.hetzner_dns_record_info <ansible_collections.community.dns.hetzner_dns_record_info_module>`: retrieve information on DNS records
+- :ref:`community.dns.hetzner_dns_record_set <ansible_collections.community.dns.hetzner_dns_record_set_module>`: create/update/delete DNS record sets
+- :ref:`community.dns.hetzner_dns_record_set_info <ansible_collections.community.dns.hetzner_dns_record_set_info_module>`: retrieve information on DNS record sets
+- :ref:`community.dns.hetzner_dns_record_sets <ansible_collections.community.dns.hetzner_dns_record_sets_module>`: bulk synchronize DNS record sets
+- :ref:`community.dns.hetzner_dns_zone_info <ansible_collections.community.dns.hetzner_dns_zone_info_module>`: retrieve zone information
+
+If you are interested in migrating from the `markuman.hetzner_dns collection <https://galaxy.ansible.com/markuman/hetzner_dns>`_, please see :ref:`ansible_collections.community.dns.docsite.hetzner_guide.migration_markuman_hetzner_dns`.
+
+It also provides an inventory plugin:
+
+- :ref:`community.dns.hetzner_dns_records <ansible_collections.community.dns.hetzner_dns_records_inventory>`: create inventory from DNS records
+
+Authentication
+--------------
+
+To use Hetzner's API, you need to create an API token. You can manage API tokens in the "API tokens" menu entry in your user menu in the `DNS Console <https://dns.hetzner.com/>`_. You must provide the token to the ``hetzner_token`` option of the modules, its alias ``api_token``, or pass it on in the ``HETZNER_DNS_TOKEN`` environment variable:
+
+.. code-block:: yaml+jinja
+
+ - community.dns.hetzner_dns_record:
+ hetzner_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`) or with an environment variable for the user and machine where the modules are run on.
+
+Using the ``community.dns.hetzner`` module defaults group
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To avoid having to specify common parameters for all Hetzner DNS modules in every task, you can use the ``community.dns.hetzner`` module defaults group:
+
+.. code-block:: yaml+jinja
+
+ ---
+ - name: Hetzner DNS
+ hosts: localhost
+ gather_facts: false
+ module_defaults:
+ group/community.dns.hetzner
+ hetzner_token: '{{ token }}'
+ tasks:
+ - name: Query zone information
+ community.dns.hetzner_dns_zone_info:
+ zone_name: example.com
+ register: result
+
+ - name: Set A records for www.example.com
+ community.dns.hetzner_dns_record_set:
+ state: present
+ zone_name: example.com
+ type: A
+ prefix: www
+ value:
+ - 192.168.0.1
+
+Here all two tasks will use the options set for the module defaults group.
+
+Working with DNS zones
+----------------------
+
+The :ref:`community.dns.hetzner_dns_zone_info module <ansible_collections.community.dns.hetzner_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.hetzner_dns_zone_info:
+ zone_name: example.com
+ register: result
+
+ - name: Query zone information by ID
+ community.dns.hetzner_dns_zone_info:
+ zone_id: aBcDeFgHiJlMnOpQrStUvW
+ 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
+------------------------
+
+.. note::
+
+ By default, TXT record values returned and accepted by the modules and plugins in this collection are unquoted. This means that you do not have to add double quotes (``"``), and escape double quotes (as ``\"``) and backslashes (as ``\\``). All modules and plugins which work with DNS records support the ``txt_transformation`` option which allows to configure this behavior.
+
+Querying DNS records and record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :ref:`community.dns.hetzner_dns_record_set_info module <ansible_collections.community.dns.hetzner_dns_record_set_info_module>` allows to query DNS record sets from the API. It can be used to query a single record set:
+
+.. code-block:: yaml+jinja
+
+ - name: Query single record
+ community.dns.hetzner_dns_record_set_info:
+ zone_name: 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_name=example.com`` by ``zone_id=aBcDeFgHiJlMnOpQrStUvW`` with the zone's ID string.
+
+You can also query a list of all record sets for a record name or prefix:
+
+.. code-block:: yaml+jinja
+
+ - name: Query all records for www.example.com
+ community.dns.hetzner_dns_record_set_info:
+ zone_name: 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 record sets for a zone:
+
+.. code-block:: yaml+jinja
+
+ - name: Query all records for a zone
+ community.dns.hetzner_dns_record_set_info:
+ zone_name: 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
+
+If you are interested in individual DNS records, and not record sets, you should use the :ref:`community.dns.hetzner_dns_record_info module <ansible_collections.community.dns.hetzner_dns_record_info_module>`. It supports the same limiting options as the ``community.dns.hetzner_dns_record_set_info`` module.
+
+Creating and updating DNS single records
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you do not want to add/remove values, but replace values, you will be interested in modifying a **record set** and not a single record. This is in particular important when working with ``CNAME`` and ``SOA`` records.
+
+The :ref:`community.dns.hetzner_dns_record module <ansible_collections.community.dns.hetzner_dns_record_module>` allows to set, update and remove single DNS records. Setting and updating can be done as follows. Records will be matched by record name and type, and the TTL value will be updated if necessary:
+
+.. code-block:: yaml+jinja
+
+ - name: Add an A record with value 1.1.1.1 for www.example.com, resp. make sure the TTL is 300
+ community.dns.hetzner_dns_record:
+ state: present
+ zone_name: 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
+ value: 1.1.1.1
+ ttl: 300
+
+To delete records, simply use ``state=absent``. Records will be matched by record name and type, and the TTL will be ignored:
+
+.. code-block:: yaml+jinja
+
+ - name: Remove A values for www.example.com
+ community.dns.hetzner_dns_record:
+ state: absent
+ zone_name: example.com
+ type: A # IPv4 addresses
+ record: www.example.com
+ value: 1.1.1.1
+
+Records of the same type for the same record name with other values are ignored.
+
+Creating and updating DNS record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :ref:`community.dns.hetzner_dns_record_set module <ansible_collections.community.dns.hetzner_dns_record_set_module>` allows to set, update and remove DNS record sets. Setting and updating can be done as follows:
+
+.. code-block:: yaml+jinja
+
+ - name: Make sure record is set to the given value
+ community.dns.hetzner_dns_record_set:
+ state: present
+ zone_name: 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
+ value:
+ - 1.1.1.1
+ - 8.8.8.8
+
+If you want to assert that a record has a certain value, set ``on_existing=keep``. Using ``keep_and_warn`` instead will emit a warning if this happens, and ``keep_and_fail`` will make the module fail.
+
+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.hetzner_dns_record_set:
+ state: present
+ zone_name: example.com
+ type: A # IPv4 addresses
+ record: www.example.com
+ value: []
+
+ - name: Remove TXT values for www.example.com
+ community.dns.hetzner_dns_record_set:
+ zone_name: example.com
+ type: TXT
+ prefix: www
+ state: absent
+
+ - name: Remove specific AAAA values for www.example.com
+ community.dns.hetzner_dns_record_set:
+ zone_name: example.com
+ type: AAAA # IPv6 addresses
+ prefix: www
+ state: absent
+ on_existing: keep_and_fail
+ ttl: 300
+ value:
+ - '::1'
+
+In the third example, ``on_existing=keep_and_fail`` is present and 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, but fail. This can be useful to not accidentally remove values you do not want to change. To issue a warning instead of failing, use ``on_existing=keep_and_warn``, and to simply not do a change without any indication of this situation, use ``on_existing=keep``.
+
+Bulk synchronization of DNS record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 :ref:`community.dns.hetzner_dns_record_sets module <ansible_collections.community.dns.hetzner_dns_record_sets_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.hetzner_dns_record_sets:
+ zone_name: 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.hetzner_dns_record_sets:
+ zone_name: 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
+
+.. _ansible_collections.community.dns.docsite.hetzner_guide.migration_markuman_hetzner_dns:
+
+Migrating from ``markuman.hetzner_dns``
+---------------------------------------
+
+This section describes how to migrate playbooks and roles from using the `markuman.hetzner_dns collection <https://galaxy.ansible.com/markuman/hetzner_dns>`_ to the Hetzner modules and plugins in the ``community.dns`` collection.
+
+There are three steps for migrating. Two of these steps must be done on migration, the third step can also be done later:
+
+1. Replace the modules and plugins used by the new ones.
+2. Adjust module and plugin options if necessary.
+3. Avoid deprecated aliases which ease the transition.
+
+The `markuman.hetzner_dns collection <https://galaxy.ansible.com/markuman/hetzner_dns>`_ collection provides three modules and one inventory plugin.
+
+.. note::
+
+ When working with TXT records, please look at the ``txt_transformation`` option. By default, the modules and plugins in this collection use **unquoted** values (you do not have to add double quotes and escape double quotes and backslashes), while the modules and plugins in ``markuman.hetzner_dns`` use partially quoted values. You can switch behavior of the ``community.dns`` modules by passing ``txt_transformation=api`` or ``txt_transformation=quoted``.
+
+The markuman.hetzner_dns.record module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``markuman.hetzner_dns.zone_info`` module can be replaced by the :ref:`community.dns.hetzner_dns_record module <ansible_collections.community.dns.hetzner_dns_record_module>` and the :ref:`community.dns.hetzner_dns_record_set module <ansible_collections.community.dns.hetzner_dns_record_set_module>`, depending on what it is used for.
+
+When creating, updating or removing single records, the :ref:`community.dns.hetzner_dns_record module <ansible_collections.community.dns.hetzner_dns_record_module>` should be used. This is the case when ``purge=false`` is specified (the default value). Note that ``replace``, ``overwrite`` and ``solo`` are aliases of ``purge``.
+
+.. code-block:: yaml+jinja
+
+ # Creating and updating DNS records
+
+ - name: Creating or updating a single DNS record with markuman.hetzner_dns
+ markuman.hetzner_dns.record:
+ zone_name: example.com
+ name: localhost
+ type: A
+ value: 127.0.0.1
+ ttl: 60
+ # This means the module operates on single DNS entries. If not specified,
+ # this is the default value:
+ purge: false
+
+ - name: Creating or updating a single DNS record with community.dns
+ community.dns.hetzner_dns_record:
+ zone_name: example.com
+ # 'state' must always be specified:
+ state: present
+ # 'name' is a deprecated alias of 'prefix', so it can be
+ # kept during a first migration step:
+ name: localhost
+ # 'type', 'value' and 'ttl' do not change:
+ type: A
+ value: 127.0.0.1
+ ttl: 60
+ # If type is TXT, you either have to adjust the value you pass,
+ # or keep the following option:
+ txt_transformation: api
+
+When the ``markuman.hetzner_dns.record`` module is in replace mode, it should be replaced by the :ref:`community.dns.hetzner_dns_record_set module <ansible_collections.community.dns.hetzner_dns_record_set_module>`, since then it operates on the *record set* and not just on a single record:
+
+.. code-block:: yaml+jinja
+
+ # Creating and updating DNS record sets
+
+ - name: Creating or updating a record set with markuman.hetzner_dns
+ markuman.hetzner_dns.record:
+ zone_name: example.com
+ name: localhost
+ type: A
+ value: 127.0.0.1
+ ttl: 60
+ # This means the module operates on the record set:
+ purge: true
+
+ - name: Creating or updating a record set with community.dns
+ community.dns.hetzner_dns_record_set:
+ zone_name: example.com
+ # 'state' must always be specified:
+ state: present
+ # 'name' is a deprecated alias of 'prefix', so it can be
+ # kept during a first migration step:
+ name: localhost
+ # 'type' and 'ttl' do not change:
+ type: A
+ ttl: 60
+ # 'value' is now a list:
+ value:
+ - 127.0.0.1
+ # Ansible allows to specify lists as a comma-separated string.
+ # So for records which do not contain a comma, you can also
+ # keep the old syntax, in this case:
+ #
+ # value: 127.0.0.1
+ #
+ # If type is TXT, you either have to adjust the value you pass,
+ # or keep the following option:
+ txt_transformation: api
+
+When deleting a record, it depends on whether ``value`` is specified or not. If ``value`` is specified, the module is deleting a single DNS record, and the :ref:`community.dns.hetzner_dns_record module <ansible_collections.community.dns.hetzner_dns_record_module>` should be used:
+
+.. code-block:: yaml+jinja
+
+ # Deleting single DNS records
+
+ - name: Deleting a single DNS record with markuman.hetzner_dns
+ markuman.hetzner_dns.record:
+ zone_name: example.com
+ state: absent
+ name: localhost
+ type: A
+ value: 127.0.0.1
+ ttl: 60
+
+ - name: Deleting a single DNS record with community.dns
+ community.dns.hetzner_dns_record:
+ zone_name: example.com
+ state: absent
+ # 'name' is a deprecated alias of 'prefix', so it can be
+ # kept during a first migration step:
+ name: localhost
+ # 'type', 'value' and 'ttl' do not change:
+ type: A
+ value: 127.0.0.1
+ ttl: 60
+ # If type is TXT, you either have to adjust the value you pass,
+ # or keep the following option:
+ txt_transformation: api
+
+When ``value`` is not specified, the ``markuman.hetzner_dns.record`` module will delete all records for this prefix and type. In that case, it operates on a record set and the :ref:`community.dns.hetzner_dns_record_set module <ansible_collections.community.dns.hetzner_dns_record_set_module>` should be used:
+
+.. code-block:: yaml+jinja
+
+ # Deleting multiple DNS records
+
+ - name: Deleting multiple DNS records with markuman.hetzner_dns
+ markuman.hetzner_dns.record:
+ zone_name: example.com
+ state: absent
+ name: localhost
+ type: A
+
+ - name: Deleting a single DNS record with community.dns
+ community.dns.hetzner_dns_record_set:
+ zone_name: example.com
+ state: absent
+ # 'name' is a deprecated alias of 'prefix', so it can be
+ # kept during a first migration step:
+ name: localhost
+ # 'type' does not change:
+ type: A
+
+A last step is replacing the deprecated alias ``name`` of ``prefix`` by ``prefix``. This can be done later though, if you do not mind the deprecation warnings.
+
+The markuman.hetzner_dns.record_info module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``markuman.hetzner_dns.record_info`` module can be replaced by the :ref:`community.dns.hetzner_dns_record_info module <ansible_collections.community.dns.hetzner_dns_record_info_module>`. The main difference is that instead of by the ``filters`` option, the output is controlled by the ``what`` option (choices ``single_record``, ``all_types_for_record``, and ``all_records``), the ``type`` option (needed when ``what=single_record``), and the ``record`` and ``prefix`` options (needed when ``what`` is not ``all_records``).
+
+The markuman.hetzner_dns.zone_info module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``markuman.hetzner_dns.zone_info`` module can be replaced by the :ref:`community.dns.hetzner_dns_zone_info module <ansible_collections.community.dns.hetzner_dns_zone_info_module>`. The main differences are:
+
+1. The parameter ``name`` must be changed to ``zone_name`` or ``zone``.
+2. The return value ``zone_info`` no longer has the ``name`` and ``id`` entries. Use the return values ``zone_name`` and ``zone_id`` instead.
+
+The markuman.hetzner_dns.inventory inventory plugin
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``markuman.hetzner_dns.inventory`` inventory plugin can be replaced by the :ref:`community.dns.hetzner_dns_records inventory plugin <ansible_collections.community.dns.hetzner_dns_records_inventory>`. Besides the plugin name, no change should be necessary.
diff --git a/ansible_collections/community/dns/docs/docsite/rst/hosttech_guide.rst b/ansible_collections/community/dns/docs/docsite/rst/hosttech_guide.rst
new file mode 100644
index 00000000..8efb8058
--- /dev/null
+++ b/ansible_collections/community/dns/docs/docsite/rst/hosttech_guide.rst
@@ -0,0 +1,338 @@
+..
+ Copyright (c) Ansible Project
+ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
+ SPDX-License-Identifier: GPL-3.0-or-later
+
+.. _ansible_collections.community.dns.docsite.hosttech_guide:
+
+HostTech DNS Guide
+==================
+
+.. contents:: Contents
+ :local:
+ :depth: 2
+
+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 six modules for working with HostTech DNS:
+
+- :ref:`community.dns.hosttech_dns_record <ansible_collections.community.dns.hosttech_dns_record_module>`: create/update/delete single DNS records
+- :ref:`community.dns.hosttech_dns_record_info <ansible_collections.community.dns.hosttech_dns_record_info_module>`: retrieve information on DNS records
+- :ref:`community.dns.hosttech_dns_record_set <ansible_collections.community.dns.hosttech_dns_record_set_module>`: create/update/delete DNS record sets
+- :ref:`community.dns.hosttech_dns_record_set_info <ansible_collections.community.dns.hosttech_dns_record_set_info_module>`: retrieve information on DNS record sets
+- :ref:`community.dns.hosttech_dns_record_sets <ansible_collections.community.dns.hosttech_dns_record_sets_module>`: bulk synchronize DNS record sets
+- :ref:`community.dns.hosttech_dns_zone_info <ansible_collections.community.dns.hosttech_dns_zone_info_module>`: retrieve zone information
+
+It also provides an inventory plugin:
+
+- :ref:`community.dns.hosttech_dns_records <ansible_collections.community.dns.hosttech_dns_records_inventory>`: create inventory from DNS records
+
+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`).
+
+Using the ``community.dns.hosttech`` module defaults group
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To avoid having to specify common parameters for all Hosttech DNS modules in every task, you can use the ``community.dns.hosttech`` module defaults group:
+
+.. code-block:: yaml+jinja
+
+ ---
+ - name: Hosttech DNS
+ hosts: localhost
+ gather_facts: false
+ module_defaults:
+ group/community.dns.hosttech
+ hosttech_username: '{{ username }}'
+ hosttech_password: '{{ password }}'
+ tasks:
+ - name: Query zone information
+ community.dns.hosttech_dns_zone_info:
+ zone_name: example.com
+ register: result
+
+ - name: Set A records for www.example.com
+ community.dns.hosttech_dns_record_set:
+ state: present
+ zone_name: example.com
+ type: A
+ prefix: www
+ value:
+ - 192.168.0.1
+
+Here all two tasks will use the options set for the module defaults group.
+
+Working with DNS zones
+----------------------
+
+The :ref:`community.dns.hosttech_dns_zone_info module <ansible_collections.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_name: example.com
+ register: result
+
+ - name: Query zone information by ID
+ 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
+------------------------
+
+.. note::
+
+ By default, TXT record values returned and accepted by the modules and plugins in this collection are unquoted. This means that you do not have to add double quotes (``"``), and escape double quotes (as ``\"``) and backslashes (as ``\\``). All modules and plugins which work with DNS records support the ``txt_transformation`` option which allows to configure this behavior.
+
+Querying DNS records and record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :ref:`community.dns.hosttech_dns_record_set_info module <ansible_collections.community.dns.hosttech_dns_record_set_info_module>` allows to query DNS record sets from the API. It can be used to query a single record set:
+
+.. code-block:: yaml+jinja
+
+ - name: Query single record
+ community.dns.hosttech_dns_record_set_info:
+ zone_name: 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_name: example.com`` by ``zone_id: 42`` with the zone's integer ID.
+
+You can also query a list of all record sets for a record name or prefix:
+
+.. code-block:: yaml+jinja
+
+ - name: Query all records for www.example.com
+ community.dns.hosttech_dns_record_set_info:
+ zone_name: 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 record sets for a zone:
+
+.. code-block:: yaml+jinja
+
+ - name: Query all records for a zone
+ community.dns.hosttech_dns_record_set_info:
+ zone_name: 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
+
+If you are interested in individual DNS records, and not record sets, you should use the :ref:`community.dns.hosttech_dns_record_info module <ansible_collections.community.dns.hosttech_dns_record_info_module>`. It supports the same limiting options as the ``community.dns.hosttech_dns_record_set_info`` module.
+
+Creating and updating DNS single records
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you do not want to add/remove values, but replace values, you will be interested in modifying a **record set** and not a single record. This is in particular important when working with ``CNAME`` and ``SOA`` records.
+
+The :ref:`community.dns.hosttech_dns_record module <ansible_collections.community.dns.hosttech_dns_record_module>` allows to set, update and remove single DNS records. Setting and updating can be done as follows. Records will be matched by record name and type, and the TTL value will be updated if necessary:
+
+.. code-block:: yaml+jinja
+
+ - name: Add an A record with value 1.1.1.1 for www.example.com, resp. make sure the TTL is 300
+ community.dns.hosttech_dns_record:
+ state: present
+ zone_name: 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
+ value: 1.1.1.1
+ ttl: 300
+
+To delete records, simply use ``state: absent``. Records will be matched by record name and type, and the TTL will be ignored:
+
+.. code-block:: yaml+jinja
+
+ - name: Remove A values for www.example.com
+ community.dns.hosttech_dns_record:
+ state: absent
+ zone_name: example.com
+ type: A # IPv4 addresses
+ record: www.example.com
+ value: 1.1.1.1
+
+Records of the same type for the same record name with other values are ignored.
+
+Creating and updating DNS record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :ref:`community.dns.hosttech_dns_record_set module <ansible_collections.community.dns.hosttech_dns_record_set_module>` allows to set, update and remove DNS record sets. 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_set:
+ state: present
+ zone_name: 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
+ value:
+ - 1.1.1.1
+ - 8.8.8.8
+
+If you want to assert that a record has a certain value, set ``on_existing: keep``. Using ``keep_and_warn`` instead will emit a warning if this happens, and ``keep_and_fail`` will make the module fail.
+
+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_set:
+ state: present
+ zone_name: example.com
+ type: A # IPv4 addresses
+ record: www.example.com
+ value: []
+
+ - name: Remove TXT values for www.example.com
+ community.dns.hosttech_dns_record_set:
+ zone_name: example.com
+ type: TXT
+ prefix: www
+ state: absent
+
+ - name: Remove specific AAAA values for www.example.com
+ community.dns.hosttech_dns_record_set:
+ zone_name: example.com
+ type: AAAA # IPv6 addresses
+ prefix: www
+ state: absent
+ on_existing: keep_and_fail
+ ttl: 300
+ value:
+ - '::1'
+
+In the third example, ``on_existing: keep_and_fail`` is present and 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, but fail. This can be useful to not accidentally remove values you do not want to change. To issue a warning instead of failing, use ``on_existing: keep_and_warn``, and to simply not do a change without any indication of this situation, use ``on_existing: keep``.
+
+Bulk synchronization of DNS record sets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 :ref:`community.dns.hosttech_dns_record_sets module <ansible_collections.community.dns.hosttech_dns_record_sets_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_record_sets:
+ zone_name: 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_record_sets:
+ zone_name: 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