diff options
Diffstat (limited to 'ansible_collections/ngine_io/exoscale')
21 files changed, 1562 insertions, 0 deletions
diff --git a/ansible_collections/ngine_io/exoscale/.github/workflows/publish.yml b/ansible_collections/ngine_io/exoscale/.github/workflows/publish.yml new file mode 100644 index 000000000..0318edfc4 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/.github/workflows/publish.yml @@ -0,0 +1,25 @@ +name: Upload release to Galaxy + +on: + release: + types: [created] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ansible + - name: Build and publish + env: + ANSIBLE_GALAXY_API_KEY: ${{ secrets.ANSIBLE_GALAXY_API_KEY }} + run: | + ansible-galaxy collection build . + ansible-galaxy collection publish *.tar.gz --api-key $ANSIBLE_GALAXY_API_KEY diff --git a/ansible_collections/ngine_io/exoscale/.github/workflows/sanity.yml b/ansible_collections/ngine_io/exoscale/.github/workflows/sanity.yml new file mode 100644 index 000000000..7e0fab5b9 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/.github/workflows/sanity.yml @@ -0,0 +1,31 @@ +name: Sanity +on: +- pull_request + +jobs: + sanity: + name: Sanity (${{ matrix.ansible }}) + strategy: + matrix: + ansible: + - stable-2.10 + - stable-2.9 + - devel + runs-on: ubuntu-latest + steps: + + - name: Check out code + uses: actions/checkout@v1 + with: + path: ansible_collections/ngine_io/exoscale + + - name: Set up Python 3.6 + uses: actions/setup-python@v1 + with: + python-version: 3.6 + + - name: Install ansible-base (${{ matrix.ansible }}) + run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check + + - name: Run sanity tests + run: ansible-test sanity --docker -v --color --python 3.6 diff --git a/ansible_collections/ngine_io/exoscale/CHANGELOG.rst b/ansible_collections/ngine_io/exoscale/CHANGELOG.rst new file mode 100644 index 000000000..54909f89b --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/CHANGELOG.rst @@ -0,0 +1,9 @@ +========================================= +Exoscale Ansible Collection Release Notes +========================================= + +.. contents:: Topics + + +v1.0.0 +====== diff --git a/ansible_collections/ngine_io/exoscale/CONTRIBUTING.md b/ansible_collections/ngine_io/exoscale/CONTRIBUTING.md new file mode 100644 index 000000000..44683c135 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/CONTRIBUTING.md @@ -0,0 +1,6 @@ +# Contributing + +Any contribution is welcome and we only ask contributors to: + +- Create an issues for any significant contribution that would change a large portion of the code base. +- Provide at least integration tests for any contribution diff --git a/ansible_collections/ngine_io/exoscale/FILES.json b/ansible_collections/ngine_io/exoscale/FILES.json new file mode 100644 index 000000000..f725ab2d6 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/FILES.json @@ -0,0 +1,250 @@ +{ + "files": [ + { + "name": ".", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy/roles", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy/roles/test_exoscale_dns", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy/roles/test_exoscale_dns/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy/roles/test_exoscale_dns/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4e0ebd8ef1cdaf150fbcf76859542f017fc0203ca642dff07f0600337760491b", + "format": 1 + }, + { + "name": "tests/legacy/roles/test_exoscale_dns/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/legacy/roles/test_exoscale_dns/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ed720423a1d55815026eca860e4b39dd0f6609775f2cab3c07642720a3c448d7", + "format": 1 + }, + { + "name": "tests/legacy/exoscale.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "38d542d66924d6e8fd7991ffc2e73544cfd7f88cdd4734ba47734b8ec86ea3fb", + "format": 1 + }, + { + "name": "CHANGELOG.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3a697694dc57ace9e8600b5b2afbff42deeb76739d55cf66d844aec1ebb5dbf", + "format": 1 + }, + { + "name": "CONTRIBUTING.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d61725d614410e2ee0a900fb0f6b6d742ad8fb689ae27c4d6a3a7f89e82fc791", + "format": 1 + }, + { + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta/runtime.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "65ddf4c03edf730c4bf7da2184d83dfd28e790cb816ef1f9d82904273cb0c854", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "476a74dcdd9be0337c38135c7ab2f0f65de2ab4fdff679ceaa66b04f3e844811", + "format": 1 + }, + { + "name": "plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/doc_fragments/exoscale.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c484b770aa74ea4fbd70bf2f673af2e7f469ad732e818223152a356a5b9fd861", + "format": 1 + }, + { + "name": "plugins/module_utils", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/module_utils/exoscale.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "27754664282f766b3ad37dde8ac45d67495e3bc599e4bfa4a089a11819038311", + "format": 1 + }, + { + "name": "plugins/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/modules/exo_dns_domain.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fe708671d29b57cdf89f39aee4b0f81672db58030a92b832bf6b78008e080b80", + "format": 1 + }, + { + "name": "plugins/modules/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/modules/exo_dns_record.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "920ee4da3ced628cec9e998467ec04cd84db296b47e36225cf0693445fa483a9", + "format": 1 + }, + { + "name": "changelogs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6077ffbd67c5ad687d45cb43010521973fe662e82c2f167c5121016803861cea", + "format": 1 + }, + { + "name": "changelogs/fragments", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/fragments/.keep", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "changelogs/.gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "919ef00776e7d2ff349950ac4b806132aa9faf006e214d5285de54533e443b33", + "format": 1 + }, + { + "name": "changelogs/changelog.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2dbaa843cb55fda031c7fa291a37ff6a59c596763cce1eaf97fd72b3a1761d92", + "format": 1 + }, + { + "name": ".github", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows/publish.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c529e2810ae1f02ea98dcae1b78241d21a5988496ed5389b2ce8c37395323756", + "format": 1 + }, + { + "name": ".github/workflows/sanity.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "33964a78f085244db7db9904c39776a726cd4cfef48c3b1dcb5e1cf57714d223", + "format": 1 + } + ], + "format": 1 +}
\ No newline at end of file diff --git a/ansible_collections/ngine_io/exoscale/MANIFEST.json b/ansible_collections/ngine_io/exoscale/MANIFEST.json new file mode 100644 index 000000000..acebe1576 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/MANIFEST.json @@ -0,0 +1,35 @@ +{ + "collection_info": { + "namespace": "ngine_io", + "name": "exoscale", + "version": "1.0.0", + "authors": [ + "Ren\u00e9 Moser <mail@renemoser.net>" + ], + "readme": "README.md", + "tags": [ + "cloud", + "dns", + "exoscale", + "ngine_io" + ], + "description": "Ansible Collection for Exoscale", + "license": [ + "GPL-3.0-or-later" + ], + "license_file": null, + "dependencies": {}, + "repository": "https://github.com/ngine-io/ansible-collection-exoscale", + "documentation": "", + "homepage": "https://github.com/ngine-io/ansible-collection-exoscale", + "issues": "https://github.com/ngine-io/ansible-collection-exoscale/issues" + }, + "file_manifest_file": { + "name": "FILES.json", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dbbe7cf8b0656632d858a3bcec7ed6049ee30663c1ed9488392b80c53311d4a4", + "format": 1 + }, + "format": 1 +}
\ No newline at end of file diff --git a/ansible_collections/ngine_io/exoscale/README.md b/ansible_collections/ngine_io/exoscale/README.md new file mode 100644 index 000000000..824f6b779 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/README.md @@ -0,0 +1,72 @@ +![Collection integration](https://github.com/ngine-io/ansible-collection-exoscale/workflows/Collection%20integration/badge.svg) + [![Codecov](https://img.shields.io/codecov/c/github/ngine-io/ansible-collection-exoscale)](https://codecov.io/gh/ngine-io/ansible-collection-exoscale) +[![License](https://img.shields.io/badge/license-GPL%20v3.0-brightgreen.svg)](LICENSE) + +# Ansible Collection for exoscale Cloud + +This collection provides a series of Ansible modules and plugins for interacting with the [exoscale](https://www.exoscale.com) Cloud. + +## Requirements + +- ansible version >= 2.9 + +## Installation + +To install the collection hosted in Galaxy: + +```bash +ansible-galaxy collection install ngine_io.exoscale +``` + +To upgrade to the latest version of the collection: + +```bash +ansible-galaxy collection install ngine_io.exoscale --force +``` + +## Usage + +### Playbooks + +To use a module from exoscale collection, please reference the full namespace, collection name, and modules name that you want to use: + +```yaml +--- +- name: Using exoscale collection + hosts: localhost + tasks: + - ngine_io.exoscale.<module>: + ... +``` + +Or you can add full namepsace and collecton name in the `collections` element: + +```yaml +--- +- name: Using exoscale collection + hosts: localhost + collections: + - ngine_io.exoscale + tasks: + - <module>: + ... +``` + +### Roles + +For existing Ansible roles, please also reference the full namespace, collection name, and modules name which used in tasks instead of just modules name. + +## Contributing + +There are many ways in which you can participate in the project, for example: + +- Submit bugs and feature requests, and help us verify as they are checked in +- Review source code changes +- Review the documentation and make pull requests for anything from typos to new content +- If you are interested in fixing issues and contributing directly to the code base, please see the [CONTRIBUTING](CONTRIBUTING.md) document. + +## License + +GNU General Public License v3.0 + +See [COPYING](COPYING) to see the full text. diff --git a/ansible_collections/ngine_io/exoscale/changelogs/.gitignore b/ansible_collections/ngine_io/exoscale/changelogs/.gitignore new file mode 100644 index 000000000..6be6b5331 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/changelogs/.gitignore @@ -0,0 +1 @@ +/.plugin-cache.yaml diff --git a/ansible_collections/ngine_io/exoscale/changelogs/changelog.yaml b/ansible_collections/ngine_io/exoscale/changelogs/changelog.yaml new file mode 100644 index 000000000..4eef701ce --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/changelogs/changelog.yaml @@ -0,0 +1,4 @@ +ancestor: null +releases: + 1.0.0: + release_date: '2020-08-15' diff --git a/ansible_collections/ngine_io/exoscale/changelogs/config.yaml b/ansible_collections/ngine_io/exoscale/changelogs/config.yaml new file mode 100644 index 000000000..969c215e5 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/changelogs/config.yaml @@ -0,0 +1,30 @@ +changelog_filename_template: ../CHANGELOG.rst +changelog_filename_version_depth: 0 +changes_file: changelog.yaml +changes_format: combined +keep_fragments: false +mention_ancestor: true +new_plugins_after_name: removed_features +notesdir: fragments +prelude_section_name: release_summary +prelude_section_title: Release Summary +sections: +- - major_changes + - Major Changes +- - minor_changes + - Minor Changes +- - breaking_changes + - Breaking Changes / Porting Guide +- - deprecated_features + - Deprecated Features +- - removed_features + - Removed Features (previously deprecated) +- - security_fixes + - Security Fixes +- - bugfixes + - Bugfixes +- - known_issues + - Known Issues +title: Exoscale Ansible Collection +trivial_section_name: trivial +use_fqcn: true diff --git a/ansible_collections/ngine_io/exoscale/changelogs/fragments/.keep b/ansible_collections/ngine_io/exoscale/changelogs/fragments/.keep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/changelogs/fragments/.keep diff --git a/ansible_collections/ngine_io/exoscale/meta/runtime.yml b/ansible_collections/ngine_io/exoscale/meta/runtime.yml new file mode 100644 index 000000000..cf7c04dc2 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/meta/runtime.yml @@ -0,0 +1,5 @@ +requires_ansible: '>=2.9.10' +action_groups: + exoscale: + - exo_dns_domain + - exo_dns_record diff --git a/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/__init__.py b/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/__init__.py diff --git a/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/exoscale.py b/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/exoscale.py new file mode 100644 index 000000000..52ea2cd49 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/doc_fragments/exoscale.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2017, René Moser <mail@renemoser.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +class ModuleDocFragment(object): + + # Standard exoscale documentation fragment + DOCUMENTATION = r''' +options: + api_key: + description: + - API key of the Exoscale DNS API. + - The ENV variable C(CLOUDSTACK_KEY) is used as default, when defined. + type: str + api_secret: + description: + - Secret key of the Exoscale DNS API. + - The ENV variable C(CLOUDSTACK_SECRET) is used as default, when defined. + type: str + api_timeout: + description: + - HTTP timeout to Exoscale DNS API. + - The ENV variable C(CLOUDSTACK_TIMEOUT) is used as default, when defined. + type: int + default: 10 + api_region: + description: + - Name of the ini section in the C(cloustack.ini) file. + - The ENV variable C(CLOUDSTACK_REGION) is used as default, when defined. + type: str + default: cloudstack + validate_certs: + description: + - Validate SSL certs of the Exoscale DNS API. + type: bool + default: yes +requirements: + - python >= 2.6 +notes: + - As Exoscale DNS uses the same API key and secret for all services, we reuse the config used for Exscale Compute based on CloudStack. + The config is read from several locations, in the following order. + The C(CLOUDSTACK_KEY), C(CLOUDSTACK_SECRET) environment variables. + A C(CLOUDSTACK_CONFIG) environment variable pointing to an C(.ini) file, + A C(cloudstack.ini) file in the current working directory. + A C(.cloudstack.ini) file in the users home directory. + Optionally multiple credentials and endpoints can be specified using ini sections in C(cloudstack.ini). + Use the argument C(api_region) to select the section name, default section is C(cloudstack). + - This module does not support multiple A records and will complain properly if you try. + - More information Exoscale DNS can be found on https://community.exoscale.ch/documentation/dns/. + - This module supports check mode and diff. +''' diff --git a/ansible_collections/ngine_io/exoscale/plugins/module_utils/exoscale.py b/ansible_collections/ngine_io/exoscale/plugins/module_utils/exoscale.py new file mode 100644 index 000000000..44933b1b0 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/module_utils/exoscale.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2016, René Moser <mail@renemoser.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +import os + +from ansible.module_utils.six.moves import configparser +from ansible.module_utils.six import integer_types, string_types +from ansible.module_utils._text import to_native, to_text +from ansible.module_utils.urls import fetch_url + +EXO_DNS_BASEURL = "https://api.exoscale.ch/dns/v1" + + +def exo_dns_argument_spec(): + return dict( + api_key=dict(type='str', default=os.environ.get('CLOUDSTACK_KEY'), no_log=True), + api_secret=dict(type='str', default=os.environ.get('CLOUDSTACK_SECRET'), no_log=True), + api_timeout=dict(type='int', default=os.environ.get('CLOUDSTACK_TIMEOUT') or 10), + api_region=dict(type='str', default=os.environ.get('CLOUDSTACK_REGION') or 'cloudstack'), + validate_certs=dict(default=True, type='bool'), + ) + + +def exo_dns_required_together(): + return [['api_key', 'api_secret']] + + +class ExoDns(object): + + def __init__(self, module): + self.module = module + + self.api_key = self.module.params.get('api_key') + self.api_secret = self.module.params.get('api_secret') + if not (self.api_key and self.api_secret): + try: + region = self.module.params.get('api_region') + config = self.read_config(ini_group=region) + self.api_key = config['key'] + self.api_secret = config['secret'] + except Exception as e: + self.module.fail_json(msg="Error while processing config: %s" % to_native(e)) + + self.headers = { + 'X-DNS-Token': "%s:%s" % (self.api_key, self.api_secret), + 'Content-Type': 'application/json', + 'Accept': 'application/json', + } + self.result = { + 'changed': False, + 'diff': { + 'before': {}, + 'after': {}, + } + } + + def read_config(self, ini_group=None): + if not ini_group: + ini_group = os.environ.get('CLOUDSTACK_REGION', 'cloudstack') + + keys = ['key', 'secret'] + env_conf = {} + for key in keys: + if 'CLOUDSTACK_%s' % key.upper() not in os.environ: + break + else: + env_conf[key] = os.environ['CLOUDSTACK_%s' % key.upper()] + else: + return env_conf + + # Config file: $PWD/cloudstack.ini or $HOME/.cloudstack.ini + # Last read wins in configparser + paths = ( + os.path.join(os.path.expanduser('~'), '.cloudstack.ini'), + os.path.join(os.getcwd(), 'cloudstack.ini'), + ) + # Look at CLOUDSTACK_CONFIG first if present + if 'CLOUDSTACK_CONFIG' in os.environ: + paths += (os.path.expanduser(os.environ['CLOUDSTACK_CONFIG']),) + if not any([os.path.exists(c) for c in paths]): + self.module.fail_json(msg="Config file not found. Tried : %s" % ", ".join(paths)) + + conf = configparser.ConfigParser() + conf.read(paths) + return dict(conf.items(ini_group)) + + def api_query(self, resource="/domains", method="GET", data=None): + url = EXO_DNS_BASEURL + resource + if data: + data = self.module.jsonify(data) + + response, info = fetch_url( + module=self.module, + url=url, + data=data, + method=method, + headers=self.headers, + timeout=self.module.params.get('api_timeout'), + ) + + if info['status'] not in (200, 201, 204): + self.module.fail_json(msg="%s returned %s, with body: %s" % (url, info['status'], info['msg'])) + + try: + return self.module.from_json(to_text(response.read())) + + except Exception as e: + self.module.fail_json(msg="Could not process response into json: %s" % to_native(e)) + + def has_changed(self, want_dict, current_dict, only_keys=None): + changed = False + for key, value in want_dict.items(): + # Optionally limit by a list of keys + if only_keys and key not in only_keys: + continue + # Skip None values + if value is None: + continue + if key in current_dict: + if isinstance(current_dict[key], integer_types): + if value != current_dict[key]: + self.result['diff']['before'][key] = current_dict[key] + self.result['diff']['after'][key] = value + changed = True + elif isinstance(current_dict[key], string_types): + if value.lower() != current_dict[key].lower(): + self.result['diff']['before'][key] = current_dict[key] + self.result['diff']['after'][key] = value + changed = True + else: + self.module.fail_json(msg="Unable to determine comparison for key %s" % key) + else: + self.result['diff']['after'][key] = value + changed = True + return changed diff --git a/ansible_collections/ngine_io/exoscale/plugins/modules/__init__.py b/ansible_collections/ngine_io/exoscale/plugins/modules/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/modules/__init__.py diff --git a/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_domain.py b/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_domain.py new file mode 100644 index 000000000..334c5c02b --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_domain.py @@ -0,0 +1,204 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016, René Moser <mail@renemoser.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: exo_dns_domain +short_description: Manages domain records on Exoscale DNS API. +description: + - Create and remove domain records. +author: "René Moser (@resmo)" +version_added: "0.1.0" +options: + name: + description: + - Name of the record. + required: true + type: str + state: + description: + - State of the resource. + default: present + choices: [ present, absent ] + type: str +extends_documentation_fragment: ngine_io.exoscale.exoscale +''' + +EXAMPLES = ''' +- name: Create a domain + exo_dns_domain: + name: example.com + +- name: Remove a domain + exo_dns_domain: + name: example.com + state: absent +''' + +RETURN = ''' +--- +exo_dns_domain: + description: API domain results + returned: success + type: complex + contains: + account_id: + description: Your account ID + returned: success + type: int + sample: 34569 + auto_renew: + description: Whether domain is auto renewed or not + returned: success + type: bool + sample: false + created_at: + description: When the domain was created + returned: success + type: str + sample: "2016-08-12T15:24:23.989Z" + expires_on: + description: When the domain expires + returned: success + type: str + sample: "2016-08-12T15:24:23.989Z" + id: + description: ID of the domain + returned: success + type: int + sample: "2016-08-12T15:24:23.989Z" + lockable: + description: Whether the domain is lockable or not + returned: success + type: bool + sample: true + name: + description: Domain name + returned: success + type: str + sample: example.com + record_count: + description: Number of records related to this domain + returned: success + type: int + sample: 5 + registrant_id: + description: ID of the registrant + returned: success + type: int + sample: null + service_count: + description: Number of services + returned: success + type: int + sample: 0 + state: + description: State of the domain + returned: success + type: str + sample: "hosted" + token: + description: Token + returned: success + type: str + sample: "r4NzTRp6opIeFKfaFYvOd6MlhGyD07jl" + unicode_name: + description: Domain name as unicode + returned: success + type: str + sample: "example.com" + updated_at: + description: When the domain was updated last. + returned: success + type: str + sample: "2016-08-12T15:24:23.989Z" + user_id: + description: ID of the user + returned: success + type: int + sample: null + whois_protected: + description: Whether the whois is protected or not + returned: success + type: bool + sample: false +''' + +from ansible.module_utils.basic import AnsibleModule +from ..module_utils.exoscale import ExoDns, exo_dns_argument_spec, exo_dns_required_together + + +class ExoDnsDomain(ExoDns): + + def __init__(self, module): + super(ExoDnsDomain, self).__init__(module) + self.name = self.module.params.get('name').lower() + + def get_domain(self): + domains = self.api_query("/domains", "GET") + for z in domains: + if z['domain']['name'].lower() == self.name: + return z + return None + + def present_domain(self): + domain = self.get_domain() + data = { + 'domain': { + 'name': self.name, + } + } + if not domain: + self.result['diff']['after'] = data['domain'] + self.result['changed'] = True + if not self.module.check_mode: + domain = self.api_query("/domains", "POST", data) + return domain + + def absent_domain(self): + domain = self.get_domain() + if domain: + self.result['diff']['before'] = domain + self.result['changed'] = True + if not self.module.check_mode: + self.api_query("/domains/%s" % domain['domain']['name'], "DELETE") + return domain + + def get_result(self, resource): + if resource: + self.result['exo_dns_domain'] = resource['domain'] + return self.result + + +def main(): + argument_spec = exo_dns_argument_spec() + argument_spec.update(dict( + name=dict(type='str', required=True), + state=dict(type='str', choices=['present', 'absent'], default='present'), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + required_together=exo_dns_required_together(), + supports_check_mode=True + ) + + exo_dns_domain = ExoDnsDomain(module) + if module.params.get('state') == "present": + resource = exo_dns_domain.present_domain() + else: + resource = exo_dns_domain.absent_domain() + result = exo_dns_domain.get_result(resource) + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_record.py b/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_record.py new file mode 100644 index 000000000..8da3491eb --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/plugins/modules/exo_dns_record.py @@ -0,0 +1,339 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2016, René Moser <mail@renemoser.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: exo_dns_record +short_description: Manages DNS records on Exoscale DNS. +description: + - Create, update and delete records. +author: "René Moser (@resmo)" +version_added: "0.1.0" +options: + name: + description: + - Name of the record. + default: "" + type: str + domain: + description: + - Domain the record is related to. + required: true + type: str + record_type: + description: + - Type of the record. + default: A + choices: [ A, ALIAS, CNAME, MX, SPF, URL, TXT, NS, SRV, NAPTR, PTR, AAAA, SSHFP, HINFO, POOL ] + aliases: [ rtype, type ] + type: str + content: + description: + - Content of the record. + - Required if C(state=present) or C(multiple=yes). + aliases: [ value, address ] + type: str + ttl: + description: + - TTL of the record in seconds. + default: 3600 + type: int + prio: + description: + - Priority of the record. + aliases: [ priority ] + type: int + multiple: + description: + - Whether there are more than one records with similar I(name) and I(record_type). + - Only allowed for a few record types, e.g. C(record_type=A), C(record_type=NS) or C(record_type=MX). + - I(content) will not be updated, instead it is used as a key to find existing records. + type: bool + default: no + state: + description: + - State of the record. + default: present + choices: [ present, absent ] + type: str +extends_documentation_fragment: ngine_io.exoscale.exoscale +''' + +EXAMPLES = ''' +- name: Create or update an A record + ngine_io.exoscale.exo_dns_record: + name: web-vm-1 + domain: example.com + content: 1.2.3.4 + +- name: Update an existing A record with a new IP + ngine_io.exoscale.exo_dns_record: + name: web-vm-1 + domain: example.com + content: 1.2.3.5 + +- name: Create another A record with same name + ngine_io.exoscale.exo_dns_record: + name: web-vm-1 + domain: example.com + content: 1.2.3.6 + multiple: yes + +- name: Create or update a CNAME record + ngine_io.exoscale.exo_dns_record: + name: www + domain: example.com + record_type: CNAME + content: web-vm-1 + +- name: Create another MX record + ngine_io.exoscale.exo_dns_record: + domain: example.com + record_type: MX + content: mx1.example.com + prio: 10 + multiple: yes + +- name: Delete one MX record out of multiple + ngine_io.exoscale.exo_dns_record: + domain: example.com + record_type: MX + content: mx1.example.com + multiple: yes + state: absent + +- name: Remove a single A record + ngine_io.exoscale.exo_dns_record: + name: www + domain: example.com + state: absent +''' + +RETURN = ''' +--- +exo_dns_record: + description: API record results + returned: success + type: complex + contains: + content: + description: value of the record + returned: success + type: str + sample: 1.2.3.4 + created_at: + description: When the record was created + returned: success + type: str + sample: "2016-08-12T15:24:23.989Z" + domain: + description: Name of the domain + returned: success + type: str + sample: example.com + domain_id: + description: ID of the domain + returned: success + type: int + sample: 254324 + id: + description: ID of the record + returned: success + type: int + sample: 254324 + name: + description: name of the record + returned: success + type: str + sample: www + parent_id: + description: ID of the parent + returned: success + type: int + sample: null + prio: + description: Priority of the record + returned: success + type: int + sample: 10 + record_type: + description: Priority of the record + returned: success + type: str + sample: A + system_record: + description: Whether the record is a system record or not + returned: success + type: bool + sample: false + ttl: + description: Time to live of the record + returned: success + type: int + sample: 3600 + updated_at: + description: When the record was updated + returned: success + type: str + sample: "2016-08-12T15:24:23.989Z" +''' + +from ansible.module_utils.basic import AnsibleModule +from ..module_utils.exoscale import ExoDns, exo_dns_argument_spec, exo_dns_required_together + + +EXO_RECORD_TYPES = [ + 'A', + 'ALIAS', + 'CNAME', + 'MX', + 'SPF', + 'URL', + 'TXT', + 'NS', + 'SRV', + 'NAPTR', + 'PTR', + 'AAAA', + 'SSHFP', + 'HINFO', + 'POOL' +] + + +class ExoDnsRecord(ExoDns): + + def __init__(self, module): + super(ExoDnsRecord, self).__init__(module) + + self.domain = self.module.params.get('domain').lower() + self.name = self.module.params.get('name').lower() + if self.name == self.domain: + self.name = "" + + self.multiple = self.module.params.get('multiple') + self.record_type = self.module.params.get('record_type') + self.content = self.module.params.get('content') + + def _create_record(self, record): + self.result['changed'] = True + data = { + 'record': { + 'name': self.name, + 'record_type': self.record_type, + 'content': self.content, + 'ttl': self.module.params.get('ttl'), + 'prio': self.module.params.get('prio'), + } + } + self.result['diff']['after'] = data['record'] + if not self.module.check_mode: + record = self.api_query("/domains/%s/records" % self.domain, "POST", data) + return record + + def _update_record(self, record): + data = { + 'record': { + 'name': self.name, + 'content': self.content, + 'ttl': self.module.params.get('ttl'), + 'prio': self.module.params.get('prio'), + } + } + if self.has_changed(data['record'], record['record']): + self.result['changed'] = True + if not self.module.check_mode: + record = self.api_query("/domains/%s/records/%s" % (self.domain, record['record']['id']), "PUT", data) + return record + + def get_record(self): + domain = self.module.params.get('domain') + records = self.api_query("/domains/%s/records" % domain, "GET") + + result = {} + for r in records: + + if r['record']['record_type'] != self.record_type: + continue + + r_name = r['record']['name'].lower() + r_content = r['record']['content'] + + if r_name == self.name: + if not self.multiple: + if result: + self.module.fail_json(msg="More than one record with record_type=%s and name=%s params. " + "Use multiple=yes for more than one record." % (self.record_type, self.name)) + else: + result = r + elif r_content == self.content: + return r + + return result + + def present_record(self): + record = self.get_record() + if not record: + record = self._create_record(record) + else: + record = self._update_record(record) + return record + + def absent_record(self): + record = self.get_record() + if record: + self.result['diff']['before'] = record + self.result['changed'] = True + if not self.module.check_mode: + self.api_query("/domains/%s/records/%s" % (self.domain, record['record']['id']), "DELETE") + return record + + def get_result(self, resource): + if resource: + self.result['exo_dns_record'] = resource['record'] + self.result['exo_dns_record']['domain'] = self.domain + return self.result + + +def main(): + argument_spec = exo_dns_argument_spec() + argument_spec.update(dict( + name=dict(type='str', default=''), + record_type=dict(type='str', choices=EXO_RECORD_TYPES, aliases=['rtype', 'type'], default='A'), + content=dict(type='str', aliases=['value', 'address']), + multiple=(dict(type='bool', default=False)), + ttl=dict(type='int', default=3600), + prio=dict(type='int', aliases=['priority']), + domain=dict(type='str', required=True), + state=dict(type='str', choices=['present', 'absent'], default='present'), + )) + + module = AnsibleModule( + argument_spec=argument_spec, + required_together=exo_dns_required_together(), + required_if=[ + ('state', 'present', ['content']), + ('multiple', True, ['content']), + ], + supports_check_mode=True, + ) + + exo_dns_record = ExoDnsRecord(module) + if module.params.get('state') == "present": + resource = exo_dns_record.present_record() + else: + resource = exo_dns_record.absent_record() + + result = exo_dns_record.get_result(resource) + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/ngine_io/exoscale/tests/legacy/exoscale.yml b/ansible_collections/ngine_io/exoscale/tests/legacy/exoscale.yml new file mode 100644 index 000000000..dbe5bb164 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/tests/legacy/exoscale.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + gather_facts: no + roles: + - role: test_exoscale_dns + tags: test_exoscale_dns diff --git a/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/defaults/main.yml b/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/defaults/main.yml new file mode 100644 index 000000000..a98c86904 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/defaults/main.yml @@ -0,0 +1,4 @@ +--- +exo_dns_domain_name: example.com +exo_dns_record_name_web: web +exo_dns_record_name_mx: mx diff --git a/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/tasks/main.yml b/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/tasks/main.yml new file mode 100644 index 000000000..1b0ecb6f2 --- /dev/null +++ b/ansible_collections/ngine_io/exoscale/tests/legacy/roles/test_exoscale_dns/tasks/main.yml @@ -0,0 +1,347 @@ +--- +- name: setup + ngine_io.exoscale.exo_dns_domain: + name: "{{ exo_dns_domain_name }}" + state: absent + register: result +- name: verify setup + assert: + that: + - result is successful + +- name: test fail if missing name + ngine_io.exoscale.exo_dns_domain: + register: result + ignore_errors: true +- name: verify results of fail if missing params + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: name"' + +- name: test create a domain + ngine_io.exoscale.exo_dns_domain: + name: "{{ exo_dns_domain_name }}" + register: result +- name: verify results of test create a domain + assert: + that: + - result is changed + - 'result.exo_dns_domain.name == "{{ exo_dns_domain_name }}"' + +- name: test create a domain idempotence + ngine_io.exoscale.exo_dns_domain: + name: "{{ exo_dns_domain_name }}" + register: result +- name: verify results of test create a domain idempotence + assert: + that: + - result is not changed + - 'result.exo_dns_domain.name == "{{ exo_dns_domain_name }}"' + +- name: test fail if missing required params + ngine_io.exoscale.exo_dns_record: + register: result + ignore_errors: true +- name: verify results of test fail if missing required params + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: domain"' + +- name: test fail if missing required params state=present + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "" + register: result + ignore_errors: true +- name: verify results of test fail if missing required params state=present + assert: + that: + - result is failed + - 'result.msg == "state is present but all of the following are missing: content"' + +- name: test create a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + content: 1.2.3.4 + register: result +- name: verify results of test create a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.4"' + +- name: test create a record idempotence + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + content: 1.2.3.4 + register: result +- name: verify results of test create a record + assert: + that: + - result is not changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.4"' + +- name: test update a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + content: 1.2.3.5 + ttl: 7200 + register: result +- name: verify results of test update a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + - 'result.exo_dns_record.ttl == 7200' + +- name: test update a record idempotence + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + content: 1.2.3.5 + ttl: 7200 + register: result +- name: verify results of test update a record idempotence + assert: + that: + - result is not changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + - 'result.exo_dns_record.ttl == 7200' + +- name: test delete a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + state: absent + register: result +- name: verify results of test create a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + - 'result.exo_dns_record.ttl == 7200' + +- name: test delete a record idempotence + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + state: absent + register: result +- name: verify results of test create a record idempotence + assert: + that: + - result is not changed + +- name: setup an existing MX record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + record_type: MX + name: "" + content: "mx2.{{ exo_dns_domain_name }}" + prio: 10 + register: result +- name: verify results of test create a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == ""' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "mx2.{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.prio == 10' + +- name: test create a MX record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + record_type: MX + name: "" + content: "mx1.{{ exo_dns_domain_name }}" + prio: 10 + register: result +- name: verify results of test create a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == ""' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "mx1.{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.prio == 10' + +- name: test update a MX record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + record_type: MX + name: "" + content: "mx1.{{ exo_dns_domain_name }}" + prio: 20 + tags: foo + register: result +- name: verify results of test create a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == ""' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "mx1.{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.prio == 20' + tags: foo + +- name: test delete a MX record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + record_type: MX + name: "" + content: "mx1.{{ exo_dns_domain_name }}" + state: absent + register: result +- name: verify results of test delete a MX record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == ""' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "mx1.{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.prio == 20' + +- name: test delete a MX record idempotence + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + record_type: MX + name: "" + content: "mx1.{{ exo_dns_domain_name }}" + state: absent + register: result +- name: verify results of test delete a MX record idempotence + assert: + that: + - result is not changed + +- name: test create first multiple a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.4 + register: result +- name: verify results of test create first multiple a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.4"' + +- name: test create another similar a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.5 + register: result +- name: verify results of test create another similar a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + - 'result.exo_dns_record.ttl == 3600' + +- name: test update another similar a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.5 + ttl: 7200 + register: result +- name: verify results of test create another similar a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + - 'result.exo_dns_record.ttl == 7200' + +- name: test create first multiple a record idempotence + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.4 + register: result +- name: verify results of test create first multiple a record idempotence + assert: + that: + - result is not changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.4"' + +- name: test delete similar a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.5 + state: absent + register: result +- name: verify results of test delete similar a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.5"' + +- name: test delete first similar a record + ngine_io.exoscale.exo_dns_record: + domain: "{{ exo_dns_domain_name }}" + name: "{{ exo_dns_record_name_web }}" + multiple: yes + content: 1.2.3.4 + state: absent + register: result +- name: verify results of test delete first similar a record + assert: + that: + - result is changed + - 'result.exo_dns_record.name == "{{ exo_dns_record_name_web }}"' + - 'result.exo_dns_record.domain == "{{ exo_dns_domain_name }}"' + - 'result.exo_dns_record.content == "1.2.3.4"' + +- name: test delete a domain + ngine_io.exoscale.exo_dns_domain: + name: "{{ exo_dns_domain_name }}" + state: absent + register: result +- name: verify results of test delete a domain + assert: + that: + - result is changed + - 'result.exo_dns_domain.name == "{{ exo_dns_domain_name }}"' + +- name: test delete a domain idempotence + ngine_io.exoscale.exo_dns_domain: + name: "{{ exo_dns_domain_name }}" + state: absent + register: result +- name: verify results of test delete a domain idempotence + assert: + that: + - result is not changed |