From e5bb9dab9df5164c3001a50bbb78230d6f24f7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Moser?= Date: Tue, 16 Jun 2020 17:12:47 +0200 Subject: [PATCH] cloudscale migrated to cloudscale_ch.cloud (#517) --- .github/BOTMETA.yml | 14 - plugins/doc_fragments/cloudscale.py | 30 - plugins/inventory/cloudscale.py | 211 ------ plugins/module_utils/cloudscale.py | 132 ---- .../cloudscale/cloudscale_floating_ip.py | 296 -------- .../cloud/cloudscale/cloudscale_server.py | 549 -------------- .../cloudscale/cloudscale_server_group.py | 232 ------ .../cloud/cloudscale/cloudscale_volume.py | 300 -------- plugins/modules/cloudscale_floating_ip.py | 1 - plugins/modules/cloudscale_server.py | 1 - plugins/modules/cloudscale_server_group.py | 1 - plugins/modules/cloudscale_volume.py | 1 - .../targets/cloudscale_common/aliases | 1 - .../cloudscale_common/defaults/main.yml | 19 - .../tasks/cleanup_floating_ips.yml | 17 - .../tasks/cleanup_server_groups.yml | 17 - .../tasks/cleanup_servers.yml | 17 - .../tasks/cleanup_volumes.yml | 17 - .../targets/cloudscale_common/tasks/main.yml | 6 - .../targets/cloudscale_floating_ip/aliases | 2 - .../cloudscale_floating_ip/meta/main.yml | 3 - .../tasks/floating_ip.yml | 129 ---- .../cloudscale_floating_ip/tasks/main.yml | 35 - .../tasks/unassigned.yml | 26 - .../targets/cloudscale_server/aliases | 2 - .../cloudscale_server/defaults/main.yml | 2 - .../targets/cloudscale_server/meta/main.yml | 3 - .../cloudscale_server/tasks/failures.yml | 53 -- .../targets/cloudscale_server/tasks/main.yml | 11 - .../targets/cloudscale_server/tasks/tests.yml | 676 ------------------ .../targets/cloudscale_server_group/aliases | 2 - .../cloudscale_server_group/meta/main.yml | 3 - .../tasks/failures.yml | 45 -- .../cloudscale_server_group/tasks/main.yml | 8 - .../cloudscale_server_group/tasks/tests.yml | 159 ---- .../targets/cloudscale_volume/aliases | 2 - .../targets/cloudscale_volume/meta/main.yml | 3 - .../cloudscale_volume/tasks/cleanup.yml | 5 - .../cloudscale_volume/tasks/failures.yml | 38 - .../targets/cloudscale_volume/tasks/main.yml | 11 - .../targets/cloudscale_volume/tasks/setup.yml | 9 - .../targets/cloudscale_volume/tasks/tests.yml | 262 ------- .../targets/inventory_cloudscale/aliases | 3 - .../filter_plugins/group_name.py | 17 - .../inventory-private.yml | 14 - .../inventory_cloudscale/inventory-public.yml | 14 - .../inventory_cloudscale/inventory-uuid.yml | 14 - .../playbooks/change-inventory-config.yml | 8 - .../playbooks/cleanup.yml | 17 - .../playbooks/common-asserts.yml | 50 -- .../inventory_cloudscale/playbooks/setup.yml | 74 -- .../playbooks/test-inventory.yml | 68 -- .../targets/inventory_cloudscale/runme.sh | 21 - tests/sanity/ignore-2.10.txt | 6 - 54 files changed, 3657 deletions(-) delete mode 100644 plugins/doc_fragments/cloudscale.py delete mode 100644 plugins/inventory/cloudscale.py delete mode 100644 plugins/module_utils/cloudscale.py delete mode 100644 plugins/modules/cloud/cloudscale/cloudscale_floating_ip.py delete mode 100644 plugins/modules/cloud/cloudscale/cloudscale_server.py delete mode 100644 plugins/modules/cloud/cloudscale/cloudscale_server_group.py delete mode 100644 plugins/modules/cloud/cloudscale/cloudscale_volume.py delete mode 120000 plugins/modules/cloudscale_floating_ip.py delete mode 120000 plugins/modules/cloudscale_server.py delete mode 120000 plugins/modules/cloudscale_server_group.py delete mode 120000 plugins/modules/cloudscale_volume.py delete mode 100644 tests/integration/targets/cloudscale_common/aliases delete mode 100644 tests/integration/targets/cloudscale_common/defaults/main.yml delete mode 100644 tests/integration/targets/cloudscale_common/tasks/cleanup_floating_ips.yml delete mode 100644 tests/integration/targets/cloudscale_common/tasks/cleanup_server_groups.yml delete mode 100644 tests/integration/targets/cloudscale_common/tasks/cleanup_servers.yml delete mode 100644 tests/integration/targets/cloudscale_common/tasks/cleanup_volumes.yml delete mode 100644 tests/integration/targets/cloudscale_common/tasks/main.yml delete mode 100644 tests/integration/targets/cloudscale_floating_ip/aliases delete mode 100644 tests/integration/targets/cloudscale_floating_ip/meta/main.yml delete mode 100644 tests/integration/targets/cloudscale_floating_ip/tasks/floating_ip.yml delete mode 100644 tests/integration/targets/cloudscale_floating_ip/tasks/main.yml delete mode 100644 tests/integration/targets/cloudscale_floating_ip/tasks/unassigned.yml delete mode 100644 tests/integration/targets/cloudscale_server/aliases delete mode 100644 tests/integration/targets/cloudscale_server/defaults/main.yml delete mode 100644 tests/integration/targets/cloudscale_server/meta/main.yml delete mode 100644 tests/integration/targets/cloudscale_server/tasks/failures.yml delete mode 100644 tests/integration/targets/cloudscale_server/tasks/main.yml delete mode 100644 tests/integration/targets/cloudscale_server/tasks/tests.yml delete mode 100644 tests/integration/targets/cloudscale_server_group/aliases delete mode 100644 tests/integration/targets/cloudscale_server_group/meta/main.yml delete mode 100644 tests/integration/targets/cloudscale_server_group/tasks/failures.yml delete mode 100644 tests/integration/targets/cloudscale_server_group/tasks/main.yml delete mode 100644 tests/integration/targets/cloudscale_server_group/tasks/tests.yml delete mode 100644 tests/integration/targets/cloudscale_volume/aliases delete mode 100644 tests/integration/targets/cloudscale_volume/meta/main.yml delete mode 100644 tests/integration/targets/cloudscale_volume/tasks/cleanup.yml delete mode 100644 tests/integration/targets/cloudscale_volume/tasks/failures.yml delete mode 100644 tests/integration/targets/cloudscale_volume/tasks/main.yml delete mode 100644 tests/integration/targets/cloudscale_volume/tasks/setup.yml delete mode 100644 tests/integration/targets/cloudscale_volume/tasks/tests.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/aliases delete mode 100644 tests/integration/targets/inventory_cloudscale/filter_plugins/group_name.py delete mode 100644 tests/integration/targets/inventory_cloudscale/inventory-private.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/inventory-public.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/inventory-uuid.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/playbooks/change-inventory-config.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/playbooks/cleanup.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/playbooks/common-asserts.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/playbooks/setup.yml delete mode 100644 tests/integration/targets/inventory_cloudscale/playbooks/test-inventory.yml delete mode 100755 tests/integration/targets/inventory_cloudscale/runme.sh diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 6948d3f447..2ef360a59b 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -131,9 +131,6 @@ files: labels: infoblox networking $module_utils/: labels: module_utils - $module_utils/cloudscale.py: - maintainers: $team_cloudscale - labels: cloudscale $module_utils/docker/: maintainers: $team_docker labels: cloud @@ -203,16 +200,6 @@ files: authors: krsacme $modules/cloud/centurylink/: authors: clc-runner - $modules/cloud/cloudscale/cloudscale_floating_ip.py: - authors: gaudenz href - maintainers: resmo - $modules/cloud/cloudscale/cloudscale_server.py: - authors: gaudenz href resmo - $modules/cloud/cloudscale/cloudscale_server_group.py: - authors: href resmo - maintainers: gaudenz - $modules/cloud/cloudscale/cloudscale_volume.py: - authors: gaudenz href resmo $modules/cloud/digital_ocean/digital_ocean.py: authors: zbal $modules/cloud/digital_ocean/: @@ -1383,7 +1370,6 @@ macros: terminals: plugins/terminal team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross team_bsd: JoergFiedler MacLemon bcoca dch jasperla mekanix opoplawski overhacked tuxillo - team_cloudscale: gaudenz resmo team_cyberark_conjur: jvanderhoof ryanprior team_digital_ocean: BondAnthony mgregson team_docker: DBendit WojciechowskiPiotr akshay196 danihodovic dariko felixfontein jwitko kassiansun tbouvet diff --git a/plugins/doc_fragments/cloudscale.py b/plugins/doc_fragments/cloudscale.py deleted file mode 100644 index c7c58819bd..0000000000 --- a/plugins/doc_fragments/cloudscale.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, René Moser -# 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 cloudstack documentation fragment - DOCUMENTATION = ''' -options: - api_token: - description: - - cloudscale.ch API token. - - This can also be passed in the C(CLOUDSCALE_API_TOKEN) environment variable. - type: str - api_timeout: - description: - - Timeout in seconds for calls to the cloudscale.ch API. - default: 30 - type: int -notes: - - Instead of the api_token parameter the C(CLOUDSCALE_API_TOKEN) environment variable can be used. - - All operations are performed using the cloudscale.ch public API v1. - - "For details consult the full API documentation: U(https://www.cloudscale.ch/en/api/v1)." - - A valid API token is required for all operations. You can create as many tokens as you like using the cloudscale.ch control panel at - U(https://control.cloudscale.ch). -''' diff --git a/plugins/inventory/cloudscale.py b/plugins/inventory/cloudscale.py deleted file mode 100644 index 5f8be5d34e..0000000000 --- a/plugins/inventory/cloudscale.py +++ /dev/null @@ -1,211 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Gaudenz Steinlin -# 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 = ''' ---- -name: cloudscale -plugin_type: inventory -author: - - Gaudenz Steinlin (@gaudenz) -short_description: cloudscale.ch inventory source -description: - - Get inventory hosts from cloudscale.ch API - - Uses an YAML configuration file ending with either I(cloudscale.yml) or I(cloudscale.yaml) to set parameter values (also see examples). -extends_documentation_fragment: - - constructed -options: - plugin: - description: | - Token that ensures this is a source file for the 'cloudscale' - plugin. - required: True - choices: ['cloudscale'] - inventory_hostname: - description: | - What to register as the inventory hostname. - If set to 'uuid' the uuid of the server will be used and a - group will be created for the server name. - If set to 'name' the name of the server will be used unless - there are more than one server with the same name in which - case the 'uuid' logic will be used. - type: str - choices: - - name - - uuid - default: "name" - ansible_host: - description: | - Which IP address to register as the ansible_host. If the - requested value does not exist or this is set to 'none', no - ansible_host will be set. - type: str - choices: - - public_v4 - - public_v6 - - private - - none - default: public_v4 - api_token: - description: cloudscale.ch API token - env: - - name: CLOUDSCALE_API_TOKEN - type: str - api_timeout: - description: Timeout in seconds for calls to the cloudscale.ch API. - default: 30 - type: int -''' - -EXAMPLES = r''' -# cloudscale.yml name ending file in YAML format -# Example command line: ansible-inventory --list -i inventory_cloudscale.yml - -plugin: cloudscale - -# Example grouping by tag key "project" -plugin: cloudscale -keyed_groups: - - prefix: project - key: cloudscale.tags.project - -# Example grouping by key "operating_system" lowercased and prefixed with "os" -plugin: cloudscale -keyed_groups: - - prefix: os - key: cloudscale.image.operating_system | lower -''' - -from collections import defaultdict -from json import loads - -from ansible.errors import AnsibleError -from ansible_collections.community.general.plugins.module_utils.cloudscale import API_URL -from ansible.module_utils.urls import open_url -from ansible.inventory.group import to_safe_group_name -from ansible.plugins.inventory import BaseInventoryPlugin, Constructable - -iface_type_map = { - 'public_v4': ('public', 4), - 'public_v6': ('public', 6), - 'private': ('private', 4), - 'none': (None, None), -} - - -class InventoryModule(BaseInventoryPlugin, Constructable): - - NAME = 'community.general.cloudscale' - - def _get_server_list(self): - # Get list of servers from cloudscale.ch API - response = open_url( - API_URL + '/servers', - headers={'Authorization': 'Bearer %s' % self._token} - ) - return loads(response.read()) - - def verify_file(self, path): - ''' - :param path: the path to the inventory config file - :return the contents of the config file - ''' - if super(InventoryModule, self).verify_file(path): - if path.endswith(('cloudscale.yml', 'cloudscale.yaml')): - return True - self.display.debug( - "cloudscale inventory filename must end with 'cloudscale.yml' or 'cloudscale.yaml'" - ) - return False - - def parse(self, inventory, loader, path, cache=True): - super(InventoryModule, self).parse(inventory, loader, path) - - self._read_config_data(path) - - self._token = self.get_option('api_token') - if not self._token: - raise AnsibleError('Could not find an API token. Set the ' - 'CLOUDSCALE_API_TOKEN environment variable.') - - inventory_hostname = self.get_option('inventory_hostname') - if inventory_hostname not in ('name', 'uuid'): - raise AnsibleError('Invalid value for option inventory_hostname: %s' - % inventory_hostname) - - ansible_host = self.get_option('ansible_host') - if ansible_host not in iface_type_map: - raise AnsibleError('Invalid value for option ansible_host: %s' - % ansible_host) - - # Merge servers with the same name - firstpass = defaultdict(list) - for server in self._get_server_list(): - firstpass[server['name']].append(server) - - # Add servers to inventory - for name, servers in firstpass.items(): - if len(servers) == 1 and inventory_hostname == 'name': - self.inventory.add_host(name) - servers[0]['inventory_hostname'] = name - else: - # Two servers with the same name exist, create a group - # with this name and add the servers by UUID - group_name = to_safe_group_name(name) - if group_name not in self.inventory.groups: - self.inventory.add_group(group_name) - for server in servers: - self.inventory.add_host(server['uuid'], group_name) - server['inventory_hostname'] = server['uuid'] - - # Set variables - iface_type, iface_version = iface_type_map[ansible_host] - for server in servers: - hostname = server.pop('inventory_hostname') - if ansible_host != 'none': - addresses = [address['address'] - for interface in server['interfaces'] - for address in interface['addresses'] - if interface['type'] == iface_type - and address['version'] == iface_version] - - if len(addresses) > 0: - self.inventory.set_variable( - hostname, - 'ansible_host', - addresses[0], - ) - self.inventory.set_variable( - hostname, - 'cloudscale', - server, - ) - - variables = self.inventory.hosts[hostname].get_vars() - # Set composed variables - self._set_composite_vars( - self.get_option('compose'), - variables, - hostname, - self.get_option('strict'), - ) - - # Add host to composed groups - self._add_host_to_composed_groups( - self.get_option('groups'), - variables, - hostname, - self.get_option('strict'), - ) - - # Add host to keyed groups - self._add_host_to_keyed_groups( - self.get_option('keyed_groups'), - variables, - hostname, - self.get_option('strict'), - ) diff --git a/plugins/module_utils/cloudscale.py b/plugins/module_utils/cloudscale.py deleted file mode 100644 index 01f72bd21f..0000000000 --- a/plugins/module_utils/cloudscale.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -# -# (c) 2017, Gaudenz Steinlin -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from copy import deepcopy -from ansible.module_utils.basic import env_fallback -from ansible.module_utils.urls import fetch_url -from ansible.module_utils._text import to_text - -API_URL = 'https://api.cloudscale.ch/v1/' - - -def cloudscale_argument_spec(): - return dict( - api_token=dict(fallback=(env_fallback, ['CLOUDSCALE_API_TOKEN']), - no_log=True, - required=True, - type='str'), - api_timeout=dict(default=30, type='int'), - ) - - -class AnsibleCloudscaleBase(object): - - def __init__(self, module): - self._module = module - self._auth_header = {'Authorization': 'Bearer %s' % module.params['api_token']} - self._result = { - 'changed': False, - 'diff': dict(before=dict(), after=dict()), - } - - def _get(self, api_call): - resp, info = fetch_url(self._module, API_URL + api_call, - headers=self._auth_header, - timeout=self._module.params['api_timeout']) - - if info['status'] == 200: - return self._module.from_json(to_text(resp.read(), errors='surrogate_or_strict')) - elif info['status'] == 404: - return None - else: - self._module.fail_json(msg='Failure while calling the cloudscale.ch API with GET for ' - '"%s".' % api_call, fetch_url_info=info) - - def _post_or_patch(self, api_call, method, data): - # This helps with tags when we have the full API resource href to update. - if API_URL not in api_call: - api_endpoint = API_URL + api_call - else: - api_endpoint = api_call - - headers = self._auth_header.copy() - if data is not None: - # Sanitize data dictionary - # Deepcopy: Duplicate the data object for iteration, because - # iterating an object and changing it at the same time is insecure - for k, v in deepcopy(data).items(): - if v is None: - del data[k] - - data = self._module.jsonify(data) - headers['Content-type'] = 'application/json' - - resp, info = fetch_url(self._module, - api_endpoint, - headers=headers, - method=method, - data=data, - timeout=self._module.params['api_timeout']) - - if info['status'] in (200, 201): - return self._module.from_json(to_text(resp.read(), errors='surrogate_or_strict')) - elif info['status'] == 204: - return None - else: - self._module.fail_json(msg='Failure while calling the cloudscale.ch API with %s for ' - '"%s".' % (method, api_call), fetch_url_info=info) - - def _post(self, api_call, data=None): - return self._post_or_patch(api_call, 'POST', data) - - def _patch(self, api_call, data=None): - return self._post_or_patch(api_call, 'PATCH', data) - - def _delete(self, api_call): - resp, info = fetch_url(self._module, - API_URL + api_call, - headers=self._auth_header, - method='DELETE', - timeout=self._module.params['api_timeout']) - - if info['status'] == 204: - return None - else: - self._module.fail_json(msg='Failure while calling the cloudscale.ch API with DELETE for ' - '"%s".' % api_call, fetch_url_info=info) - - def _param_updated(self, key, resource): - param = self._module.params.get(key) - if param is None: - return False - - if resource and key in resource: - if param != resource[key]: - self._result['changed'] = True - - patch_data = { - key: param - } - - self._result['diff']['before'].update({key: resource[key]}) - self._result['diff']['after'].update(patch_data) - - if not self._module.check_mode: - href = resource.get('href') - if not href: - self._module.fail_json(msg='Unable to update %s, no href found.' % key) - - self._patch(href, patch_data) - return True - return False - - def get_result(self, resource): - if resource: - for k, v in resource.items(): - self._result[k] = v - return self._result diff --git a/plugins/modules/cloud/cloudscale/cloudscale_floating_ip.py b/plugins/modules/cloud/cloudscale/cloudscale_floating_ip.py deleted file mode 100644 index 8059b16ff7..0000000000 --- a/plugins/modules/cloud/cloudscale/cloudscale_floating_ip.py +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2017, Gaudenz Steinlin -# 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: cloudscale_floating_ip -short_description: Manages floating IPs on the cloudscale.ch IaaS service -description: - - Create, assign and delete floating IPs on the cloudscale.ch IaaS service. -notes: - - To create a new floating IP at least the C(ip_version) and C(server) options are required. - - Once a floating_ip is created all parameters except C(server) are read-only. - - It's not possible to request a floating IP without associating it with a server at the same time. - - This module requires the ipaddress python library. This library is included in Python since version 3.3. It is available as a - module on PyPI for earlier versions. -author: - - Gaudenz Steinlin (@gaudenz) - - Denis Krienbühl (@href) -options: - state: - description: - - State of the floating IP. - default: present - choices: [ present, absent ] - type: str - ip: - description: - - Floating IP address to change. - - Required to assign the IP to a different server or if I(state) is absent. - aliases: [ network ] - type: str - ip_version: - description: - - IP protocol version of the floating IP. - choices: [ 4, 6 ] - type: int - server: - description: - - UUID of the server assigned to this floating IP. - - Required unless I(state) is absent. - type: str - type: - description: - - The type of the floating IP. - choices: [ regional, global ] - type: str - default: regional - region: - description: - - Region in which the floating IP resides (e.g. C(lgp) or C(rma)). - If omitted, the region of the project default zone is used. - This parameter must be omitted if I(type) is set to C(global). - type: str - version_added: '0.2.0' - prefix_length: - description: - - Only valid if I(ip_version) is 6. - - Prefix length for the IPv6 network. Currently only a prefix of /56 can be requested. If no I(prefix_length) is present, a - single address is created. - choices: [ 56 ] - type: int - reverse_ptr: - description: - - Reverse PTR entry for this address. - - You cannot set a reverse PTR entry for IPv6 floating networks. Reverse PTR entries are only allowed for single addresses. - type: str -extends_documentation_fragment: -- community.general.cloudscale - -''' - -EXAMPLES = ''' -# Request a new floating IP -- name: Request a floating IP - cloudscale_floating_ip: - ip_version: 4 - server: 47cec963-fcd2-482f-bdb6-24461b2d47b1 - reverse_ptr: my-server.example.com - api_token: xxxxxx - register: floating_ip - -# Assign an existing floating IP to a different server -- name: Move floating IP to backup server - cloudscale_floating_ip: - ip: 192.0.2.123 - server: ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - api_token: xxxxxx - -# Request a new floating IPv6 network -- name: Request a floating IP - cloudscale_floating_ip: - ip_version: 6 - prefix_length: 56 - server: 47cec963-fcd2-482f-bdb6-24461b2d47b1 - api_token: xxxxxx - region: lpg1 - register: floating_ip - -# Assign an existing floating network to a different server -- name: Move floating IP to backup server - cloudscale_floating_ip: - ip: '{{ floating_ip.network | ip }}' - server: ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - api_token: xxxxxx - -# Release a floating IP -- name: Release floating IP - cloudscale_floating_ip: - ip: 192.0.2.123 - state: absent - api_token: xxxxxx -''' - -RETURN = ''' -href: - description: The API URL to get details about this floating IP. - returned: success when state == present - type: str - sample: https://api.cloudscale.ch/v1/floating-ips/2001:db8::cafe -network: - description: The CIDR notation of the network that is routed to your server. - returned: success when state == present - type: str - sample: 2001:db8::cafe/128 -next_hop: - description: Your floating IP is routed to this IP address. - returned: success when state == present - type: str - sample: 2001:db8:dead:beef::42 -reverse_ptr: - description: The reverse pointer for this floating IP address. - returned: success when state == present - type: str - sample: 185-98-122-176.cust.cloudscale.ch -server: - description: The floating IP is routed to this server. - returned: success when state == present - type: str - sample: 47cec963-fcd2-482f-bdb6-24461b2d47b1 -ip: - description: The floating IP address or network. This is always present and used to identify floating IPs after creation. - returned: success - type: str - sample: 185.98.122.176 -region: - description: The region of the floating IP. - returned: success when state == present - type: dict - sample: {'slug': 'lpg'} - version_added: '0.2.0' -state: - description: The current status of the floating IP. - returned: success - type: str - sample: present -''' - -import traceback - -IPADDRESS_IMP_ERR = None -try: - from ipaddress import ip_network - HAS_IPADDRESS = True -except ImportError: - IPADDRESS_IMP_ERR = traceback.format_exc() - HAS_IPADDRESS = False - -from ansible.module_utils.basic import AnsibleModule, env_fallback, missing_required_lib -from ansible_collections.community.general.plugins.module_utils.cloudscale import AnsibleCloudscaleBase, cloudscale_argument_spec - - -class AnsibleCloudscaleFloatingIP(AnsibleCloudscaleBase): - - def __init__(self, module): - super(AnsibleCloudscaleFloatingIP, self).__init__(module) - - # Initialize info dict - # Set state to absent, will be updated by self.update_info() - self.info = {'state': 'absent'} - - if self._module.params['ip']: - self.update_info() - - @staticmethod - def _resp2info(resp): - # If the API response has some content, the floating IP must exist - resp['state'] = 'present' - - # Add the IP address to the response, otherwise handling get's to complicated as this - # has to be converted from the network all the time. - resp['ip'] = str(ip_network(resp['network']).network_address) - - # Replace the server with just the UUID, the href to the server is useless and just makes - # things more complicated - if resp['server'] is not None: - resp['server'] = resp['server']['uuid'] - - return resp - - def update_info(self): - resp = self._get('floating-ips/' + self._module.params['ip']) - if resp: - self.info = self._resp2info(resp) - else: - self.info = {'ip': self._module.params['ip'], - 'state': 'absent'} - - def request_floating_ip(self): - params = self._module.params - - # check for required parameters to request a floating IP - missing_parameters = [] - for p in ('ip_version', 'server'): - if p not in params or not params[p]: - missing_parameters.append(p) - - if len(missing_parameters) > 0: - self._module.fail_json(msg='Missing required parameter(s) to request a floating IP: %s.' % - ' '.join(missing_parameters)) - - data = {'ip_version': params['ip_version'], - 'server': params['server']} - - for p in ('prefix_length', 'reverse_ptr', 'type', 'region'): - if params[p]: - data[p] = params[p] - - self.info = self._resp2info(self._post('floating-ips', data)) - - def release_floating_ip(self): - self._delete('floating-ips/%s' % self._module.params['ip']) - self.info = {'ip': self.info['ip'], 'state': 'absent'} - - def update_floating_ip(self): - params = self._module.params - if 'server' not in params or not params['server']: - self._module.fail_json(msg='Missing required parameter to update a floating IP: server.') - self.info = self._resp2info(self._post('floating-ips/%s' % params['ip'], {'server': params['server']})) - - -def main(): - argument_spec = cloudscale_argument_spec() - argument_spec.update(dict( - state=dict(default='present', choices=('present', 'absent'), type='str'), - ip=dict(aliases=('network', ), type='str'), - ip_version=dict(choices=(4, 6), type='int'), - server=dict(type='str'), - type=dict(type='str', choices=('regional', 'global'), default='regional'), - region=dict(type='str'), - prefix_length=dict(choices=(56,), type='int'), - reverse_ptr=dict(type='str'), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=(('ip', 'ip_version'),), - supports_check_mode=True, - ) - - if not HAS_IPADDRESS: - module.fail_json(msg=missing_required_lib('ipaddress'), exception=IPADDRESS_IMP_ERR) - - target_state = module.params['state'] - target_server = module.params['server'] - floating_ip = AnsibleCloudscaleFloatingIP(module) - current_state = floating_ip.info['state'] - current_server = floating_ip.info['server'] if 'server' in floating_ip.info else None - - if module.check_mode: - module.exit_json(changed=not target_state == current_state or - (current_state == 'present' and current_server != target_server), - **floating_ip.info) - - changed = False - if current_state == 'absent' and target_state == 'present': - floating_ip.request_floating_ip() - changed = True - elif current_state == 'present' and target_state == 'absent': - floating_ip.release_floating_ip() - changed = True - elif current_state == 'present' and current_server != target_server: - floating_ip.update_floating_ip() - changed = True - - module.exit_json(changed=changed, **floating_ip.info) - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/cloud/cloudscale/cloudscale_server.py b/plugins/modules/cloud/cloudscale/cloudscale_server.py deleted file mode 100644 index b71743d6b0..0000000000 --- a/plugins/modules/cloud/cloudscale/cloudscale_server.py +++ /dev/null @@ -1,549 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2017, Gaudenz Steinlin -# Copyright: (c) 2019, René Moser -# 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: cloudscale_server -short_description: Manages servers on the cloudscale.ch IaaS service -description: - - Create, update, start, stop and delete servers on the cloudscale.ch IaaS service. -notes: - - Since version 2.8, I(uuid) and I(name) or not mutually exclusive anymore. - - If I(uuid) option is provided, it takes precedence over I(name) for server selection. This allows to update the server's name. - - If no I(uuid) option is provided, I(name) is used for server selection. If more than one server with this name exists, execution is aborted. - - Only the I(name) and I(flavor) are evaluated for the update. - - The option I(force=true) must be given to allow the reboot of existing running servers for applying the changes. -author: - - Gaudenz Steinlin (@gaudenz) - - René Moser (@resmo) - - Denis Krienbühl (@href) -options: - state: - description: - - State of the server. - choices: [ running, stopped, absent ] - default: running - type: str - name: - description: - - Name of the Server. - - Either I(name) or I(uuid) are required. - type: str - uuid: - description: - - UUID of the server. - - Either I(name) or I(uuid) are required. - type: str - flavor: - description: - - Flavor of the server. - type: str - image: - description: - - Image used to create the server. - type: str - zone: - description: - - Zone in which the server resides (e.g. C(lgp1) or C(rma1)). - type: str - version_added: '0.2.0' - volume_size_gb: - description: - - Size of the root volume in GB. - default: 10 - type: int - bulk_volume_size_gb: - description: - - Size of the bulk storage volume in GB. - - No bulk storage volume if not set. - type: int - ssh_keys: - description: - - List of SSH public keys. - - Use the full content of your .pub file here. - type: list - password: - description: - - Password for the server. - type: str - use_public_network: - description: - - Attach a public network interface to the server. - default: yes - type: bool - use_private_network: - description: - - Attach a private network interface to the server. - default: no - type: bool - use_ipv6: - description: - - Enable IPv6 on the public network interface. - default: yes - type: bool - anti_affinity_with: - description: - - UUID of another server to create an anti-affinity group with. - - Mutually exclusive with I(server_groups). - - Deprecated, removed in community.general 2.0.0. - type: str - server_groups: - description: - - List of UUID or names of server groups. - - Mutually exclusive with I(anti_affinity_with). - type: list - user_data: - description: - - Cloud-init configuration (cloud-config) data to use for the server. - type: str - force: - description: - - Allow to stop the running server for updating if necessary. - default: no - type: bool - tags: - description: - - Tags assosiated with the servers. Set this to C({}) to clear any tags. - type: dict -extends_documentation_fragment: -- community.general.cloudscale - -''' - -EXAMPLES = ''' -# Create and start a server with an existing server group (shiny-group) -- name: Start cloudscale.ch server - cloudscale_server: - name: my-shiny-cloudscale-server - image: debian-8 - flavor: flex-4 - ssh_keys: ssh-rsa XXXXXXXXXX...XXXX ansible@cloudscale - server_groups: shiny-group - zone: lpg1 - use_private_network: True - bulk_volume_size_gb: 100 - api_token: xxxxxx - -# Start another server in anti-affinity (server group shiny-group) -- name: Start second cloudscale.ch server - cloudscale_server: - name: my-other-shiny-server - image: ubuntu-16.04 - flavor: flex-8 - ssh_keys: ssh-rsa XXXXXXXXXXX ansible@cloudscale - server_groups: shiny-group - zone: lpg1 - api_token: xxxxxx - - -# Force to update the flavor of a running server -- name: Start cloudscale.ch server - cloudscale_server: - name: my-shiny-cloudscale-server - image: debian-8 - flavor: flex-8 - force: yes - ssh_keys: ssh-rsa XXXXXXXXXX...XXXX ansible@cloudscale - use_private_network: True - bulk_volume_size_gb: 100 - api_token: xxxxxx - register: server1 - -# Stop the first server -- name: Stop my first server - cloudscale_server: - uuid: '{{ server1.uuid }}' - state: stopped - api_token: xxxxxx - -# Delete my second server -- name: Delete my second server - cloudscale_server: - name: my-other-shiny-server - state: absent - api_token: xxxxxx - -# Start a server and wait for the SSH host keys to be generated -- name: Start server and wait for SSH host keys - cloudscale_server: - name: my-cloudscale-server-with-ssh-key - image: debian-8 - flavor: flex-4 - ssh_keys: ssh-rsa XXXXXXXXXXX ansible@cloudscale - api_token: xxxxxx - register: server - until: server.ssh_fingerprints is defined and server.ssh_fingerprints - retries: 60 - delay: 2 -''' - -RETURN = ''' -href: - description: API URL to get details about this server - returned: success when not state == absent - type: str - sample: https://api.cloudscale.ch/v1/servers/cfde831a-4e87-4a75-960f-89b0148aa2cc -uuid: - description: The unique identifier for this server - returned: success - type: str - sample: cfde831a-4e87-4a75-960f-89b0148aa2cc -name: - description: The display name of the server - returned: success - type: str - sample: its-a-me-mario.cloudscale.ch -state: - description: The current status of the server - returned: success - type: str - sample: running -flavor: - description: The flavor that has been used for this server - returned: success when not state == absent - type: dict - sample: { "slug": "flex-4", "name": "Flex-4", "vcpu_count": 2, "memory_gb": 4 } -image: - description: The image used for booting this server - returned: success when not state == absent - type: dict - sample: { "default_username": "ubuntu", "name": "Ubuntu 18.04 LTS", "operating_system": "Ubuntu", "slug": "ubuntu-18.04" } -zone: - description: The zone used for booting this server - returned: success when not state == absent - type: dict - sample: { 'slug': 'lpg1' } - version_added: '0.2.0' -volumes: - description: List of volumes attached to the server - returned: success when not state == absent - type: list - sample: [ {"type": "ssd", "device": "/dev/vda", "size_gb": "50"} ] -interfaces: - description: List of network ports attached to the server - returned: success when not state == absent - type: list - sample: [ { "type": "public", "addresses": [ ... ] } ] -ssh_fingerprints: - description: A list of SSH host key fingerprints. Will be null until the host keys could be retrieved from the server. - returned: success when not state == absent - type: list - sample: ["ecdsa-sha2-nistp256 SHA256:XXXX", ... ] -ssh_host_keys: - description: A list of SSH host keys. Will be null until the host keys could be retrieved from the server. - returned: success when not state == absent - type: list - sample: ["ecdsa-sha2-nistp256 XXXXX", ... ] -anti_affinity_with: - description: - - List of servers in the same anti-affinity group - - Deprecated, removed in community.general 2.0.0. - returned: success when not state == absent - type: list - sample: [] -server_groups: - description: List of server groups - returned: success when not state == absent - type: list - sample: [ {"href": "https://api.cloudscale.ch/v1/server-groups/...", "uuid": "...", "name": "db-group"} ] -tags: - description: Tags assosiated with the volume. - returned: success - type: dict - sample: { 'project': 'my project' } -''' - -from datetime import datetime, timedelta -from time import sleep -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.community.general.plugins.module_utils.cloudscale import AnsibleCloudscaleBase, cloudscale_argument_spec - -ALLOWED_STATES = ('running', - 'stopped', - 'absent', - ) - - -class AnsibleCloudscaleServer(AnsibleCloudscaleBase): - - def __init__(self, module): - super(AnsibleCloudscaleServer, self).__init__(module) - - # Initialize server dictionary - self._info = {} - - def _init_server_container(self): - return { - 'uuid': self._module.params.get('uuid') or self._info.get('uuid'), - 'name': self._module.params.get('name') or self._info.get('name'), - 'state': 'absent', - } - - def _get_server_info(self, refresh=False): - if self._info and not refresh: - return self._info - - self._info = self._init_server_container() - - uuid = self._info.get('uuid') - if uuid is not None: - server_info = self._get('servers/%s' % uuid) - if server_info: - self._info = self._transform_state(server_info) - - else: - name = self._info.get('name') - if name is not None: - servers = self._get('servers') or [] - matching_server = [] - for server in servers: - if server['name'] == name: - matching_server.append(server) - - if len(matching_server) == 1: - self._info = self._transform_state(matching_server[0]) - elif len(matching_server) > 1: - self._module.fail_json(msg="More than one server with name '%s' exists. " - "Use the 'uuid' parameter to identify the server." % name) - - return self._info - - @staticmethod - def _transform_state(server): - if 'status' in server: - server['state'] = server['status'] - del server['status'] - else: - server['state'] = 'absent' - return server - - def _wait_for_state(self, states): - start = datetime.now() - timeout = self._module.params['api_timeout'] * 2 - while datetime.now() - start < timedelta(seconds=timeout): - server_info = self._get_server_info(refresh=True) - if server_info.get('state') in states: - return server_info - sleep(1) - - # Timeout succeeded - if server_info.get('name') is not None: - msg = "Timeout while waiting for a state change on server %s to states %s. " \ - "Current state is %s." % (server_info.get('name'), states, server_info.get('state')) - else: - name_uuid = self._module.params.get('name') or self._module.params.get('uuid') - msg = 'Timeout while waiting to find the server %s' % name_uuid - - self._module.fail_json(msg=msg) - - def _start_stop_server(self, server_info, target_state="running", ignore_diff=False): - actions = { - 'stopped': 'stop', - 'running': 'start', - } - - server_state = server_info.get('state') - if server_state != target_state: - self._result['changed'] = True - - if not ignore_diff: - self._result['diff']['before'].update({ - 'state': server_info.get('state'), - }) - self._result['diff']['after'].update({ - 'state': target_state, - }) - if not self._module.check_mode: - self._post('servers/%s/%s' % (server_info['uuid'], actions[target_state])) - server_info = self._wait_for_state((target_state, )) - - return server_info - - def _update_param(self, param_key, server_info, requires_stop=False): - param_value = self._module.params.get(param_key) - if param_value is None: - return server_info - - if 'slug' in server_info[param_key]: - server_v = server_info[param_key]['slug'] - else: - server_v = server_info[param_key] - - if server_v != param_value: - # Set the diff output - self._result['diff']['before'].update({param_key: server_v}) - self._result['diff']['after'].update({param_key: param_value}) - - if server_info.get('state') == "running": - if requires_stop and not self._module.params.get('force'): - self._module.warn("Some changes won't be applied to running servers. " - "Use force=yes to allow the server '%s' to be stopped/started." % server_info['name']) - return server_info - - # Either the server is stopped or change is forced - self._result['changed'] = True - if not self._module.check_mode: - - if requires_stop: - self._start_stop_server(server_info, target_state="stopped", ignore_diff=True) - - patch_data = { - param_key: param_value, - } - - # Response is 204: No Content - self._patch('servers/%s' % server_info['uuid'], patch_data) - - # State changes to "changing" after update, waiting for stopped/running - server_info = self._wait_for_state(('stopped', 'running')) - - return server_info - - def _get_server_group_ids(self): - server_group_params = self._module.params['server_groups'] - if not server_group_params: - return None - - matching_group_names = [] - results = [] - server_groups = self._get('server-groups') - for server_group in server_groups: - if server_group['uuid'] in server_group_params: - results.append(server_group['uuid']) - server_group_params.remove(server_group['uuid']) - - elif server_group['name'] in server_group_params: - results.append(server_group['uuid']) - server_group_params.remove(server_group['name']) - # Remember the names found - matching_group_names.append(server_group['name']) - - # Names are not unique, verify if name already found in previous iterations - elif server_group['name'] in matching_group_names: - self._module.fail_json(msg="More than one server group with name exists: '%s'. " - "Use the 'uuid' parameter to identify the server group." % server_group['name']) - - if server_group_params: - self._module.fail_json(msg="Server group name or UUID not found: %s" % ', '.join(server_group_params)) - - return results - - def _create_server(self, server_info): - self._result['changed'] = True - - data = deepcopy(self._module.params) - for i in ('uuid', 'state', 'force', 'api_timeout', 'api_token'): - del data[i] - data['server_groups'] = self._get_server_group_ids() - - self._result['diff']['before'] = self._init_server_container() - self._result['diff']['after'] = deepcopy(data) - if not self._module.check_mode: - self._post('servers', data) - server_info = self._wait_for_state(('running', )) - return server_info - - def _update_server(self, server_info): - - previous_state = server_info.get('state') - - # The API doesn't support to update server groups. - # Show a warning to the user if the desired state does not match. - desired_server_group_ids = self._get_server_group_ids() - if desired_server_group_ids is not None: - current_server_group_ids = [grp['uuid'] for grp in server_info['server_groups']] - if desired_server_group_ids != current_server_group_ids: - self._module.warn("Server groups can not be mutated, server needs redeployment to change groups.") - - server_info = self._update_param('flavor', server_info, requires_stop=True) - server_info = self._update_param('name', server_info) - server_info = self._update_param('tags', server_info) - - if previous_state == "running": - server_info = self._start_stop_server(server_info, target_state="running", ignore_diff=True) - - return server_info - - def present_server(self): - server_info = self._get_server_info() - - if server_info.get('state') != "absent": - - # If target state is stopped, stop before an potential update and force would not be required - if self._module.params.get('state') == "stopped": - server_info = self._start_stop_server(server_info, target_state="stopped") - - server_info = self._update_server(server_info) - - if self._module.params.get('state') == "running": - server_info = self._start_stop_server(server_info, target_state="running") - else: - server_info = self._create_server(server_info) - server_info = self._start_stop_server(server_info, target_state=self._module.params.get('state')) - - return server_info - - def absent_server(self): - server_info = self._get_server_info() - if server_info.get('state') != "absent": - self._result['changed'] = True - self._result['diff']['before'] = deepcopy(server_info) - self._result['diff']['after'] = self._init_server_container() - if not self._module.check_mode: - self._delete('servers/%s' % server_info['uuid']) - server_info = self._wait_for_state(('absent', )) - return server_info - - -def main(): - argument_spec = cloudscale_argument_spec() - argument_spec.update(dict( - state=dict(default='running', choices=ALLOWED_STATES), - name=dict(), - uuid=dict(), - flavor=dict(), - image=dict(), - zone=dict(), - volume_size_gb=dict(type='int', default=10), - bulk_volume_size_gb=dict(type='int'), - ssh_keys=dict(type='list'), - password=dict(no_log=True), - use_public_network=dict(type='bool', default=True), - use_private_network=dict(type='bool', default=False), - use_ipv6=dict(type='bool', default=True), - anti_affinity_with=dict(removed_in_version='2.0.0', removed_from_collection='community.general'), # was Ansible 2.11 - server_groups=dict(type='list'), - user_data=dict(), - force=dict(type='bool', default=False), - tags=dict(type='dict'), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=(('name', 'uuid'),), - mutually_exclusive=(('anti_affinity_with', 'server_groups'),), - supports_check_mode=True, - ) - - cloudscale_server = AnsibleCloudscaleServer(module) - if module.params['state'] == "absent": - server = cloudscale_server.absent_server() - else: - server = cloudscale_server.present_server() - - result = cloudscale_server.get_result(server) - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/cloud/cloudscale/cloudscale_server_group.py b/plugins/modules/cloud/cloudscale/cloudscale_server_group.py deleted file mode 100644 index ce76834f08..0000000000 --- a/plugins/modules/cloud/cloudscale/cloudscale_server_group.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2019, René Moser -# 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: cloudscale_server_group -short_description: Manages server groups on the cloudscale.ch IaaS service -description: - - Create, update and remove server groups. -author: - - René Moser (@resmo) - - Denis Krienbühl (@href) -options: - name: - description: - - Name of the server group. - - Either I(name) or I(uuid) is required. These options are mutually exclusive. - type: str - uuid: - description: - - UUID of the server group. - - Either I(name) or I(uuid) is required. These options are mutually exclusive. - type: str - type: - description: - - Type of the server group. - default: anti-affinity - type: str - zone: - description: - - Zone slug of the server group (e.g. C(lgp1) or C(rma1)). - type: str - version_added: '0.2.0' - state: - description: - - State of the server group. - choices: [ present, absent ] - default: present - type: str - tags: - description: - - Tags assosiated with the server groups. Set this to C({}) to clear any tags. - type: dict -extends_documentation_fragment: -- community.general.cloudscale - -''' - -EXAMPLES = ''' ---- -- name: Ensure server group exists - cloudscale_server_group: - name: my-name - type: anti-affinity - api_token: xxxxxx - -- name: Ensure server group in a specific zone - cloudscale_server_group: - name: my-rma-group - type: anti-affinity - zone: lpg1 - api_token: xxxxxx - -- name: Ensure a server group is absent - cloudscale_server_group: - name: my-name - state: absent - api_token: xxxxxx -''' - -RETURN = ''' ---- -href: - description: API URL to get details about this server group - returned: if available - type: str - sample: https://api.cloudscale.ch/v1/server-group/cfde831a-4e87-4a75-960f-89b0148aa2cc -uuid: - description: The unique identifier for this server - returned: always - type: str - sample: cfde831a-4e87-4a75-960f-89b0148aa2cc -name: - description: The display name of the server group - returned: always - type: str - sample: load balancers -type: - description: The type the server group - returned: if available - type: str - sample: anti-affinity -zone: - description: The zone of the server group - returned: success - type: dict - sample: { 'slug': 'rma1' } - version_added: '0.2.0' -servers: - description: A list of servers that are part of the server group. - returned: if available - type: list - sample: [] -state: - description: State of the server group. - returned: always - type: str - sample: present -tags: - description: Tags assosiated with the server group. - returned: success - type: dict - sample: { 'project': 'my project' } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.community.general.plugins.module_utils.cloudscale import AnsibleCloudscaleBase, cloudscale_argument_spec - - -class AnsibleCloudscaleServerGroup(AnsibleCloudscaleBase): - - def __init__(self, module, namespace): - super(AnsibleCloudscaleServerGroup, self).__init__(module) - self._info = {} - - def _init_container(self): - return { - 'uuid': self._module.params.get('uuid') or self._info.get('uuid'), - 'name': self._module.params.get('name') or self._info.get('name'), - 'state': 'absent', - } - - def _create_server_group(self, server_group): - self._module.fail_on_missing_params(['name']) - self._result['changed'] = True - data = { - 'name': self._module.params.get('name'), - 'type': self._module.params.get('type'), - 'zone': self._module.params.get('zone'), - 'tags': self._module.params.get('tags'), - } - if not self._module.check_mode: - server_group = self._post('server-groups', data) - return server_group - - def _update_server_group(self, server_group): - updated = self._param_updated('name', server_group) - updated = self._param_updated('tags', server_group) or updated - - # Refresh if resource was updated in live mode - if updated and not self._module.check_mode: - server_group = self.get_server_group() - return server_group - - def get_server_group(self): - self._info = self._init_container() - - uuid = self._info.get('uuid') - if uuid is not None: - server_group = self._get('server-groups/%s' % uuid) - if server_group: - self._info.update(server_group) - self._info.update(dict(state='present')) - - else: - name = self._info.get('name') - matching_server_groups = [] - for server_group in self._get('server-groups'): - if server_group['name'] == name: - matching_server_groups.append(server_group) - - if len(matching_server_groups) > 1: - self._module.fail_json(msg="More than one server group with name exists: '%s'. " - "Use the 'uuid' parameter to identify the server group." % name) - elif len(matching_server_groups) == 1: - self._info.update(matching_server_groups[0]) - self._info.update(dict(state='present')) - return self._info - - def present_group(self): - server_group = self.get_server_group() - if server_group.get('state') == 'absent': - server_group = self._create_server_group(server_group) - else: - server_group = self._update_server_group(server_group) - return server_group - - def absent_group(self): - server_group = self.get_server_group() - if server_group.get('state') != 'absent': - self._result['changed'] = True - if not self._module.check_mode: - self._delete('server-groups/%s' % server_group['uuid']) - return server_group - - -def main(): - argument_spec = cloudscale_argument_spec() - argument_spec.update(dict( - name=dict(), - uuid=dict(), - type=dict(default='anti-affinity'), - zone=dict(), - tags=dict(type='dict'), - state=dict(default='present', choices=['absent', 'present']), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=(('name', 'uuid'),), - supports_check_mode=True, - ) - cloudscale_server_group = AnsibleCloudscaleServerGroup(module, 'cloudscale_server_group') - - if module.params['state'] == 'absent': - server_group = cloudscale_server_group.absent_group() - else: - server_group = cloudscale_server_group.present_group() - - result = cloudscale_server_group.get_result(server_group) - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/cloud/cloudscale/cloudscale_volume.py b/plugins/modules/cloud/cloudscale/cloudscale_volume.py deleted file mode 100644 index 77b9547baf..0000000000 --- a/plugins/modules/cloud/cloudscale/cloudscale_volume.py +++ /dev/null @@ -1,300 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2018, Gaudenz Steinlin -# Copyright (c) 2019, René Moser - -# 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: cloudscale_volume -short_description: Manages volumes on the cloudscale.ch IaaS service. -description: - - Create, attach/detach, update and delete volumes on the cloudscale.ch IaaS service. -notes: - - To create a new volume at least the I(name) and I(size_gb) options - are required. - - A volume can be created and attached to a server in the same task. -author: - - Gaudenz Steinlin (@gaudenz) - - René Moser (@resmo) - - Denis Krienbühl (@href) -options: - state: - description: - - State of the volume. - default: present - choices: [ present, absent ] - type: str - name: - description: - - Name of the volume. Either name or UUID must be present to change an - existing volume. - type: str - uuid: - description: - - UUID of the volume. Either name or UUID must be present to change an - existing volume. - type: str - size_gb: - description: - - Size of the volume in GB. - type: int - type: - description: - - Type of the volume. Cannot be changed after creating the volume. - Defaults to C(ssd) on volume creation. - choices: [ ssd, bulk ] - type: str - zone: - description: - - Zone in which the volume resides (e.g. C(lgp1) or C(rma1)). Cannot be - changed after creating the volume. Defaults to the project default zone. - type: str - version_added: '0.2.0' - server_uuids: - description: - - UUIDs of the servers this volume is attached to. Set this to C([]) to - detach the volume. Currently a volume can only be attached to a - single server. - aliases: [ server_uuid ] - type: list - tags: - description: - - Tags associated with the volume. Set this to C({}) to clear any tags. - type: dict -extends_documentation_fragment: -- community.general.cloudscale - -''' - -EXAMPLES = ''' -# Create a new SSD volume -- name: Create an SSD volume - cloudscale_volume: - name: my_ssd_volume - zone: 'lpg1' - size_gb: 50 - api_token: xxxxxx - register: my_ssd_volume - -# Attach an existing volume to a server -- name: Attach volume to server - cloudscale_volume: - uuid: my_ssd_volume.uuid - server_uuids: - - ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - api_token: xxxxxx - -# Create and attach a volume to a server -- name: Create and attach volume to server - cloudscale_volume: - name: my_ssd_volume - zone: 'lpg1' - size_gb: 50 - server_uuids: - - ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - api_token: xxxxxx - -# Detach volume from server -- name: Detach volume from server - cloudscale_volume: - uuid: my_ssd_volume.uuid - server_uuids: [] - api_token: xxxxxx - -# Delete a volume -- name: Delete volume - cloudscale_volume: - name: my_ssd_volume - state: absent - api_token: xxxxxx -''' - -RETURN = ''' -href: - description: The API URL to get details about this volume. - returned: state == present - type: str - sample: https://api.cloudscale.ch/v1/volumes/2db69ba3-1864-4608-853a-0771b6885a3a -uuid: - description: The unique identifier for this volume. - returned: state == present - type: str - sample: 2db69ba3-1864-4608-853a-0771b6885a3a -name: - description: The display name of the volume. - returned: state == present - type: str - sample: my_ssd_volume -size_gb: - description: The size of the volume in GB. - returned: state == present - type: str - sample: 50 -type: - description: The type of the volume. - returned: state == present - type: str - sample: bulk -zone: - description: The zone of the volume. - returned: state == present - type: dict - sample: {'slug': 'lpg1'} - version_added: '0.2.0' -server_uuids: - description: The UUIDs of the servers this volume is attached to. - returned: state == present - type: list - sample: ['47cec963-fcd2-482f-bdb6-24461b2d47b1'] -state: - description: The current status of the volume. - returned: success - type: str - sample: present -tags: - description: Tags associated with the volume. - returned: state == present - type: dict - sample: { 'project': 'my project' } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.community.general.plugins.module_utils.cloudscale import (AnsibleCloudscaleBase, - cloudscale_argument_spec, - ) - - -class AnsibleCloudscaleVolume(AnsibleCloudscaleBase): - - def __init__(self, module): - super(AnsibleCloudscaleVolume, self).__init__(module) - self._info = {} - - def _init_container(self): - return { - 'uuid': self._module.params.get('uuid') or self._info.get('uuid'), - 'name': self._module.params.get('name') or self._info.get('name'), - 'state': 'absent', - } - - def _create(self, volume): - # Fail when missing params for creation - self._module.fail_on_missing_params(['name', 'size_gb']) - - # Fail if a user uses a UUID and state=present but the volume was not found. - if self._module.params.get('uuid'): - self._module.fail_json(msg="The volume with UUID '%s' was not found " - "and we would create a new one with different UUID, " - "this is probably not want you have asked for." % self._module.params.get('uuid')) - - self._result['changed'] = True - data = { - 'name': self._module.params.get('name'), - 'type': self._module.params.get('type'), - 'zone': self._module.params.get('zone'), - 'size_gb': self._module.params.get('size_gb') or 'ssd', - 'server_uuids': self._module.params.get('server_uuids') or [], - 'tags': self._module.params.get('tags'), - } - if not self._module.check_mode: - volume = self._post('volumes', data) - return volume - - def _update(self, volume): - update_params = ( - 'name', - 'size_gb', - 'server_uuids', - 'tags', - ) - updated = False - for param in update_params: - updated = self._param_updated(param, volume) or updated - - # Refresh if resource was updated in live mode - if updated and not self._module.check_mode: - volume = self.get_volume() - return volume - - def get_volume(self): - self._info = self._init_container() - - uuid = self._info.get('uuid') - if uuid is not None: - volume = self._get('volumes/%s' % uuid) - if volume: - self._info.update(volume) - self._info['state'] = 'present' - - else: - name = self._info.get('name') - matching_volumes = [] - for volume in self._get('volumes'): - if volume['name'] == name: - matching_volumes.append(volume) - - if len(matching_volumes) > 1: - self._module.fail_json(msg="More than one volume with name exists: '%s'. " - "Use the 'uuid' parameter to identify the volume." % name) - elif len(matching_volumes) == 1: - self._info.update(matching_volumes[0]) - self._info['state'] = 'present' - return self._info - - def present(self): - volume = self.get_volume() - if volume.get('state') == 'absent': - volume = self._create(volume) - else: - volume = self._update(volume) - return volume - - def absent(self): - volume = self.get_volume() - if volume.get('state') != 'absent': - self._result['changed'] = True - if not self._module.check_mode: - volume['state'] = "absent" - self._delete('volumes/%s' % volume['uuid']) - return volume - - -def main(): - argument_spec = cloudscale_argument_spec() - argument_spec.update(dict( - state=dict(default='present', choices=('present', 'absent')), - name=dict(), - uuid=dict(), - zone=dict(), - size_gb=dict(type='int'), - type=dict(choices=('ssd', 'bulk')), - server_uuids=dict(type='list', aliases=['server_uuid']), - tags=dict(type='dict'), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=(('name', 'uuid'),), - supports_check_mode=True, - ) - - cloudscale_volume = AnsibleCloudscaleVolume(module) - - if module.params['state'] == 'absent': - server_group = cloudscale_volume.absent() - else: - server_group = cloudscale_volume.present() - - result = cloudscale_volume.get_result(server_group) - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/plugins/modules/cloudscale_floating_ip.py b/plugins/modules/cloudscale_floating_ip.py deleted file mode 120000 index 8f87ad9601..0000000000 --- a/plugins/modules/cloudscale_floating_ip.py +++ /dev/null @@ -1 +0,0 @@ -./cloud/cloudscale/cloudscale_floating_ip.py \ No newline at end of file diff --git a/plugins/modules/cloudscale_server.py b/plugins/modules/cloudscale_server.py deleted file mode 120000 index a9d627fe44..0000000000 --- a/plugins/modules/cloudscale_server.py +++ /dev/null @@ -1 +0,0 @@ -./cloud/cloudscale/cloudscale_server.py \ No newline at end of file diff --git a/plugins/modules/cloudscale_server_group.py b/plugins/modules/cloudscale_server_group.py deleted file mode 120000 index 6e5646345b..0000000000 --- a/plugins/modules/cloudscale_server_group.py +++ /dev/null @@ -1 +0,0 @@ -./cloud/cloudscale/cloudscale_server_group.py \ No newline at end of file diff --git a/plugins/modules/cloudscale_volume.py b/plugins/modules/cloudscale_volume.py deleted file mode 120000 index 051f09c680..0000000000 --- a/plugins/modules/cloudscale_volume.py +++ /dev/null @@ -1 +0,0 @@ -./cloud/cloudscale/cloudscale_volume.py \ No newline at end of file diff --git a/tests/integration/targets/cloudscale_common/aliases b/tests/integration/targets/cloudscale_common/aliases deleted file mode 100644 index 136c05e0d0..0000000000 --- a/tests/integration/targets/cloudscale_common/aliases +++ /dev/null @@ -1 +0,0 @@ -hidden diff --git a/tests/integration/targets/cloudscale_common/defaults/main.yml b/tests/integration/targets/cloudscale_common/defaults/main.yml deleted file mode 100644 index 293e0c49de..0000000000 --- a/tests/integration/targets/cloudscale_common/defaults/main.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -# The image to use for test servers -cloudscale_test_image: 'debian-9' - -# Alternate test image to use if a different image is required -cloudscale_alt_test_image: 'ubuntu-18.04' - -# The flavor to use for test servers -cloudscale_test_flavor: 'flex-2' - -# SSH key to use for test servers -cloudscale_test_ssh_key: | - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSPmiqkvDH1/+MDAVDZT8381aYqp73Odz8cnD5hegNhqtXajqtiH0umVg7HybX3wt1HjcrwKJovZURcIbbcDvzdH2bnYbF93T4OLXA0bIfuIp6M86x1iutFtXdpN3TTicINrmSXEE2Ydm51iMu77B08ZERjVaToya2F7vC+egfoPvibf7OLxE336a5tPCywavvNihQjL8sjgpDT5AAScjb3YqK/6VLeQ18Ggt8/ufINsYkb+9/Ji/3OcGFeflnDXq80vPUyF3u4iIylob6RSZenC38cXmQB05tRNxS1B6BXCjMRdy0v4pa7oKM2GA4ADKpNrr0RI9ed+peRFwmsclH test@ansible - -# The zone to use to test servers -cloudscale_test_zone: 'lpg1' - -# The region to use to request floating IPs -cloudscale_test_region: 'lpg' diff --git a/tests/integration/targets/cloudscale_common/tasks/cleanup_floating_ips.yml b/tests/integration/targets/cloudscale_common/tasks/cleanup_floating_ips.yml deleted file mode 100644 index 743a2368c2..0000000000 --- a/tests/integration/targets/cloudscale_common/tasks/cleanup_floating_ips.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: List all floating IPs - uri: - url: 'https://api.cloudscale.ch/v1/floating-ips' - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - status_code: 200 - register: floating_ip_list - -- name: Remove all floating IPs created by this test run - cloudscale_floating_ip: - ip: '{{ item.network | ansible.netcommon.ipaddr("address") }}' - state: 'absent' - when: cloudscale_resource_prefix in (item.reverse_ptr | string ) - with_items: '{{ floating_ip_list.json }}' - loop_control: - label: '{{ item.reverse_ptr }} ({{ item.network }})' diff --git a/tests/integration/targets/cloudscale_common/tasks/cleanup_server_groups.yml b/tests/integration/targets/cloudscale_common/tasks/cleanup_server_groups.yml deleted file mode 100644 index 2bdb9e5939..0000000000 --- a/tests/integration/targets/cloudscale_common/tasks/cleanup_server_groups.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: List all server groups - uri: - url: 'https://api.cloudscale.ch/v1/server-groups' - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - status_code: 200 - register: server_group_list - -- name: Remove all server groups created by this test run - cloudscale_server_group: - uuid: '{{ item.uuid }}' - state: absent - when: cloudscale_resource_prefix in item.name - with_items: '{{ server_group_list.json }}' - loop_control: - label: '{{ item.name }} ({{ item.uuid }})' diff --git a/tests/integration/targets/cloudscale_common/tasks/cleanup_servers.yml b/tests/integration/targets/cloudscale_common/tasks/cleanup_servers.yml deleted file mode 100644 index 8fe6798693..0000000000 --- a/tests/integration/targets/cloudscale_common/tasks/cleanup_servers.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: List all servers - uri: - url: 'https://api.cloudscale.ch/v1/servers' - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - status_code: 200 - register: server_list - -- name: Remove all servers created by this test run - cloudscale_server: - uuid: '{{ item.uuid }}' - state: 'absent' - when: cloudscale_resource_prefix in item.name - with_items: '{{ server_list.json }}' - loop_control: - label: '{{ item.name }} ({{ item.uuid }})' diff --git a/tests/integration/targets/cloudscale_common/tasks/cleanup_volumes.yml b/tests/integration/targets/cloudscale_common/tasks/cleanup_volumes.yml deleted file mode 100644 index 67cc89bb31..0000000000 --- a/tests/integration/targets/cloudscale_common/tasks/cleanup_volumes.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: List all volumes - uri: - url: 'https://api.cloudscale.ch/v1/volumes' - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - status_code: 200 - register: volume_list - -- name: Remove all volumes created by this test run - cloudscale_volume: - uuid: '{{ item.uuid }}' - state: 'absent' - when: cloudscale_resource_prefix in item.name - with_items: '{{ volume_list.json }}' - loop_control: - label: '{{ item.name }} ({{ item.uuid }})' diff --git a/tests/integration/targets/cloudscale_common/tasks/main.yml b/tests/integration/targets/cloudscale_common/tasks/main.yml deleted file mode 100644 index fa0be6eb80..0000000000 --- a/tests/integration/targets/cloudscale_common/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -# Password to use for test server -# This has to be set as a fact, otherwise a new password will be generated -# on every variable access. -- set_fact: - cloudscale_test_password: "{{ lookup('password', '/dev/null length=15 chars=ascii_letters') }}" diff --git a/tests/integration/targets/cloudscale_floating_ip/aliases b/tests/integration/targets/cloudscale_floating_ip/aliases deleted file mode 100644 index c200a3d2c8..0000000000 --- a/tests/integration/targets/cloudscale_floating_ip/aliases +++ /dev/null @@ -1,2 +0,0 @@ -cloud/cloudscale -unsupported diff --git a/tests/integration/targets/cloudscale_floating_ip/meta/main.yml b/tests/integration/targets/cloudscale_floating_ip/meta/main.yml deleted file mode 100644 index 8dd48f0337..0000000000 --- a/tests/integration/targets/cloudscale_floating_ip/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - cloudscale_common diff --git a/tests/integration/targets/cloudscale_floating_ip/tasks/floating_ip.yml b/tests/integration/targets/cloudscale_floating_ip/tasks/floating_ip.yml deleted file mode 100644 index 4e92c6ff46..0000000000 --- a/tests/integration/targets/cloudscale_floating_ip/tasks/floating_ip.yml +++ /dev/null @@ -1,129 +0,0 @@ -- name: Request regional floating IP - cloudscale_floating_ip: - server: '{{ test01.uuid }}' - ip_version: '{{ item.ip_version }}' - reverse_ptr: '{{ item.reverse_ptr | default(omit) }}' - prefix_length: '{{ item.prefix_length | default(omit) }}' - region: '{{ cloudscale_test_region }}' - - register: floating_ip -- name: Verify request floating IP - assert: - that: - - floating_ip is successful - - floating_ip is changed - - floating_ip.region.slug == '{{ cloudscale_test_region }}' - - (item.ip_version == 4 and floating_ip.ip | ipv4) or (item.ip_version == 6 and floating_ip.ip | ipv6) - - floating_ip.server == test01.uuid - -- name: Check floating IP idempotence - cloudscale_floating_ip: - server: '{{ test01.uuid }}' - ip: '{{ floating_ip.ip }}' - region: '{{ cloudscale_test_region }}' - register: floating_ip_idempotence -- name: Verify floating IP idempotence - assert: - that: - - floating_ip_idempotence is successful - - floating_ip_idempotence is not changed - - floating_ip_idempotence.server == test01.uuid - - floating_ip.region.slug == '{{ cloudscale_test_region }}' - -- name: Request global floating IP - cloudscale_floating_ip: - server: '{{ test01.uuid }}' - ip_version: '{{ item.ip_version }}' - reverse_ptr: '{{ item.reverse_ptr | default(omit) }}' - prefix_length: '{{ item.prefix_length | default(omit) }}' - type: 'global' - register: global_floating_ip -- name: Verify global floating IP - assert: - that: - - global_floating_ip is successful - - global_floating_ip is changed - - global_floating_ip.region == None - - global_floating_ip.type == 'global' - - (item.ip_version == 4 and global_floating_ip.ip | ipv4) or (item.ip_version == 6 and global_floating_ip.ip | ipv6) - - global_floating_ip.server == test01.uuid - -- name: Release global floating IP - cloudscale_floating_ip: - ip: '{{ global_floating_ip.ip }}' - state: 'absent' - register: global_floating_ip -- name: Verify release of global floating IP - assert: - that: - - global_floating_ip is successful - - global_floating_ip is changed - - global_floating_ip.state == 'absent' - -- name: Check network parameter alias - cloudscale_floating_ip: - server: '{{ test01.uuid }}' - network: '{{ floating_ip.ip }}' - register: floating_ip_network -- name: Verify network parameter alias - assert: - that: - - floating_ip_network is successful - -- name: Move floating IP to second server - cloudscale_floating_ip: - server: '{{ test02.uuid }}' - ip: '{{ floating_ip.ip }}' - register: move_ip -- name: Verify move floating IPv4 to second server - assert: - that: - - move_ip is successful - - move_ip is changed - - move_ip.server == test02.uuid - -- name: Fail if server is missing on update - cloudscale_floating_ip: - ip: '{{ floating_ip.ip }}' - register: update_failed - ignore_errors: True -- name: Verify fail if server is missing on update - assert: - that: - - update_failed is failed - - "'Missing required parameter' in update_failed.msg" - -- name: Release floating IP - cloudscale_floating_ip: - ip: '{{ floating_ip.ip }}' - state: 'absent' - register: release_ip -- name: Verify release floating IPs - assert: - that: - - release_ip is successful - - release_ip is changed - - release_ip.state == 'absent' - -- name: Release floating IP idempotence - cloudscale_floating_ip: - ip: '{{ floating_ip.ip }}' - state: 'absent' - register: release_ip -- name: Verify release floating IPs idempotence - assert: - that: - - release_ip is successful - - release_ip is not changed - - release_ip.state == 'absent' - -- name: Fail if server is missing on request - cloudscale_floating_ip: - ip_version: 6 - register: request_failed - ignore_errors: True -- name: Verify fail if server is missing on request - assert: - that: - - request_failed is failed - - "'Missing required parameter' in request_failed.msg" diff --git a/tests/integration/targets/cloudscale_floating_ip/tasks/main.yml b/tests/integration/targets/cloudscale_floating_ip/tasks/main.yml deleted file mode 100644 index e46cad3108..0000000000 --- a/tests/integration/targets/cloudscale_floating_ip/tasks/main.yml +++ /dev/null @@ -1,35 +0,0 @@ -- name: Cloudscale floating IP tests - block: - - name: Create a server - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test01' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - zone: '{{ cloudscale_test_zone }}' - register: test01 - - - name: Create a second server - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test02' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - zone: '{{ cloudscale_test_zone }}' - register: test02 - - - include_tasks: floating_ip.yml - loop: - - { 'ip_version': 4, 'reverse_ptr': '{{ cloudscale_resource_prefix }}-4.example.com' } - - { 'ip_version': 6, 'reverse_ptr': '{{ cloudscale_resource_prefix }}-6.example.com' } - - { 'ip_version': 6, 'prefix_length': 56 } - - - import_tasks: unassigned.yml - - always: - - import_role: - name: cloudscale_common - tasks_from: cleanup_servers - - import_role: - name: cloudscale_common - tasks_from: cleanup_floating_ips diff --git a/tests/integration/targets/cloudscale_floating_ip/tasks/unassigned.yml b/tests/integration/targets/cloudscale_floating_ip/tasks/unassigned.yml deleted file mode 100644 index 214f4ab368..0000000000 --- a/tests/integration/targets/cloudscale_floating_ip/tasks/unassigned.yml +++ /dev/null @@ -1,26 +0,0 @@ ---- -- name: Assign Floating IP to server test01 - cloudscale_floating_ip: - ip_version: 6 - server: '{{ test01.uuid }}' - reverse_ptr: '{{ cloudscale_resource_prefix }}-unassigned.example.com' - region: '{{ cloudscale_test_region }}' - register: floating_ip - -# The only way to have an unassigned floating IP is to delete the server -# where the floating IP is currently assigned. -- name: Delete server test01 - cloudscale_server: - uuid: '{{ test01.uuid }}' - state: 'absent' - -- name: Do not fail if floating IP is unassigned - cloudscale_floating_ip: - ip: '{{ floating_ip.ip }}' - register: floating_ip_not_fail -- name: Verify do not fail if floating IP is unassigned - assert: - that: - - floating_ip_not_fail is successful - - floating_ip_not_fail is not changed - - floating_ip_not_fail.server == None diff --git a/tests/integration/targets/cloudscale_server/aliases b/tests/integration/targets/cloudscale_server/aliases deleted file mode 100644 index c200a3d2c8..0000000000 --- a/tests/integration/targets/cloudscale_server/aliases +++ /dev/null @@ -1,2 +0,0 @@ -cloud/cloudscale -unsupported diff --git a/tests/integration/targets/cloudscale_server/defaults/main.yml b/tests/integration/targets/cloudscale_server/defaults/main.yml deleted file mode 100644 index 6d8a0ff847..0000000000 --- a/tests/integration/targets/cloudscale_server/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -cloudscale_test_flavor_2: flex-4 diff --git a/tests/integration/targets/cloudscale_server/meta/main.yml b/tests/integration/targets/cloudscale_server/meta/main.yml deleted file mode 100644 index 8dd48f0337..0000000000 --- a/tests/integration/targets/cloudscale_server/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - cloudscale_common diff --git a/tests/integration/targets/cloudscale_server/tasks/failures.yml b/tests/integration/targets/cloudscale_server/tasks/failures.yml deleted file mode 100644 index 2c975d76bd..0000000000 --- a/tests/integration/targets/cloudscale_server/tasks/failures.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- -- name: Fail missing params - cloudscale_server: - register: srv - ignore_errors: True -- name: 'VERIFY: Fail name and UUID' - assert: - that: - - srv is failed - -- name: Fail unexisting server group - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-group' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - password: '{{ cloudscale_test_password }}' - server_groups: '{{ cloudscale_resource_prefix }}-unexist-group' - ignore_errors: True - register: srv -- name: 'VERIFY: Fail unexisting server group' - assert: - that: - - srv is failed - - srv.msg.startswith('Server group name or UUID not found') - -- name: Create two server groups with the same name - uri: - url: https://api.cloudscale.ch/v1/server-groups - method: POST - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - body: - name: '{{ cloudscale_resource_prefix }}-duplicate' - type: anti-affinity - body_format: json - status_code: 201 - register: duplicate - with_sequence: count=2 - -- name: Try to use server groups with identical name - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-group' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - password: '{{ cloudscale_test_password }}' - server_groups: '{{ cloudscale_resource_prefix }}-duplicate' - ignore_errors: True - register: srv -- name: 'VERIFY: Fail unexisting server group' - assert: - that: - - srv is failed - - srv.msg.startswith('More than one server group with name exists') diff --git a/tests/integration/targets/cloudscale_server/tasks/main.yml b/tests/integration/targets/cloudscale_server/tasks/main.yml deleted file mode 100644 index cb53757eb8..0000000000 --- a/tests/integration/targets/cloudscale_server/tasks/main.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- block: - - import_tasks: failures.yml - - import_tasks: tests.yml - always: - - import_role: - name: cloudscale_common - tasks_from: cleanup_servers - - import_role: - name: cloudscale_common - tasks_from: cleanup_server_groups \ No newline at end of file diff --git a/tests/integration/targets/cloudscale_server/tasks/tests.yml b/tests/integration/targets/cloudscale_server/tasks/tests.yml deleted file mode 100644 index 34c4b3bf83..0000000000 --- a/tests/integration/targets/cloudscale_server/tasks/tests.yml +++ /dev/null @@ -1,676 +0,0 @@ ---- -- name: Setup server groups - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-group-{{ item }}' - type: anti-affinity - zone: '{{ cloudscale_test_zone }}' - with_sequence: count=2 - -- name: Test create a running server in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: server - check_mode: yes -- name: Verify create a running server in check mode - assert: - that: - - server is changed - - server.state == 'absent' - -- name: Test create a running server - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: server -- name: Verify create a running server - assert: - that: - - server is changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.zone.slug == '{{ cloudscale_test_zone }}' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'production' - - server.tags.sla == '24-7' - -- name: Test create a running server idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: server -- name: Verify create a running server idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.zone.slug == '{{ cloudscale_test_zone }}' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'production' - - server.tags.sla == '24-7' - -- name: Test update tags in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: server - check_mode: yes -- name: Verify update tags in check mode - assert: - that: - - server is changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'production' - - server.tags.sla == '24-7' - -- name: Test update tags - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: server -- name: Verify update tags - assert: - that: - - server is changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'staging' - - server.tags.sla == '8-5' - -- name: Test update tags idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: server -- name: Verify update tags idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'staging' - - server.tags.sla == '8-5' - -- name: Test omit tags idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - register: server -- name: Verify update tags idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - server.tags.project == 'ansible-test' - - server.tags.stage == 'staging' - - server.tags.sla == '8-5' - -- name: Test delete tags - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - tags: {} - register: server -- name: Verify delete tags - assert: - that: - - server is changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - not server.tags - -- name: Test delete tags idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - tags: {} - register: server -- name: Verify delete tags idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - - not server.tags - -- name: Test update flavor of a running server without force in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server - check_mode: yes -- name: Verify update flavor of a running server without force in check mode - assert: - that: - - server is not changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test update flavor of a running server without force - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server -- name: Verify update flavor of a running server without force - assert: - that: - - server is not changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test update flavor of a running server without force idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server -- name: Verify update flavor of a running server without force idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test update flavor and name of a running server without force in check mode - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server - check_mode: yes -- name: Verify update flavor and name of a running server without force in check mode - assert: - that: - - server is changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test' - -- name: Test update flavor and name of a running server without force - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server -- name: Verify update flavor and name of a running server without force - assert: - that: - - server is changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Test update flavor and name of a running server without force idempotence - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: no - register: server -- name: Verify update flavor and name of a running server without force idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Test update flavor of a running server with force in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: yes - register: server - check_mode: yes -- name: Verify update flavor of a running server with force in check mode - assert: - that: - - server is changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Test update flavor of a running server with force - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: yes - register: server -- name: Verify update flavor of a running server with force - assert: - that: - - server is changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor_2 }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Test update a running server with force idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - flavor: '{{ cloudscale_test_flavor_2 }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - force: yes - register: server -- name: Verify update flavor of a running server with force idempotence - assert: - that: - - server is not changed - - server.state == 'running' - - server.flavor.slug == '{{ cloudscale_test_flavor_2 }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Remember uuid of running server for anti affinity - set_fact: - running_server_uuid: '{{ server.uuid }}' - -- name: Test create server stopped in anti affinity and private network only in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-stopped' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - use_public_network: no - use_private_network: yes - state: stopped - check_mode: yes - register: server_stopped -- name: Verify create server stopped in anti affinity and private network only in check mode - assert: - that: - - server_stopped is changed - - server_stopped.state == 'absent' - -- name: Test create server stopped in anti affinity and private network only - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-stopped' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - use_public_network: no - use_private_network: yes - state: stopped - register: server_stopped -- name: Verify create server stopped in anti affinity and private network only - assert: - that: - - server_stopped is changed - - server_stopped.state == 'stopped' - - server_stopped.zone.slug == '{{ cloudscale_test_zone }}' - - server_stopped.anti_affinity_with.0.uuid == running_server_uuid - - server_stopped.interfaces.0.type == 'private' - - server_stopped.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test create server stopped in anti affinity and private network only idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-stopped' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-1' - zone: '{{ cloudscale_test_zone }}' - use_public_network: no - use_private_network: yes - state: stopped - register: server_stopped -- name: Verify create server stopped in anti affinity and private network only idempotence - assert: - that: - - server_stopped is not changed - - server_stopped.state == 'stopped' - - server_stopped.zone.slug == '{{ cloudscale_test_zone }}' - - server_stopped.anti_affinity_with.0.uuid == running_server_uuid - - server_stopped.interfaces.0.type == 'private' - - server_stopped.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test change server group not changed - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-stopped' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - server_groups: '{{ cloudscale_resource_prefix }}-group-2' - use_public_network: no - use_private_network: yes - state: stopped - register: server_stopped -- name: Verify Test update server group not changed - assert: - that: - - server_stopped is not changed - - server_stopped.state == 'stopped' - - server_stopped.zone.slug == '{{ cloudscale_test_zone }}' - - server_stopped.anti_affinity_with.0.uuid == running_server_uuid - - server_stopped.interfaces.0.type == 'private' - - server_stopped.server_groups.0.name == '{{ cloudscale_resource_prefix }}-group-1' - -- name: Test create server with password in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-password' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - password: '{{ cloudscale_test_password }}' - check_mode: yes - register: server_password -- name: Verify create server with password in check mode - assert: - that: - - server_password is changed - - server_password.state == 'absent' - # Verify password is not logged - - server_password.diff.after.password != cloudscale_test_password - -- name: Test create server with password - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-password' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - password: '{{ cloudscale_test_password }}' - register: server_password -- name: Verify create server with password - assert: - that: - - server_password is changed - - server_password.state == 'running' - # Verify password is not logged - - server_password.diff.after.password != cloudscale_test_password - -- name: Test create server with password idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-password' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - password: '{{ cloudscale_test_password }}' - register: server_password -- name: Verify create server with password idempotence - assert: - that: - - server_password is not changed - - server_password.state == 'running' - -- name: Test create server failure without required parameters - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-failed' - register: server_failed - ignore_errors: yes -- name: Verify create server failure without required parameters - assert: - that: - - server_failed is failed - - "'Failure while calling the cloudscale.ch API with POST for \"servers\".' in server_failed.msg" - - "'This field is required.' in server_failed.fetch_url_info.body" - -- name: Test stop running server in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - state: stopped - check_mode: yes - register: server -- name: Verify stop running server in check mode - assert: - that: - - server is changed - - server.state == 'running' - -- name: Test stop running server - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - state: stopped - register: server -- name: Verify stop running server - assert: - that: - - server is changed - - server.state == 'stopped' - -- name: Test stop running server idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test-renamed' - state: 'stopped' - register: server -- name: Verify stop running server idempotence - assert: - that: - - server is not changed - - server.state == 'stopped' - -- name: Test update a stopped server in check mode - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - state: stopped - register: server - check_mode: yes -- name: Verify update a stopped server in check mode - assert: - that: - - server is changed - - server.state == 'stopped' - - server.flavor.slug == '{{ cloudscale_test_flavor_2 }}' - - server.name == '{{ cloudscale_resource_prefix }}-test-renamed' - -- name: Test update a stopped server without force - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - state: stopped - register: server -- name: Verify update a stopped server without force - assert: - that: - - server is changed - - server.state == 'stopped' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test' - -- name: Test update a stopped server idempotence - cloudscale_server: - uuid: '{{ server.uuid }}' - name: '{{ cloudscale_resource_prefix }}-test' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - state: stopped - register: server -- name: Verify update a stopped server idempotence - assert: - that: - - server is not changed - - server.state == 'stopped' - - server.flavor.slug == '{{ cloudscale_test_flavor }}' - - server.name == '{{ cloudscale_resource_prefix }}-test' - -- name: Test server running in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: running - register: server - check_mode: yes -- name: Verify server running in check mode - assert: - that: - - server is changed - - server.state == 'stopped' - -- name: Test server running - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: running - register: server -- name: Verify server running - assert: - that: - - server is changed - - server.state == 'running' - -- name: Test server running idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: running - register: server -- name: Verify server running idempotence - assert: - that: - - server is not changed - - server.state == 'running' - -- name: Test running server deletion by name in check mode - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: absent - register: server - check_mode: yes -- name: Verify running server deletion by name in check mode - assert: - that: - - server is changed - - server.state == 'running' - -- name: Test running server deletion by name - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: absent - register: server -- name: Verify running server deletion by name - assert: - that: - - server is changed - - server.state == 'absent' - -- name: Test running server deletion by name idempotence - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-test' - state: absent - register: server -- name: Verify running server deletion by name idempotence - assert: - that: - - server is not changed - - server.state == 'absent' - -- name: Test stopped server deletion by uuid in check mode - cloudscale_server: - uuid: '{{ server_stopped.uuid }}' - state: absent - register: server_stopped - check_mode: yes -- name: Verify stopped server deletion by uuid in check mode - assert: - that: - - server_stopped is changed - - server_stopped.state == 'stopped' - -- name: Test stopped server deletion by uuid - cloudscale_server: - uuid: '{{ server_stopped.uuid }}' - state: absent - register: server_stopped -- name: Verify stopped server deletion by uuid - assert: - that: - - server_stopped is changed - - server_stopped.state == 'absent' - -- name: Test stopped server deletion by uuid idempotence - cloudscale_server: - uuid: '{{ server_stopped.uuid }}' - state: absent - register: server_stopped -- name: Verify stopped server deletion by uuid idempotence - assert: - that: - - server_stopped is not changed - - server_stopped.state == 'absent' diff --git a/tests/integration/targets/cloudscale_server_group/aliases b/tests/integration/targets/cloudscale_server_group/aliases deleted file mode 100644 index c200a3d2c8..0000000000 --- a/tests/integration/targets/cloudscale_server_group/aliases +++ /dev/null @@ -1,2 +0,0 @@ -cloud/cloudscale -unsupported diff --git a/tests/integration/targets/cloudscale_server_group/meta/main.yml b/tests/integration/targets/cloudscale_server_group/meta/main.yml deleted file mode 100644 index 8dd48f0337..0000000000 --- a/tests/integration/targets/cloudscale_server_group/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - cloudscale_common diff --git a/tests/integration/targets/cloudscale_server_group/tasks/failures.yml b/tests/integration/targets/cloudscale_server_group/tasks/failures.yml deleted file mode 100644 index 9269a63458..0000000000 --- a/tests/integration/targets/cloudscale_server_group/tasks/failures.yml +++ /dev/null @@ -1,45 +0,0 @@ ---- -- name: Fail missing params - cloudscale_server_group: - register: grp - ignore_errors: True -- name: 'VERIFY: Fail name and UUID' - assert: - that: - - grp is failed - -- name: Create two server groups with the same name - uri: - url: 'https://api.cloudscale.ch/v1/server-groups' - method: POST - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - body: - name: '{{ cloudscale_resource_prefix }}-duplicate' - type: 'anti-affinity' - body_format: json - status_code: 201 - register: duplicate - with_sequence: count=2 - -- name: Try access to duplicate name - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-duplicate' - register: grp - ignore_errors: True -- name: 'VERIFY: Try access to duplicate name' - assert: - that: - - grp is failed - - grp.msg.startswith('More than one server group with name exists') - -- name: Fail server group creation with UUID - cloudscale_server_group: - uuid: ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - register: grp - ignore_errors: True -- name: 'VERIFY: Fail server group creation with UUID' - assert: - that: - - grp is failed - - grp.msg.startswith('missing required arguments') \ No newline at end of file diff --git a/tests/integration/targets/cloudscale_server_group/tasks/main.yml b/tests/integration/targets/cloudscale_server_group/tasks/main.yml deleted file mode 100644 index f8783414af..0000000000 --- a/tests/integration/targets/cloudscale_server_group/tasks/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- block: - - import_tasks: failures.yml - - import_tasks: tests.yml - always: - - import_role: - name: cloudscale_common - tasks_from: cleanup_server_groups diff --git a/tests/integration/targets/cloudscale_server_group/tasks/tests.yml b/tests/integration/targets/cloudscale_server_group/tasks/tests.yml deleted file mode 100644 index 3fcaa0397b..0000000000 --- a/tests/integration/targets/cloudscale_server_group/tasks/tests.yml +++ /dev/null @@ -1,159 +0,0 @@ ---- -- name: Create server group in check mode - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: grp - check_mode: yes -- name: 'VERIFY: Create server group in check mode' - assert: - that: - - grp is changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp' - - not grp.uuid - -- name: Create server group - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp' - zone: '{{ cloudscale_test_zone }}' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: grp -- name: 'VERIFY: Create server group' - assert: - that: - - grp is changed - - grp.type == 'anti-affinity' - - grp.name == '{{ cloudscale_resource_prefix }}-grp' - - grp.zone.slug == '{{ cloudscale_test_zone }}' - - grp.uuid - - grp.tags.project == 'ansible-test' - - grp.tags.stage == 'production' - - grp.tags.sla == '24-7' - -- name: Remember uuid - set_fact: - server_group_uuid: '{{ grp.uuid }}' - -- name: Create server group idempotence - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp' - zone: '{{ cloudscale_test_zone }}' - tags: - project: ansible-test - stage: production - sla: 24-7 - register: grp -- name: 'VERIFY: Create server group idempotence' - assert: - that: - - grp is not changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp' - - grp.zone.slug == '{{ cloudscale_test_zone }}' - - grp.uuid == server_group_uuid - - grp.tags.project == 'ansible-test' - - grp.tags.stage == 'production' - - grp.tags.sla == '24-7' - -- name: Update server group in check mode - cloudscale_server_group: - uuid: '{{ server_group_uuid }}' - name: '{{ cloudscale_resource_prefix }}-grp2' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: grp - check_mode: yes -- name: 'VERIFY: Update server group in check mode' - assert: - that: - - grp is changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp' - - grp.uuid == server_group_uuid - - grp.zone.slug == '{{ cloudscale_test_zone }}' - - grp.tags.project == 'ansible-test' - - grp.tags.stage == 'production' - - grp.tags.sla == '24-7' - -- name: Update server group - cloudscale_server_group: - uuid: '{{ server_group_uuid }}' - name: '{{ cloudscale_resource_prefix }}-grp2' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: grp -- name: 'VERIFY: Update server group' - assert: - that: - - grp is changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp2' - - grp.uuid == server_group_uuid - - grp.zone.slug == '{{ cloudscale_test_zone }}' - - grp.tags.project == 'ansible-test' - - grp.tags.stage == 'staging' - - grp.tags.sla == '8-5' - -- name: Update server group idempotence - cloudscale_server_group: - uuid: '{{ server_group_uuid }}' - name: '{{ cloudscale_resource_prefix }}-grp2' - tags: - project: ansible-test - stage: staging - sla: 8-5 - register: grp -- name: 'VERIFY: Update server group idempotence' - assert: - that: - - grp is not changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp2' - - grp.uuid == server_group_uuid - - grp.zone.slug == '{{ cloudscale_test_zone }}' - - grp.tags.project == 'ansible-test' - - grp.tags.stage == 'staging' - - grp.tags.sla == '8-5' - -- name: Delete server group in check mode - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp2' - state: absent - register: grp - check_mode: yes -- name: 'VERIFY: Delete server group in check mode' - assert: - that: - - grp is changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp2' - - grp.uuid == server_group_uuid - -- name: Delete server group - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp2' - state: absent - register: grp -- name: 'VERIFY: Delete server group' - assert: - that: - - grp is changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp2' - - grp.uuid == server_group_uuid - -- name: Delete server group idempotence - cloudscale_server_group: - name: '{{ cloudscale_resource_prefix }}-grp2' - state: absent - register: grp -- name: 'VERIFY: Delete server group idempotence' - assert: - that: - - grp is not changed - - grp.name == '{{ cloudscale_resource_prefix }}-grp2' - - not grp.uuid diff --git a/tests/integration/targets/cloudscale_volume/aliases b/tests/integration/targets/cloudscale_volume/aliases deleted file mode 100644 index c200a3d2c8..0000000000 --- a/tests/integration/targets/cloudscale_volume/aliases +++ /dev/null @@ -1,2 +0,0 @@ -cloud/cloudscale -unsupported diff --git a/tests/integration/targets/cloudscale_volume/meta/main.yml b/tests/integration/targets/cloudscale_volume/meta/main.yml deleted file mode 100644 index 8dd48f0337..0000000000 --- a/tests/integration/targets/cloudscale_volume/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - cloudscale_common diff --git a/tests/integration/targets/cloudscale_volume/tasks/cleanup.yml b/tests/integration/targets/cloudscale_volume/tasks/cleanup.yml deleted file mode 100644 index 716717071a..0000000000 --- a/tests/integration/targets/cloudscale_volume/tasks/cleanup.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Remove test server - cloudscale_server: - uuid: '{{ server.uuid }}' - state: 'absent' diff --git a/tests/integration/targets/cloudscale_volume/tasks/failures.yml b/tests/integration/targets/cloudscale_volume/tasks/failures.yml deleted file mode 100644 index cab0d27cdc..0000000000 --- a/tests/integration/targets/cloudscale_volume/tasks/failures.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -- name: Create two volumes with the same name - uri: - url: 'https://api.cloudscale.ch/v1/volumes' - method: POST - headers: - Authorization: 'Bearer {{ cloudscale_api_token }}' - body: - name: '{{ cloudscale_resource_prefix }}-duplicate' - size_gb: 50 - body_format: json - status_code: 201 - register: duplicate - with_sequence: count=2 - -- name: Try access to duplicate name - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-duplicate' - size_gb: 10 - register: vol - ignore_errors: True -- name: 'VERIFY: Try access to duplicate name' - assert: - that: - - vol is failed - -- name: Fail volume creation with UUID - cloudscale_volume: - uuid: ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48 - name: '{{ cloudscale_resource_prefix }}-inexistent' - size_gb: 10 - register: vol - ignore_errors: True -- name: 'VERIFY: Fail volume creation with UUID' - assert: - that: - - vol is failed - - vol.msg.startswith('The volume with UUID \'ea3b39a3-77a8-4d0b-881d-0bb00a1e7f48\' was not found') diff --git a/tests/integration/targets/cloudscale_volume/tasks/main.yml b/tests/integration/targets/cloudscale_volume/tasks/main.yml deleted file mode 100644 index 984f6e1a24..0000000000 --- a/tests/integration/targets/cloudscale_volume/tasks/main.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- block: - - import_tasks: setup.yml - - import_tasks: tests.yml - always: - - import_role: - name: cloudscale_common - tasks_from: cleanup_servers - - import_role: - name: cloudscale_common - tasks_from: cleanup_volumes diff --git a/tests/integration/targets/cloudscale_volume/tasks/setup.yml b/tests/integration/targets/cloudscale_volume/tasks/setup.yml deleted file mode 100644 index 4e3593cfe3..0000000000 --- a/tests/integration/targets/cloudscale_volume/tasks/setup.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Create test instance - cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-server' - flavor: '{{ cloudscale_test_flavor }}' - zone: '{{ cloudscale_test_zone }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - register: server diff --git a/tests/integration/targets/cloudscale_volume/tasks/tests.yml b/tests/integration/targets/cloudscale_volume/tasks/tests.yml deleted file mode 100644 index ec1ac28b51..0000000000 --- a/tests/integration/targets/cloudscale_volume/tasks/tests.yml +++ /dev/null @@ -1,262 +0,0 @@ ---- -- name: Create volume in check mode - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - zone: '{{ cloudscale_test_zone }}' - size_gb: 50 - tags: - project: ansible-test - stage: production - sla: 24-7 - check_mode: yes - register: vol -- name: 'VERIFY: Create volume in check mode' - assert: - that: - - vol is successful - - vol is changed - - vol.state == 'absent' - -- name: Create volume - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - zone: '{{ cloudscale_test_zone }}' - size_gb: 50 - tags: - project: ansible-test - stage: production - sla: 24-7 - register: vol -- name: 'VERIFY: Create volume' - assert: - that: - - vol is successful - - vol is changed - - vol.size_gb == 50 - - vol.name == '{{ cloudscale_resource_prefix }}-vol' - - vol.zone.slug == '{{ cloudscale_test_zone }}' - - vol.tags.project == 'ansible-test' - - vol.tags.stage == 'production' - - vol.tags.sla == '24-7' - -- name: Create volume idempotence - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - zone: '{{ cloudscale_test_zone }}' - size_gb: 50 - tags: - project: ansible-test - stage: production - sla: 24-7 - register: vol -- name: 'VERIFY: Create volume idempotence' - assert: - that: - - vol is successful - - vol is not changed - - vol.size_gb == 50 - - vol.name == '{{ cloudscale_resource_prefix }}-vol' - - vol.zone.slug == '{{ cloudscale_test_zone }}' - - vol.tags.project == 'ansible-test' - - vol.tags.stage == 'production' - - vol.tags.sla == '24-7' - -- name: Attach existing volume by name to server in check mode - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - server_uuids: - - '{{ server.uuid }}' - check_mode: yes - register: vol -- name: 'VERIFY: Attach existing volume by name to server in check mode' - assert: - that: - - vol is successful - - vol is changed - - server.uuid not in vol.server_uuids - -- name: Attach existing volume by name to server - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - server_uuids: - - '{{ server.uuid }}' - register: vol -- name: 'VERIFY: Attach existing volume by name to server' - assert: - that: - - vol is successful - - vol is changed - - server.uuid in vol.server_uuids - -- name: Attach existing volume by name to server idempotence - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-vol' - server_uuids: - - '{{ server.uuid }}' - register: vol -- name: 'VERIFY: Attach existing volume by name to server idempotence' - assert: - that: - - vol is successful - - vol is not changed - - server.uuid in vol.server_uuids - -- name: Resize attached volume by UUID in check mode - cloudscale_volume: - uuid: '{{ vol.uuid }}' - size_gb: 100 - check_mode: yes - register: vol -- name: 'VERIFY: Resize attached volume by UUID in check mode' - assert: - that: - - vol is successful - - vol is changed - - vol.size_gb == 50 - -- name: Resize attached volume by UUID - cloudscale_volume: - uuid: '{{ vol.uuid }}' - size_gb: 100 - register: vol -- name: 'VERIFY: Resize attached volume by UUID' - assert: - that: - - vol is successful - - vol is changed - - vol.size_gb == 100 - -- name: Resize attached volume by UUID idempotence - cloudscale_volume: - uuid: '{{ vol.uuid }}' - size_gb: 100 - register: vol -- name: 'VERIFY: Resize attached volume by UUID idempotence' - assert: - that: - - vol is successful - - vol is not changed - - vol.size_gb == 100 - -- name: Delete attached volume by UUID in check mode - cloudscale_volume: - uuid: '{{ vol.uuid }}' - state: 'absent' - check_mode: yes - register: deleted -- name: 'VERIFY: Delete attached volume by UUID in check mode' - assert: - that: - - deleted is successful - - deleted is changed - - deleted.state == 'present' - - deleted.uuid == vol.uuid - - deleted.name == '{{ cloudscale_resource_prefix }}-vol' - -- name: Delete attached volume by UUID - cloudscale_volume: - uuid: '{{ vol.uuid }}' - state: 'absent' - register: deleted -- name: 'VERIFY: Delete attached volume by UUID' - assert: - that: - - deleted is successful - - deleted is changed - - deleted.state == 'absent' - - deleted.uuid == vol.uuid - - deleted.name == '{{ cloudscale_resource_prefix }}-vol' - -- name: Delete attached volume by UUID idempotence - cloudscale_volume: - uuid: '{{ vol.uuid }}' - state: 'absent' - register: deleted -- name: 'VERIFY: Delete attached volume by UUID idempotence' - assert: - that: - - deleted is successful - - deleted is not changed - - deleted.state == 'absent' - - deleted.uuid == vol.uuid - - not deleted.name - -- name: Create bulk volume and attach - cloudscale_volume: - name: '{{ cloudscale_resource_prefix }}-bulk' - type: bulk - zone: '{{ cloudscale_test_zone }}' - size_gb: 100 - server_uuids: - - '{{ server.uuid }}' - register: bulk -- name: 'VERIFY: Create bulk volume and attach' - assert: - that: - - bulk is successful - - bulk is changed - - bulk.size_gb == 100 - - server.uuid in bulk.server_uuids - -- name: Detach volume by UUID - cloudscale_volume: - uuid: '{{ bulk.uuid }}' - server_uuids: [] - register: bulk -- name: 'VERIFY: Detach volume by UUID' - assert: - that: - - bulk is successful - - bulk is changed - - bulk.server_uuids == [] - -- name: Resize detached volume by name - cloudscale_volume: - name: '{{ bulk.name }}' - size_gb: 200 - register: bulk -- name: 'VERIFY: Resize detached volume by name' - assert: - that: - - bulk is successful - - bulk is changed - - bulk.size_gb == 200 - -- name: Delete volume by name in check mode - cloudscale_volume: - name: '{{ bulk.name }}' - state: 'absent' - check_mode: yes - register: bulk -- name: 'VERIFY: Delete volume by name' - assert: - that: - - bulk is successful - - bulk is changed - - bulk.state == 'present' - -- name: Delete volume by name - cloudscale_volume: - name: '{{ bulk.name }}' - state: 'absent' - register: bulk -- name: 'VERIFY: Delete volume by name' - assert: - that: - - bulk is successful - - bulk is changed - - bulk.state == 'absent' - -- name: Delete volume by name idempotence - cloudscale_volume: - name: '{{ bulk.name }}' - state: 'absent' - register: bulk -- name: 'VERIFY: Delete volume by name idempotence' - assert: - that: - - bulk is successful - - bulk is not changed - - bulk.state == 'absent' - -- import_tasks: failures.yml diff --git a/tests/integration/targets/inventory_cloudscale/aliases b/tests/integration/targets/inventory_cloudscale/aliases deleted file mode 100644 index 1ce5f09122..0000000000 --- a/tests/integration/targets/inventory_cloudscale/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/cloudscale -unsupported -needs/target/cloudscale_common diff --git a/tests/integration/targets/inventory_cloudscale/filter_plugins/group_name.py b/tests/integration/targets/inventory_cloudscale/filter_plugins/group_name.py deleted file mode 100644 index faddb23882..0000000000 --- a/tests/integration/targets/inventory_cloudscale/filter_plugins/group_name.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from ansible.inventory.group import to_safe_group_name - - -def safe_group_name(name): - return to_safe_group_name(name) - - -class FilterModule(object): - filter_map = { - 'safe_group_name': safe_group_name - } - - def filters(self): - return self.filter_map diff --git a/tests/integration/targets/inventory_cloudscale/inventory-private.yml b/tests/integration/targets/inventory_cloudscale/inventory-private.yml deleted file mode 100644 index b81d101041..0000000000 --- a/tests/integration/targets/inventory_cloudscale/inventory-private.yml +++ /dev/null @@ -1,14 +0,0 @@ -plugin: community.general.cloudscale -ansible_host: private -inventory_hostname: name -groups: - ansible: inventory_hostname.startswith('ansible') - private_net: (cloudscale.interfaces | selectattr('type', 'equalto', 'private') | list | length) > 0 -keyed_groups: -- prefix: net - key: (cloudscale.interfaces.0.addresses.0.address + '/' + cloudscale.interfaces.0.addresses.0.prefix_length | string) | ansible.netcommon.ipaddr('network') -- prefix: distro - key: cloudscale.image.operating_system -compose: - flavor_image: cloudscale.flavor.slug + '_' + cloudscale.image.slug -strict: false diff --git a/tests/integration/targets/inventory_cloudscale/inventory-public.yml b/tests/integration/targets/inventory_cloudscale/inventory-public.yml deleted file mode 100644 index 283ebee50e..0000000000 --- a/tests/integration/targets/inventory_cloudscale/inventory-public.yml +++ /dev/null @@ -1,14 +0,0 @@ -plugin: community.general.cloudscale -ansible_host: public_v4 -inventory_hostname: name -groups: - ansible: inventory_hostname.startswith('ansible') - private_net: (cloudscale.interfaces | selectattr('type', 'equalto', 'private') | list | length) > 0 -keyed_groups: -- prefix: net - key: (cloudscale.interfaces.0.addresses.0.address + '/' + cloudscale.interfaces.0.addresses.0.prefix_length | string) | ansible.netcommon.ipaddr('network') -- prefix: distro - key: cloudscale.image.operating_system -compose: - flavor_image: cloudscale.flavor.slug + '_' + cloudscale.image.slug -strict: false diff --git a/tests/integration/targets/inventory_cloudscale/inventory-uuid.yml b/tests/integration/targets/inventory_cloudscale/inventory-uuid.yml deleted file mode 100644 index 92c35f1e79..0000000000 --- a/tests/integration/targets/inventory_cloudscale/inventory-uuid.yml +++ /dev/null @@ -1,14 +0,0 @@ -plugin: community.general.cloudscale -ansible_host: public_v4 -inventory_hostname: uuid -groups: - ansible: cloudscale.name.startswith('ansible') - private_net: (cloudscale.interfaces | selectattr('type', 'equalto', 'private') | list | length) > 0 -keyed_groups: -- prefix: net - key: (cloudscale.interfaces.0.addresses.0.address + '/' + cloudscale.interfaces.0.addresses.0.prefix_length | string) | ansible.netcommon.ipaddr('network') -- prefix: distro - key: cloudscale.image.operating_system -compose: - flavor_image: cloudscale.flavor.slug + '_' + cloudscale.image.slug -strict: false diff --git a/tests/integration/targets/inventory_cloudscale/playbooks/change-inventory-config.yml b/tests/integration/targets/inventory_cloudscale/playbooks/change-inventory-config.yml deleted file mode 100644 index 74e9132de1..0000000000 --- a/tests/integration/targets/inventory_cloudscale/playbooks/change-inventory-config.yml +++ /dev/null @@ -1,8 +0,0 @@ -- name: Change inventory configuration to {{ inventory_config }} - file: - src: '{{ inventory_config }}' - dest: ../inventory_cloudscale.yml - state: link - -- name: Refresh inventory - meta: refresh_inventory diff --git a/tests/integration/targets/inventory_cloudscale/playbooks/cleanup.yml b/tests/integration/targets/inventory_cloudscale/playbooks/cleanup.yml deleted file mode 100644 index f47bbe6eb0..0000000000 --- a/tests/integration/targets/inventory_cloudscale/playbooks/cleanup.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -- name: List all servers - uri: - url: 'https://api.cloudscale.ch/v1/servers' - headers: - Authorization: 'Bearer {{ lookup("env", "CLOUDSCALE_API_TOKEN") }}' - status_code: 200 - register: server_list - -- name: Remove all servers created by this test run - community.general.cloudscale_server: - uuid: '{{ item.uuid }}' - state: 'absent' - when: cloudscale_resource_prefix in item.name - with_items: '{{ server_list.json }}' - loop_control: - label: '{{ item.name }} ({{ item.uuid }})' diff --git a/tests/integration/targets/inventory_cloudscale/playbooks/common-asserts.yml b/tests/integration/targets/inventory_cloudscale/playbooks/common-asserts.yml deleted file mode 100644 index b83e4ffcf3..0000000000 --- a/tests/integration/targets/inventory_cloudscale/playbooks/common-asserts.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -- name: '{{ inventory }}: Verify basic inventory' - assert: - that: - - server_public[identifier] in hostvars - - server_private[identifier] in hostvars - - server_public_private[identifier] in hostvars - - server_unsafe_chars[identifier] in hostvars - -- name: '{{ inventory }}: Verify duplicate host names in inventory' - assert: - that: - - cloudscale_resource_prefix + '-duplicate' not in hostvars - - (cloudscale_resource_prefix + '-duplicate') | safe_group_name in groups - -- name: '{{ inventory }}: Verify constructed groups in inventory' - assert: - that: - # Test for the "ansible" group - - '"ansible" in groups' - - server_public[identifier] in groups.ansible - - server_private[identifier] in groups.ansible - - server_public_private[identifier] in groups.ansible - - server_unsafe_chars[identifier] in groups.ansible - - server_other_prefix[identifier] not in groups.ansible - # Tests for the "private_net" group - - '"private_net" in groups' - - server_public[identifier] not in groups["private_net"] - - server_private[identifier] in groups["private_net"] - - server_public_private[identifier] in groups["private_net"] - # Tests for "distro" keyed group - - '"distro_Debian" in groups' - - '"distro_Ubuntu" in groups' - - server_public[identifier] in groups.distro_Debian - - server_private[identifier] not in groups.distro_Debian - - server_public[identifier] not in groups.distro_Ubuntu - - server_private[identifier] in groups.distro_Ubuntu - # Test for flavor_image composed variable - - hostvars[server_public[identifier]].flavor_image == 'flex-2_debian-9' - - hostvars[server_private[identifier]].flavor_image == 'flex-2_ubuntu-18.04' - -- name: '{{ inventory }}: Verify cloudscale specific host variables' - assert: - that: - - hostvars[item.0[identifier]].cloudscale[item.1] == item.0[item.1] - with_nested: - - [ '{{ server_public }}', '{{ server_private }}', '{{ server_public_private }}' ] - - [ 'anti_affinity_with', 'flavor', 'href', 'image', 'interfaces', 'name', 'uuid', 'volumes' ] - loop_control: - label: '{{ item.0.name }} ({{ item.0.uuid }}): {{ item.1 }}' diff --git a/tests/integration/targets/inventory_cloudscale/playbooks/setup.yml b/tests/integration/targets/inventory_cloudscale/playbooks/setup.yml deleted file mode 100644 index 59ccee9932..0000000000 --- a/tests/integration/targets/inventory_cloudscale/playbooks/setup.yml +++ /dev/null @@ -1,74 +0,0 @@ ---- -- name: Create server with public network only - community.general.cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-inventory-public' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - use_public_network: True - use_private_network: False - register: server_public - -- name: Create server with private network only - community.general.cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-inventory-private' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_alt_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - use_public_network: False - use_private_network: True - register: server_private - -- name: Create server with public and private network - community.general.cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-inventory-public-private' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - use_public_network: True - use_private_network: True - register: server_public_private - -- name: Create servers with duplicate names - # The cloudscale_server module does not allow creating two servers with the same - # name. To do this the uri module has to be used. - uri: - url: 'https://api.cloudscale.ch/v1/servers' - method: POST - headers: - Authorization: 'Bearer {{ lookup("env", "CLOUDSCALE_API_TOKEN") }}' - body: - name: '{{ cloudscale_resource_prefix }}-duplicate' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: - - '{{ cloudscale_test_ssh_key }}' - body_format: json - status_code: 201 - register: duplicate - with_sequence: count=2 - -- name: Create server with different prefix - community.general.cloudscale_server: - name: 'other-prefix-{{ cloudscale_resource_prefix }}-inventory' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - register: server_other_prefix - -# The API does not allow creation of a server with a name containing -# characters not allowed in DNS names. So create a server and rename -# it afterwards (which is possible). The resaon for this restriction is -# that on creation a PTR entry for the server is created. -- name: Create server to be renamed with unsafe characters - community.general.cloudscale_server: - name: '{{ cloudscale_resource_prefix }}-unsafe-chars' - flavor: '{{ cloudscale_test_flavor }}' - image: '{{ cloudscale_test_image }}' - ssh_keys: '{{ cloudscale_test_ssh_key }}' - register: server_unsafe_chars -- name: Rename server to contain unsafe characters - community.general.cloudscale_server: - uuid: '{{ server_unsafe_chars.uuid }}' - name: '{{ cloudscale_resource_prefix }}-snowmans-are-cool-☃!' - register: server_unsafe_chars diff --git a/tests/integration/targets/inventory_cloudscale/playbooks/test-inventory.yml b/tests/integration/targets/inventory_cloudscale/playbooks/test-inventory.yml deleted file mode 100644 index 24fe38eeb9..0000000000 --- a/tests/integration/targets/inventory_cloudscale/playbooks/test-inventory.yml +++ /dev/null @@ -1,68 +0,0 @@ ---- -- name: Create servers and test cloudscale inventory plugin - hosts: localhost - gather_facts: False - roles: - - cloudscale_common - tasks: - - block: - - import_tasks: setup.yml - - - import_tasks: change-inventory-config.yml - vars: - inventory_config: inventory-public.yml - - - import_tasks: common-asserts.yml - vars: - identifier: 'name' - inventory: 'Public v4' - - - name: Verify inventory with public IP - assert: - that: - # Test ansible_host setting - - server_public.interfaces.0.addresses.0.address - == hostvars[server_public.name].ansible_host - - server_public_private.interfaces.0.addresses.0.address - == hostvars[server_public_private.name].ansible_host - - '"ansible_host" not in hostvars[server_private.name]' - - - import_tasks: change-inventory-config.yml - vars: - inventory_config: inventory-private.yml - - - import_tasks: common-asserts.yml - vars: - identifier: 'name' - inventory: 'Private v4' - - - name: Verify inventory with private IP - assert: - that: - # Test ansible_host setting - - '"ansible_host" not in hostvars[server_public.name]' - - server_private.interfaces.0.addresses.0.address - == hostvars[server_private.name].ansible_host - - server_public_private.interfaces.1.addresses.0.address - == hostvars[server_public_private.name].ansible_host - - - import_tasks: change-inventory-config.yml - vars: - inventory_config: inventory-uuid.yml - - - import_tasks: common-asserts.yml - vars: - identifier: 'uuid' - inventory: 'UUID' - - - name: Verify inventory with UUID - assert: - that: - # Test server name groups - - groups[server_public.name | safe_group_name] == [server_public.uuid] - - groups[server_private.name | safe_group_name] == [server_private.uuid] - - groups[server_public_private.name | safe_group_name] == [server_public_private.uuid] - - groups[server_unsafe_chars.name | safe_group_name] == [server_unsafe_chars.uuid] - - always: - - import_tasks: cleanup.yml diff --git a/tests/integration/targets/inventory_cloudscale/runme.sh b/tests/integration/targets/inventory_cloudscale/runme.sh deleted file mode 100755 index 25c2352d45..0000000000 --- a/tests/integration/targets/inventory_cloudscale/runme.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Exit on errors, exit when accessing unset variables and print all commands -set -eux - -# Set the role path so that the cloudscale_common role is available -export ANSIBLE_ROLES_PATH="../" - -# Set the filter plugin search path so that the safe_group_name filter is available -export ANSIBLE_FILTER_PLUGINS="./filter_plugins" - -rm -f inventory.yml -export ANSIBLE_INVENTORY="./inventory_cloudscale.yml" - -# Run without converting invalid characters in group names -export ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=never -ansible-playbook playbooks/test-inventory.yml "$@" - -# Run with converting invalid characters in group names -export ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=always -ansible-playbook playbooks/test-inventory.yml "$@" diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt index a072d7d715..ec2802d4bf 100644 --- a/tests/sanity/ignore-2.10.txt +++ b/tests/sanity/ignore-2.10.txt @@ -194,12 +194,6 @@ plugins/modules/cloud/centurylink/clc_server_snapshot.py validate-modules:doc-mi plugins/modules/cloud/centurylink/clc_server_snapshot.py validate-modules:implied-parameter-type-mismatch plugins/modules/cloud/centurylink/clc_server_snapshot.py validate-modules:parameter-list-no-elements plugins/modules/cloud/centurylink/clc_server_snapshot.py validate-modules:parameter-type-not-in-doc -plugins/modules/cloud/cloudscale/cloudscale_floating_ip.py validate-modules:doc-required-mismatch -plugins/modules/cloud/cloudscale/cloudscale_server.py validate-modules:doc-required-mismatch -plugins/modules/cloud/cloudscale/cloudscale_server.py validate-modules:parameter-list-no-elements -plugins/modules/cloud/cloudscale/cloudscale_server_group.py validate-modules:doc-required-mismatch -plugins/modules/cloud/cloudscale/cloudscale_volume.py validate-modules:doc-required-mismatch -plugins/modules/cloud/cloudscale/cloudscale_volume.py validate-modules:parameter-list-no-elements plugins/modules/cloud/digital_ocean/digital_ocean.py validate-modules:doc-missing-type plugins/modules/cloud/digital_ocean/digital_ocean.py validate-modules:parameter-list-no-elements plugins/modules/cloud/digital_ocean/digital_ocean.py validate-modules:parameter-type-not-in-doc