diff options
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules')
34 files changed, 5493 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean.py new file mode 100644 index 00000000..53314513 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean.py @@ -0,0 +1,475 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean +short_description: Create/delete a droplet/SSH_key in DigitalOcean +deprecated: + removed_in: 2.0.0 # was Ansible 2.12 + why: Updated module to remove external dependency with increased functionality. + alternative: Use M(community.digitalocean.digital_ocean_droplet) instead. +description: + - Create/delete a droplet in DigitalOcean and optionally wait for it to be 'running', or deploy an SSH key. +author: "Vincent Viallet (@zbal)" +options: + command: + description: + - Which target you want to operate on. + default: droplet + choices: ['droplet', 'ssh'] + state: + description: + - Indicate desired state of the target. + default: present + choices: ['present', 'active', 'absent', 'deleted'] + api_token: + description: + - DigitalOcean api token. + id: + description: + - Numeric, the droplet id you want to operate on. + aliases: ['droplet_id'] + name: + description: + - String, this is the name of the droplet - must be formatted by hostname rules, or the name of a SSH key. + unique_name: + description: + - Bool, require unique hostnames. By default, DigitalOcean allows multiple hosts with the same name. Setting this to "yes" allows only one host + per name. Useful for idempotence. + type: bool + default: 'no' + size_id: + description: + - This is the slug of the size you would like the droplet created with. + image_id: + description: + - This is the slug of the image you would like the droplet created with. + region_id: + description: + - This is the slug of the region you would like your server to be created in. + ssh_key_ids: + description: + - Optional, array of SSH key (numeric) ID that you would like to be added to the server. + virtio: + description: + - "Bool, turn on virtio driver in droplet for improved network and storage I/O." + type: bool + default: 'yes' + private_networking: + description: + - "Bool, add an additional, private network interface to droplet for inter-droplet communication." + type: bool + default: 'no' + backups_enabled: + description: + - Optional, Boolean, enables backups for your droplet. + type: bool + default: 'no' + user_data: + description: + - opaque blob of data which is made available to the droplet + ipv6: + description: + - Optional, Boolean, enable IPv6 for your droplet. + type: bool + default: 'no' + wait: + description: + - Wait for the droplet to be in state 'running' before returning. If wait is "no" an ip_address may not be returned. + type: bool + default: 'yes' + wait_timeout: + description: + - How long before wait gives up, in seconds. + default: 300 + ssh_pub_key: + description: + - The public SSH key you want to add to your account. + +notes: + - Two environment variables can be used, DO_API_KEY and DO_API_TOKEN. They both refer to the v2 token. + - As of Ansible 1.9.5 and 2.0, Version 2 of the DigitalOcean API is used, this removes C(client_id) and C(api_key) options in favor of C(api_token). + - If you are running Ansible 1.9.4 or earlier you might not be able to use the included version of this module as the API version used has been retired. + Upgrade Ansible or, if unable to, try downloading the latest version of this module from github and putting it into a 'library' directory. +requirements: + - "python >= 2.6" + - dopy +''' + + +EXAMPLES = r''' +# Ensure a SSH key is present +# If a key matches this name, will return the ssh key id and changed = False +# If no existing key matches this name, a new key is created, the ssh key id is returned and changed = False + +- name: Ensure a SSH key is present + community.digitalocean.digital_ocean: + state: present + command: ssh + name: my_ssh_key + ssh_pub_key: 'ssh-rsa AAAA...' + api_token: XXX + +# Will return the droplet details including the droplet id (used for idempotence) +- name: Create a new Droplet + community.digitalocean.digital_ocean: + state: present + command: droplet + name: mydroplet + api_token: XXX + size_id: 2gb + region_id: ams2 + image_id: fedora-19-x64 + wait_timeout: 500 + register: my_droplet + +- debug: + msg: "ID is {{ my_droplet.droplet.id }}" + +- debug: + msg: "IP is {{ my_droplet.droplet.ip_address }}" + +# Ensure a droplet is present +# If droplet id already exist, will return the droplet details and changed = False +# If no droplet matches the id, a new droplet will be created and the droplet details (including the new id) are returned, changed = True. + +- name: Ensure a droplet is present + community.digitalocean.digital_ocean: + state: present + command: droplet + id: 123 + name: mydroplet + api_token: XXX + size_id: 2gb + region_id: ams2 + image_id: fedora-19-x64 + wait_timeout: 500 + +# Create a droplet with ssh key +# The ssh key id can be passed as argument at the creation of a droplet (see ssh_key_ids). +# Several keys can be added to ssh_key_ids as id1,id2,id3 +# The keys are used to connect as root to the droplet. + +- name: Create a droplet with ssh key + community.digitalocean.digital_ocean: + state: present + ssh_key_ids: 123,456 + name: mydroplet + api_token: XXX + size_id: 2gb + region_id: ams2 + image_id: fedora-19-x64 +''' + +import os +import time +import traceback + +from distutils.version import LooseVersion + +try: + # Imported as a dependency for dopy + import ansible.module_utils.six + HAS_SIX = True +except ImportError: + HAS_SIX = False + +HAS_DOPY = False +try: + import dopy + from dopy.manager import DoError, DoManager + if LooseVersion(dopy.__version__) >= LooseVersion('0.3.2'): + HAS_DOPY = True +except ImportError: + pass + +from ansible.module_utils.basic import AnsibleModule, env_fallback + + +class TimeoutError(Exception): + + def __init__(self, msg, id_): + super(TimeoutError, self).__init__(msg) + self.id = id_ + + +class JsonfyMixIn(object): + + def to_json(self): + return self.__dict__ + + +class Droplet(JsonfyMixIn): + manager = None + + def __init__(self, droplet_json): + self.status = 'new' + self.__dict__.update(droplet_json) + + def is_powered_on(self): + return self.status == 'active' + + def update_attr(self, attrs=None): + if attrs: + for k, v in attrs.items(): + setattr(self, k, v) + networks = attrs.get('networks', {}) + for network in networks.get('v6', []): + if network['type'] == 'public': + setattr(self, 'public_ipv6_address', network['ip_address']) + else: + setattr(self, 'private_ipv6_address', network['ip_address']) + else: + json = self.manager.show_droplet(self.id) + if json['ip_address']: + self.update_attr(json) + + def power_on(self): + if self.status != 'off': + raise AssertionError('Can only power on a closed one.') + json = self.manager.power_on_droplet(self.id) + self.update_attr(json) + + def ensure_powered_on(self, wait=True, wait_timeout=300): + if self.is_powered_on(): + return + if self.status == 'off': # powered off + self.power_on() + + if wait: + end_time = time.time() + wait_timeout + while time.time() < end_time: + time.sleep(min(20, end_time - time.time())) + self.update_attr() + if self.is_powered_on(): + if not self.ip_address: + raise TimeoutError('No ip is found.', self.id) + return + raise TimeoutError('Wait for droplet running timeout', self.id) + + def destroy(self): + return self.manager.destroy_droplet(self.id, scrub_data=True) + + @classmethod + def setup(cls, api_token): + cls.manager = DoManager(None, api_token, api_version=2) + + @classmethod + def add(cls, name, size_id, image_id, region_id, ssh_key_ids=None, virtio=True, private_networking=False, backups_enabled=False, user_data=None, + ipv6=False): + private_networking_lower = str(private_networking).lower() + backups_enabled_lower = str(backups_enabled).lower() + ipv6_lower = str(ipv6).lower() + json = cls.manager.new_droplet(name, size_id, image_id, region_id, + ssh_key_ids=ssh_key_ids, virtio=virtio, private_networking=private_networking_lower, + backups_enabled=backups_enabled_lower, user_data=user_data, ipv6=ipv6_lower) + droplet = cls(json) + return droplet + + @classmethod + def find(cls, id=None, name=None): + if not id and not name: + return False + + droplets = cls.list_all() + + # Check first by id. digital ocean requires that it be unique + for droplet in droplets: + if droplet.id == id: + return droplet + + # Failing that, check by hostname. + for droplet in droplets: + if droplet.name == name: + return droplet + + return False + + @classmethod + def list_all(cls): + json = cls.manager.all_active_droplets() + return list(map(cls, json)) + + +class SSH(JsonfyMixIn): + manager = None + + def __init__(self, ssh_key_json): + self.__dict__.update(ssh_key_json) + update_attr = __init__ + + def destroy(self): + self.manager.destroy_ssh_key(self.id) + return True + + @classmethod + def setup(cls, api_token): + cls.manager = DoManager(None, api_token, api_version=2) + + @classmethod + def find(cls, name): + if not name: + return False + keys = cls.list_all() + for key in keys: + if key.name == name: + return key + return False + + @classmethod + def list_all(cls): + json = cls.manager.all_ssh_keys() + return list(map(cls, json)) + + @classmethod + def add(cls, name, key_pub): + json = cls.manager.new_ssh_key(name, key_pub) + return cls(json) + + +def core(module): + def getkeyordie(k): + v = module.params[k] + if v is None: + module.fail_json(msg='Unable to load %s' % k) + return v + + api_token = module.params['api_token'] + changed = True + command = module.params['command'] + state = module.params['state'] + + if command == 'droplet': + Droplet.setup(api_token) + if state in ('active', 'present'): + + # First, try to find a droplet by id. + droplet = Droplet.find(id=module.params['id']) + + # If we couldn't find the droplet and the user is allowing unique + # hostnames, then check to see if a droplet with the specified + # hostname already exists. + if not droplet and module.params['unique_name']: + droplet = Droplet.find(name=getkeyordie('name')) + + # If both of those attempts failed, then create a new droplet. + if not droplet: + droplet = Droplet.add( + name=getkeyordie('name'), + size_id=getkeyordie('size_id'), + image_id=getkeyordie('image_id'), + region_id=getkeyordie('region_id'), + ssh_key_ids=module.params['ssh_key_ids'], + virtio=module.params['virtio'], + private_networking=module.params['private_networking'], + backups_enabled=module.params['backups_enabled'], + user_data=module.params.get('user_data'), + ipv6=module.params['ipv6'], + ) + + if droplet.is_powered_on(): + changed = False + + droplet.ensure_powered_on( + wait=getkeyordie('wait'), + wait_timeout=getkeyordie('wait_timeout') + ) + + module.exit_json(changed=changed, droplet=droplet.to_json()) + + elif state in ('absent', 'deleted'): + # First, try to find a droplet by id. + droplet = Droplet.find(module.params['id']) + + # If we couldn't find the droplet and the user is allowing unique + # hostnames, then check to see if a droplet with the specified + # hostname already exists. + if not droplet and module.params['unique_name']: + droplet = Droplet.find(name=getkeyordie('name')) + + if not droplet: + module.exit_json(changed=False, msg='The droplet is not found.') + + droplet.destroy() + module.exit_json(changed=True) + + elif command == 'ssh': + SSH.setup(api_token) + name = getkeyordie('name') + if state in ('active', 'present'): + key = SSH.find(name) + if key: + module.exit_json(changed=False, ssh_key=key.to_json()) + key = SSH.add(name, getkeyordie('ssh_pub_key')) + module.exit_json(changed=True, ssh_key=key.to_json()) + + elif state in ('absent', 'deleted'): + key = SSH.find(name) + if not key: + module.exit_json(changed=False, msg='SSH key with the name of %s is not found.' % name) + key.destroy() + module.exit_json(changed=True) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + command=dict(choices=['droplet', 'ssh'], default='droplet'), + state=dict(choices=['active', 'present', 'absent', 'deleted'], default='present'), + api_token=dict( + aliases=['API_TOKEN'], + no_log=True, + fallback=(env_fallback, ['DO_API_TOKEN', 'DO_API_KEY']) + ), + name=dict(type='str'), + size_id=dict(), + image_id=dict(), + region_id=dict(), + ssh_key_ids=dict(type='list'), + virtio=dict(type='bool', default=True), + private_networking=dict(type='bool', default=False), + backups_enabled=dict(type='bool', default=False), + id=dict(aliases=['droplet_id'], type='int'), + unique_name=dict(type='bool', default=False), + user_data=dict(default=None), + ipv6=dict(type='bool', default=False), + wait=dict(type='bool', default=True), + wait_timeout=dict(default=300, type='int'), + ssh_pub_key=dict(type='str'), + ), + required_together=( + ['size_id', 'image_id', 'region_id'], + ), + mutually_exclusive=( + ['size_id', 'ssh_pub_key'], + ['image_id', 'ssh_pub_key'], + ['region_id', 'ssh_pub_key'], + ), + required_one_of=( + ['id', 'name'], + ), + ) + if not HAS_DOPY and not HAS_SIX: + module.fail_json(msg='dopy >= 0.3.2 is required for this module. dopy requires six but six is not installed. ' + 'Make sure both dopy and six are installed.') + if not HAS_DOPY: + module.fail_json(msg='dopy >= 0.3.2 required for this module') + + try: + core(module) + except TimeoutError as e: + module.fail_json(msg=str(e), id=e.id) + except (DoError, Exception) as e: + module.fail_json(msg=str(e), exception=traceback.format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_facts.py new file mode 100644 index 00000000..51e17b94 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_facts.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_account_info +short_description: Gather information about DigitalOcean User account +description: + - This module can be used to gather information about User account. + - This module was called C(digital_ocean_account_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" + +requirements: + - "python >= 2.6" + +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about user account + community.digitalocean.digital_ocean_account_info: + oauth_token: "{{ oauth_token }}" +''' + + +RETURN = r''' +data: + description: DigitalOcean account information + returned: success + type: dict + sample: { + "droplet_limit": 10, + "email": "testuser1@gmail.com", + "email_verified": true, + "floating_ip_limit": 3, + "status": "active", + "status_message": "", + "uuid": "aaaaaaaaaaaaaa" + } +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get("account") + if response.status_code != 200: + module.fail_json(msg="Failed to fetch 'account' information due to error : %s" % response.json['message']) + + module.exit_json(changed=False, data=response.json["account"]) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_account_facts', 'community.digitalocean.digital_ocean_account_facts'): + module.deprecate("The 'digital_ocean_account_facts' module has been renamed to 'digital_ocean_account_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_info.py new file mode 100644 index 00000000..51e17b94 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_account_info.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_account_info +short_description: Gather information about DigitalOcean User account +description: + - This module can be used to gather information about User account. + - This module was called C(digital_ocean_account_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" + +requirements: + - "python >= 2.6" + +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about user account + community.digitalocean.digital_ocean_account_info: + oauth_token: "{{ oauth_token }}" +''' + + +RETURN = r''' +data: + description: DigitalOcean account information + returned: success + type: dict + sample: { + "droplet_limit": 10, + "email": "testuser1@gmail.com", + "email_verified": true, + "floating_ip_limit": 3, + "status": "active", + "status_message": "", + "uuid": "aaaaaaaaaaaaaa" + } +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get("account") + if response.status_code != 200: + module.fail_json(msg="Failed to fetch 'account' information due to error : %s" % response.json['message']) + + module.exit_json(changed=False, data=response.json["account"]) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_account_facts', 'community.digitalocean.digital_ocean_account_facts'): + module.deprecate("The 'digital_ocean_account_facts' module has been renamed to 'digital_ocean_account_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_block_storage.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_block_storage.py new file mode 100644 index 00000000..4c4a7c8e --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_block_storage.py @@ -0,0 +1,295 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_block_storage +short_description: Create/destroy or attach/detach Block Storage volumes in DigitalOcean +description: + - Create/destroy Block Storage volume in DigitalOcean, or attach/detach Block Storage volume to a droplet. +options: + command: + description: + - Which operation do you want to perform. + choices: ['create', 'attach'] + required: true + type: str + state: + description: + - Indicate desired state of the target. + choices: ['present', 'absent'] + required: true + type: str + block_size: + description: + - The size of the Block Storage volume in gigabytes. + - Required when I(command=create) and I(state=present). + - If snapshot_id is included, this will be ignored. + type: int + volume_name: + description: + - The name of the Block Storage volume. + type: str + required: true + description: + description: + - Description of the Block Storage volume. + type: str + region: + description: + - The slug of the region where your Block Storage volume should be located in. + - If I(snapshot_id) is included, this will be ignored. + type: str + snapshot_id: + description: + - The snapshot id you would like the Block Storage volume created with. + - If included, I(region) and I(block_size) will be ignored and changed to C(null). + type: str + droplet_id: + description: + - The droplet id you want to operate on. + - Required when I(command=attach). + type: int +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Two environment variables can be used, DO_API_KEY and DO_API_TOKEN. + They both refer to the v2 token. + - If snapshot_id is used, region and block_size will be ignored and changed to null. + +author: + - "Harnek Sidhu (@harneksidhu)" +''' + +EXAMPLES = r''' +- name: Create new Block Storage + community.digitalocean.digital_ocean_block_storage: + state: present + command: create + api_token: <TOKEN> + region: nyc1 + block_size: 10 + volume_name: nyc1-block-storage + +- name: Delete Block Storage + community.digitalocean.digital_ocean_block_storage: + state: absent + command: create + api_token: <TOKEN> + region: nyc1 + volume_name: nyc1-block-storage + +- name: Attach Block Storage to a Droplet + community.digitalocean.digital_ocean_block_storage: + state: present + command: attach + api_token: <TOKEN> + volume_name: nyc1-block-storage + region: nyc1 + droplet_id: <ID> + +- name: Detach Block Storage from a Droplet + community.digitalocean.digital_ocean_block_storage: + state: absent + command: attach + api_token: <TOKEN> + volume_name: nyc1-block-storage + region: nyc1 + droplet_id: <ID> +''' + +RETURN = r''' +id: + description: Unique identifier of a Block Storage volume returned during creation. + returned: changed + type: str + sample: "69b25d9a-494c-12e6-a5af-001f53126b44" +''' + +import time +import traceback + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper + + +class DOBlockStorageException(Exception): + pass + + +class DOBlockStorage(object): + def __init__(self, module): + self.module = module + self.rest = DigitalOceanHelper(module) + + def get_key_or_fail(self, k): + v = self.module.params[k] + if v is None: + self.module.fail_json(msg='Unable to load %s' % k) + return v + + def poll_action_for_complete_status(self, action_id): + url = 'actions/{0}'.format(action_id) + end_time = time.time() + self.module.params['timeout'] + while time.time() < end_time: + time.sleep(2) + response = self.rest.get(url) + status = response.status_code + json = response.json + if status == 200: + if json['action']['status'] == 'completed': + return True + elif json['action']['status'] == 'errored': + raise DOBlockStorageException(json['message']) + raise DOBlockStorageException('Unable to reach api.digitalocean.com') + + def get_attached_droplet_ID(self, volume_name, region): + url = 'volumes?name={0}®ion={1}'.format(volume_name, region) + response = self.rest.get(url) + status = response.status_code + json = response.json + if status == 200: + volumes = json['volumes'] + if len(volumes) > 0: + droplet_ids = volumes[0]['droplet_ids'] + if len(droplet_ids) > 0: + return droplet_ids[0] + return None + else: + raise DOBlockStorageException(json['message']) + + def attach_detach_block_storage(self, method, volume_name, region, droplet_id): + data = { + 'type': method, + 'volume_name': volume_name, + 'region': region, + 'droplet_id': droplet_id + } + response = self.rest.post('volumes/actions', data=data) + status = response.status_code + json = response.json + if status == 202: + return self.poll_action_for_complete_status(json['action']['id']) + elif status == 200: + return True + elif status == 422: + return False + else: + raise DOBlockStorageException(json['message']) + + def create_block_storage(self): + volume_name = self.get_key_or_fail('volume_name') + snapshot_id = self.module.params['snapshot_id'] + if snapshot_id: + self.module.params['block_size'] = None + self.module.params['region'] = None + block_size = None + region = None + else: + block_size = self.get_key_or_fail('block_size') + region = self.get_key_or_fail('region') + description = self.module.params['description'] + data = { + 'size_gigabytes': block_size, + 'name': volume_name, + 'description': description, + 'region': region, + 'snapshot_id': snapshot_id, + } + response = self.rest.post("volumes", data=data) + status = response.status_code + json = response.json + if status == 201: + self.module.exit_json(changed=True, id=json['volume']['id']) + elif status == 409 and json['id'] == 'conflict': + self.module.exit_json(changed=False) + else: + raise DOBlockStorageException(json['message']) + + def delete_block_storage(self): + volume_name = self.get_key_or_fail('volume_name') + region = self.get_key_or_fail('region') + url = 'volumes?name={0}®ion={1}'.format(volume_name, region) + attached_droplet_id = self.get_attached_droplet_ID(volume_name, region) + if attached_droplet_id is not None: + self.attach_detach_block_storage('detach', volume_name, region, attached_droplet_id) + response = self.rest.delete(url) + status = response.status_code + json = response.json + if status == 204: + self.module.exit_json(changed=True) + elif status == 404: + self.module.exit_json(changed=False) + else: + raise DOBlockStorageException(json['message']) + + def attach_block_storage(self): + volume_name = self.get_key_or_fail('volume_name') + region = self.get_key_or_fail('region') + droplet_id = self.get_key_or_fail('droplet_id') + attached_droplet_id = self.get_attached_droplet_ID(volume_name, region) + if attached_droplet_id is not None: + if attached_droplet_id == droplet_id: + self.module.exit_json(changed=False) + else: + self.attach_detach_block_storage('detach', volume_name, region, attached_droplet_id) + changed_status = self.attach_detach_block_storage('attach', volume_name, region, droplet_id) + self.module.exit_json(changed=changed_status) + + def detach_block_storage(self): + volume_name = self.get_key_or_fail('volume_name') + region = self.get_key_or_fail('region') + droplet_id = self.get_key_or_fail('droplet_id') + changed_status = self.attach_detach_block_storage('detach', volume_name, region, droplet_id) + self.module.exit_json(changed=changed_status) + + +def handle_request(module): + block_storage = DOBlockStorage(module) + command = module.params['command'] + state = module.params['state'] + if command == 'create': + if state == 'present': + block_storage.create_block_storage() + elif state == 'absent': + block_storage.delete_block_storage() + elif command == 'attach': + if state == 'present': + block_storage.attach_block_storage() + elif state == 'absent': + block_storage.detach_block_storage() + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + state=dict(choices=['present', 'absent'], required=True), + command=dict(choices=['create', 'attach'], required=True), + block_size=dict(type='int', required=False), + volume_name=dict(type='str', required=True), + description=dict(type='str'), + region=dict(type='str', required=False), + snapshot_id=dict(type='str', required=False), + droplet_id=dict(type='int') + ) + + module = AnsibleModule(argument_spec=argument_spec) + + try: + handle_request(module) + except DOBlockStorageException as e: + module.fail_json(msg=e.message, exception=traceback.format_exc()) + except KeyError as e: + module.fail_json(msg='Unable to load %s' % e.message, exception=traceback.format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate.py new file mode 100644 index 00000000..3bf8980b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate.py @@ -0,0 +1,174 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> +# +# 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 = r''' +--- +module: digital_ocean_certificate +short_description: Manage certificates in DigitalOcean +description: + - Create, Retrieve and remove certificates DigitalOcean. +author: "Abhijeet Kasurde (@Akasurde)" +options: + name: + description: + - The name of the certificate. + required: True + type: str + private_key: + description: + - A PEM-formatted private key content of SSL Certificate. + type: str + leaf_certificate: + description: + - A PEM-formatted public SSL Certificate. + type: str + certificate_chain: + description: + - The full PEM-formatted trust chain between the certificate authority's certificate and your domain's SSL certificate. + type: str + state: + description: + - Whether the certificate should be present or absent. + default: present + choices: ['present', 'absent'] + type: str +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Two environment variables can be used, DO_API_KEY, DO_OAUTH_TOKEN and DO_API_TOKEN. + They both refer to the v2 token. +''' + + +EXAMPLES = r''' +- name: Create a certificate + community.digitalocean.digital_ocean_certificate: + name: production + state: present + private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkM8OI7pRpgyj1I\n-----END PRIVATE KEY-----" + leaf_certificate: "-----BEGIN CERTIFICATE-----\nMIIFDmg2Iaw==\n-----END CERTIFICATE-----" + oauth_token: b7d03a6947b217efb6f3ec3bd365652 + +- name: Create a certificate using file lookup plugin + community.digitalocean.digital_ocean_certificate: + name: production + state: present + private_key: "{{ lookup('file', 'test.key') }}" + leaf_certificate: "{{ lookup('file', 'test.cert') }}" + oauth_token: "{{ oauth_token }}" + +- name: Create a certificate with trust chain + community.digitalocean.digital_ocean_certificate: + name: production + state: present + private_key: "{{ lookup('file', 'test.key') }}" + leaf_certificate: "{{ lookup('file', 'test.cert') }}" + certificate_chain: "{{ lookup('file', 'chain.cert') }}" + oauth_token: "{{ oauth_token }}" + +- name: Remove a certificate + community.digitalocean.digital_ocean_certificate: + name: production + state: absent + oauth_token: "{{ oauth_token }}" + +''' + + +RETURN = r''' # ''' + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + state = module.params['state'] + name = module.params['name'] + + rest = DigitalOceanHelper(module) + + results = dict(changed=False) + + response = rest.get('certificates') + status_code = response.status_code + resp_json = response.json + + if status_code != 200: + module.fail_json(msg="Failed to retrieve certificates for DigitalOcean") + + if state == 'present': + for cert in resp_json['certificates']: + if cert['name'] == name: + module.fail_json(msg="Certificate name %s already exists" % name) + + # Certificate does not exist, let us create it + cert_data = dict(name=name, + private_key=module.params['private_key'], + leaf_certificate=module.params['leaf_certificate']) + + if module.params['certificate_chain'] is not None: + cert_data.update(certificate_chain=module.params['certificate_chain']) + + response = rest.post("certificates", data=cert_data) + status_code = response.status_code + if status_code == 500: + module.fail_json(msg="Failed to upload certificates as the certificates are malformed.") + + resp_json = response.json + if status_code == 201: + results.update(changed=True, response=resp_json) + elif status_code == 422: + results.update(changed=False, response=resp_json) + + elif state == 'absent': + cert_id_del = None + for cert in resp_json['certificates']: + if cert['name'] == name: + cert_id_del = cert['id'] + + if cert_id_del is not None: + url = "certificates/{0}".format(cert_id_del) + response = rest.delete(url) + if response.status_code == 204: + results.update(changed=True) + else: + results.update(changed=False) + else: + module.fail_json(msg="Failed to find certificate %s" % name) + + module.exit_json(**results) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + name=dict(type='str', required=True), + leaf_certificate=dict(type='str'), + private_key=dict(type='str', no_log=True), + state=dict(choices=['present', 'absent'], default='present'), + certificate_chain=dict(type='str') + ) + + module = AnsibleModule( + argument_spec=argument_spec, + required_if=[ + ('state', 'present', ['leaf_certificate', 'private_key']), + ], + ) + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e)) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_facts.py new file mode 100644 index 00000000..afadbd09 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_facts.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_certificate_info +short_description: Gather information about DigitalOcean certificates +description: + - This module can be used to gather information about DigitalOcean provided certificates. + - This module was called C(digital_ocean_certificate_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + certificate_id: + description: + - Certificate ID that can be used to identify and reference a certificate. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all certificates + community.digitalocean.digital_ocean_certificate_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about certificate with given id + community.digitalocean.digital_ocean_certificate_info: + oauth_token: "{{ oauth_token }}" + certificate_id: "892071a0-bb95-49bc-8021-3afd67a210bf" + +- name: Get not after information about certificate + community.digitalocean.digital_ocean_certificate_info: + register: resp_out +- set_fact: + not_after_date: "{{ item.not_after }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='web-cert-01']" +- debug: + var: not_after_date +''' + + +RETURN = r''' +data: + description: DigitalOcean certificate information + returned: success + type: list + sample: [ + { + "id": "892071a0-bb95-49bc-8021-3afd67a210bf", + "name": "web-cert-01", + "not_after": "2017-02-22T00:23:00Z", + "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", + "created_at": "2017-02-08T16:02:37Z" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + certificate_id = module.params.get('certificate_id', None) + rest = DigitalOceanHelper(module) + + base_url = 'certificates?' + if certificate_id is not None: + response = rest.get("%s/%s" % (base_url, certificate_id)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve certificates for DigitalOcean") + + resp_json = response.json + certificate = resp_json['certificate'] + else: + certificate = rest.get_paginated_data(base_url=base_url, data_key_name='certificates') + + module.exit_json(changed=False, data=certificate) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + certificate_id=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_certificate_facts', 'community.digitalocean.digital_ocean_certificate_facts'): + module.deprecate("The 'digital_ocean_certificate_facts' module has been renamed to 'digital_ocean_certificate_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_info.py new file mode 100644 index 00000000..afadbd09 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_certificate_info.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_certificate_info +short_description: Gather information about DigitalOcean certificates +description: + - This module can be used to gather information about DigitalOcean provided certificates. + - This module was called C(digital_ocean_certificate_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + certificate_id: + description: + - Certificate ID that can be used to identify and reference a certificate. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all certificates + community.digitalocean.digital_ocean_certificate_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about certificate with given id + community.digitalocean.digital_ocean_certificate_info: + oauth_token: "{{ oauth_token }}" + certificate_id: "892071a0-bb95-49bc-8021-3afd67a210bf" + +- name: Get not after information about certificate + community.digitalocean.digital_ocean_certificate_info: + register: resp_out +- set_fact: + not_after_date: "{{ item.not_after }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='web-cert-01']" +- debug: + var: not_after_date +''' + + +RETURN = r''' +data: + description: DigitalOcean certificate information + returned: success + type: list + sample: [ + { + "id": "892071a0-bb95-49bc-8021-3afd67a210bf", + "name": "web-cert-01", + "not_after": "2017-02-22T00:23:00Z", + "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", + "created_at": "2017-02-08T16:02:37Z" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + certificate_id = module.params.get('certificate_id', None) + rest = DigitalOceanHelper(module) + + base_url = 'certificates?' + if certificate_id is not None: + response = rest.get("%s/%s" % (base_url, certificate_id)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve certificates for DigitalOcean") + + resp_json = response.json + certificate = resp_json['certificate'] + else: + certificate = rest.get_paginated_data(base_url=base_url, data_key_name='certificates') + + module.exit_json(changed=False, data=certificate) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + certificate_id=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_certificate_facts', 'community.digitalocean.digital_ocean_certificate_facts'): + module.deprecate("The 'digital_ocean_certificate_facts' module has been renamed to 'digital_ocean_certificate_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain.py new file mode 100644 index 00000000..465d446f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain.py @@ -0,0 +1,218 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_domain +short_description: Create/delete a DNS domain in DigitalOcean +description: + - Create/delete a DNS domain in DigitalOcean. +author: "Michael Gregson (@mgregson)" +options: + state: + description: + - Indicate desired state of the target. + default: present + choices: ['present', 'absent'] + type: str + id: + description: + - The droplet id you want to operate on. + aliases: ['droplet_id'] + type: int + name: + description: + - The name of the droplet - must be formatted by hostname rules, or the name of a SSH key, or the name of a domain. + type: str + ip: + description: + - An 'A' record for '@' ($ORIGIN) will be created with the value 'ip'. 'ip' is an IP version 4 address. + type: str +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Environment variables DO_OAUTH_TOKEN can be used for the oauth_token. + - As of Ansible 1.9.5 and 2.0, Version 2 of the DigitalOcean API is used, this removes C(client_id) and C(api_key) options in favor of C(oauth_token). + - If you are running Ansible 1.9.4 or earlier you might not be able to use the included version of this module as the API version used has been retired. + +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Create a domain + community.digitalocean.digital_ocean_domain: + state: present + name: my.digitalocean.domain + ip: 127.0.0.1 + +# Create a droplet and corresponding domain +- name: Create a droplet + community.digitalocean.digital_ocean: + state: present + name: test_droplet + size_id: 1gb + region_id: sgp1 + image_id: ubuntu-14-04-x64 + register: test_droplet + +- name: Create a corresponding domain + community.digitalocean.digital_ocean_domain: + state: present + name: "{{ test_droplet.droplet.name }}.my.domain" + ip: "{{ test_droplet.droplet.ip_address }}" + +''' + +import traceback +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +class DoManager(DigitalOceanHelper, object): + def __init__(self, module): + super(DoManager, self).__init__(module) + self.domain_name = module.params.get('name', None) + self.domain_ip = module.params.get('ip', None) + self.domain_id = module.params.get('id', None) + + @staticmethod + def jsonify(response): + return response.status_code, response.json + + def all_domains(self): + resp = self.get('domains/') + return resp + + def find(self): + if self.domain_name is None and self.domain_id is None: + return False + + domains = self.all_domains() + status, json = self.jsonify(domains) + for domain in json['domains']: + if domain['name'] == self.domain_name: + return True + return False + + def add(self): + params = {'name': self.domain_name, 'ip_address': self.domain_ip} + resp = self.post('domains/', data=params) + status = resp.status_code + json = resp.json + if status == 201: + return json['domain'] + else: + return json + + def all_domain_records(self): + resp = self.get('domains/%s/records/' % self.domain_name) + return resp.json + + def domain_record(self): + resp = self.get('domains/%s' % self.domain_name) + status, json = self.jsonify(resp) + return json + + def destroy_domain(self): + resp = self.delete('domains/%s' % self.domain_name) + status, json = self.jsonify(resp) + if status == 204: + return True + else: + return json + + def edit_domain_record(self, record): + params = {'name': '@', + 'data': self.module.params.get('ip')} + resp = self.put('domains/%s/records/%s' % (self.domain_name, record['id']), data=params) + status, json = self.jsonify(resp) + + return json['domain_record'] + + def create_domain_record(self): + params = {'name': '@', + 'type': 'A', + 'data': self.module.params.get('ip')} + + resp = self.post('domains/%s/records' % (self.domain_name), data=params) + status, json = self.jsonify(resp) + + return json['domain_record'] + + +def core(module): + do_manager = DoManager(module) + state = module.params.get('state') + + domain = do_manager.find() + if state == 'present': + if not domain: + domain = do_manager.add() + if 'message' in domain: + module.fail_json(changed=False, msg=domain['message']) + else: + module.exit_json(changed=True, domain=domain) + else: + records = do_manager.all_domain_records() + at_record = None + for record in records['domain_records']: + if record['name'] == "@" and record['type'] == 'A': + at_record = record + + if not at_record: + do_manager.create_domain_record() + module.exit_json(changed=True, domain=do_manager.find()) + elif not at_record['data'] == module.params.get('ip'): + do_manager.edit_domain_record(at_record) + module.exit_json(changed=True, domain=do_manager.find()) + else: + module.exit_json(changed=False, domain=do_manager.domain_record()) + + elif state == 'absent': + if not domain: + module.exit_json(changed=False, msg="Domain not found") + else: + delete_event = do_manager.destroy_domain() + if not delete_event: + module.fail_json(changed=False, msg=delete_event['message']) + else: + module.exit_json(changed=True, event=None) + delete_event = do_manager.destroy_domain() + module.exit_json(changed=delete_event) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + state=dict(choices=['present', 'absent'], default='present'), + name=dict(type='str'), + id=dict(aliases=['droplet_id'], type='int'), + ip=dict(type='str') + ) + + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=( + ['id', 'name'], + ), + ) + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=traceback.format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_facts.py new file mode 100644 index 00000000..851e75d4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_facts.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_domain_info +short_description: Gather information about DigitalOcean Domains +description: + - This module can be used to gather information about DigitalOcean provided Domains. + - This module was called C(digital_ocean_domain_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + domain_name: + description: + - Name of the domain to gather information for. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all domains + community.digitalocean.digital_ocean_domain_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about domain with given name + community.digitalocean.digital_ocean_domain_info: + oauth_token: "{{ oauth_token }}" + domain_name: "example.com" + +- name: Get ttl from domain + community.digitalocean.digital_ocean_domain_info: + register: resp_out +- set_fact: + domain_ttl: "{{ item.ttl }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='example.com']" +- debug: + var: domain_ttl +''' + + +RETURN = r''' +data: + description: DigitalOcean Domain information + returned: success + type: list + sample: [ + { + "domain_records": [ + { + "data": "ns1.digitalocean.com", + "flags": null, + "id": 37826823, + "name": "@", + "port": null, + "priority": null, + "tag": null, + "ttl": 1800, + "type": "NS", + "weight": null + }, + ], + "name": "myexample123.com", + "ttl": 1800, + "zone_file": "myexample123.com. IN SOA ns1.digitalocean.com. hostmaster.myexample123.com. 1520702984 10800 3600 604800 1800\n", + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + domain_name = module.params.get('domain_name', None) + rest = DigitalOceanHelper(module) + domain_results = [] + + if domain_name is not None: + response = rest.get("domains/%s" % domain_name) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve domain for DigitalOcean") + + resp_json = response.json + domains = [resp_json['domain']] + else: + domains = rest.get_paginated_data(base_url="domains?", data_key_name='domains') + + for temp_domain in domains: + temp_domain_dict = { + "name": temp_domain['name'], + "ttl": temp_domain['ttl'], + "zone_file": temp_domain['zone_file'], + "domain_records": list(), + } + + base_url = "domains/%s/records?" % temp_domain['name'] + + temp_domain_dict["domain_records"] = rest.get_paginated_data(base_url=base_url, data_key_name='domain_records') + domain_results.append(temp_domain_dict) + + module.exit_json(changed=False, data=domain_results) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + domain_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_domain_facts', 'community.digitalocean.digital_ocean_domain_facts'): + module.deprecate("The 'digital_ocean_domain_facts' module has been renamed to 'digital_ocean_domain_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_info.py new file mode 100644 index 00000000..851e75d4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_domain_info.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_domain_info +short_description: Gather information about DigitalOcean Domains +description: + - This module can be used to gather information about DigitalOcean provided Domains. + - This module was called C(digital_ocean_domain_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + domain_name: + description: + - Name of the domain to gather information for. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all domains + community.digitalocean.digital_ocean_domain_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about domain with given name + community.digitalocean.digital_ocean_domain_info: + oauth_token: "{{ oauth_token }}" + domain_name: "example.com" + +- name: Get ttl from domain + community.digitalocean.digital_ocean_domain_info: + register: resp_out +- set_fact: + domain_ttl: "{{ item.ttl }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='example.com']" +- debug: + var: domain_ttl +''' + + +RETURN = r''' +data: + description: DigitalOcean Domain information + returned: success + type: list + sample: [ + { + "domain_records": [ + { + "data": "ns1.digitalocean.com", + "flags": null, + "id": 37826823, + "name": "@", + "port": null, + "priority": null, + "tag": null, + "ttl": 1800, + "type": "NS", + "weight": null + }, + ], + "name": "myexample123.com", + "ttl": 1800, + "zone_file": "myexample123.com. IN SOA ns1.digitalocean.com. hostmaster.myexample123.com. 1520702984 10800 3600 604800 1800\n", + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + domain_name = module.params.get('domain_name', None) + rest = DigitalOceanHelper(module) + domain_results = [] + + if domain_name is not None: + response = rest.get("domains/%s" % domain_name) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve domain for DigitalOcean") + + resp_json = response.json + domains = [resp_json['domain']] + else: + domains = rest.get_paginated_data(base_url="domains?", data_key_name='domains') + + for temp_domain in domains: + temp_domain_dict = { + "name": temp_domain['name'], + "ttl": temp_domain['ttl'], + "zone_file": temp_domain['zone_file'], + "domain_records": list(), + } + + base_url = "domains/%s/records?" % temp_domain['name'] + + temp_domain_dict["domain_records"] = rest.get_paginated_data(base_url=base_url, data_key_name='domain_records') + domain_results.append(temp_domain_dict) + + module.exit_json(changed=False, data=domain_results) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + domain_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_domain_facts', 'community.digitalocean.digital_ocean_domain_facts'): + module.deprecate("The 'digital_ocean_domain_facts' module has been renamed to 'digital_ocean_domain_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_droplet.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_droplet.py new file mode 100644 index 00000000..32e58725 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_droplet.py @@ -0,0 +1,351 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_droplet +short_description: Create and delete a DigitalOcean droplet +description: + - Create and delete a droplet in DigitalOcean and optionally wait for it to be active. +author: "Gurchet Rai (@gurch101)" +options: + state: + description: + - Indicate desired state of the target. + default: present + choices: ['present', 'absent'] + id: + description: + - Numeric, the droplet id you want to operate on. + aliases: ['droplet_id'] + name: + description: + - String, this is the name of the droplet - must be formatted by hostname rules. + unique_name: + description: + - require unique hostnames. By default, DigitalOcean allows multiple hosts with the same name. Setting this to "yes" allows only one host + per name. Useful for idempotence. + default: False + type: bool + size: + description: + - This is the slug of the size you would like the droplet created with. + aliases: ['size_id'] + image: + description: + - This is the slug of the image you would like the droplet created with. + aliases: ['image_id'] + region: + description: + - This is the slug of the region you would like your server to be created in. + aliases: ['region_id'] + ssh_keys: + description: + - array of SSH key Fingerprint that you would like to be added to the server. + required: False + private_networking: + description: + - add an additional, private network interface to droplet for inter-droplet communication. + default: False + type: bool + vpc_uuid: + description: + - A string specifying the UUID of the VPC to which the Droplet will be assigned. If excluded, Droplet will be + assigned to the account's default VPC for the region. + type: str + version_added: 0.1.0 + user_data: + description: + - opaque blob of data which is made available to the droplet + required: False + ipv6: + description: + - enable IPv6 for your droplet. + required: False + default: False + type: bool + wait: + description: + - Wait for the droplet to be active before returning. If wait is "no" an ip_address may not be returned. + required: False + default: True + type: bool + wait_timeout: + description: + - How long before wait gives up, in seconds, when creating a droplet. + default: 120 + backups: + description: + - indicates whether automated backups should be enabled. + required: False + default: False + type: bool + monitoring: + description: + - indicates whether to install the DigitalOcean agent for monitoring. + required: False + default: False + type: bool + tags: + description: + - List, A list of tag names as strings to apply to the Droplet after it is created. Tag names can either be existing or new tags. + required: False + volumes: + description: + - List, A list including the unique string identifier for each Block Storage volume to be attached to the Droplet. + required: False + oauth_token: + description: + - DigitalOcean OAuth token. Can be specified in C(DO_API_KEY), C(DO_API_TOKEN), or C(DO_OAUTH_TOKEN) environment variables + aliases: ['API_TOKEN'] + required: True +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Create a new droplet + community.digitalocean.digital_ocean_droplet: + state: present + name: mydroplet + oauth_token: XXX + size: 2gb + region: sfo1 + image: ubuntu-16-04-x64 + wait_timeout: 500 + ssh_keys: [ .... ] + register: my_droplet + +- debug: + msg: "ID is {{ my_droplet.data.droplet.id }}, IP is {{ my_droplet.data.ip_address }}" + +- name: Ensure a droplet is present + community.digitalocean.digital_ocean_droplet: + state: present + id: 123 + name: mydroplet + oauth_token: XXX + size: 2gb + region: sfo1 + image: ubuntu-16-04-x64 + wait_timeout: 500 + +- name: Ensure a droplet is present with SSH keys installed + community.digitalocean.digital_ocean_droplet: + state: present + id: 123 + name: mydroplet + oauth_token: XXX + size: 2gb + region: sfo1 + ssh_keys: ['1534404', '1784768'] + image: ubuntu-16-04-x64 + wait_timeout: 500 +''' + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#droplets +data: + description: a DigitalOcean Droplet + returned: changed + type: dict + sample: { + "ip_address": "104.248.118.172", + "ipv6_address": "2604:a880:400:d1::90a:6001", + "private_ipv4_address": "10.136.122.141", + "droplet": { + "id": 3164494, + "name": "example.com", + "memory": 512, + "vcpus": 1, + "disk": 20, + "locked": true, + "status": "new", + "kernel": { + "id": 2233, + "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic", + "version": "3.13.0-37-generic" + }, + "created_at": "2014-11-14T16:36:31Z", + "features": ["virtio"], + "backup_ids": [], + "snapshot_ids": [], + "image": {}, + "volume_ids": [], + "size": {}, + "size_slug": "512mb", + "networks": {}, + "region": {}, + "tags": ["web"] + } + } +''' + +import time +import json +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper + + +class DODroplet(object): + def __init__(self, module): + self.rest = DigitalOceanHelper(module) + self.module = module + self.wait = self.module.params.pop('wait', True) + self.wait_timeout = self.module.params.pop('wait_timeout', 120) + self.unique_name = self.module.params.pop('unique_name', False) + # pop the oauth token so we don't include it in the POST data + self.module.params.pop('oauth_token') + + def get_by_id(self, droplet_id): + if not droplet_id: + return None + response = self.rest.get('droplets/{0}'.format(droplet_id)) + json_data = response.json + if response.status_code == 200: + return json_data + return None + + def get_by_name(self, droplet_name): + if not droplet_name: + return None + page = 1 + while page is not None: + response = self.rest.get('droplets?page={0}'.format(page)) + json_data = response.json + if response.status_code == 200: + for droplet in json_data['droplets']: + if droplet['name'] == droplet_name: + return {'droplet': droplet} + if 'links' in json_data and 'pages' in json_data['links'] and 'next' in json_data['links']['pages']: + page += 1 + else: + page = None + return None + + def get_addresses(self, data): + """ + Expose IP addresses as their own property allowing users extend to additional tasks + """ + _data = data + for k, v in data.items(): + setattr(self, k, v) + networks = _data['droplet']['networks'] + for network in networks.get('v4', []): + if network['type'] == 'public': + _data['ip_address'] = network['ip_address'] + else: + _data['private_ipv4_address'] = network['ip_address'] + for network in networks.get('v6', []): + if network['type'] == 'public': + _data['ipv6_address'] = network['ip_address'] + else: + _data['private_ipv6_address'] = network['ip_address'] + return _data + + def get_droplet(self): + json_data = self.get_by_id(self.module.params['id']) + if not json_data and self.unique_name: + json_data = self.get_by_name(self.module.params['name']) + return json_data + + def create(self): + json_data = self.get_droplet() + droplet_data = None + if json_data: + droplet_data = self.get_addresses(json_data) + self.module.exit_json(changed=False, data=droplet_data) + if self.module.check_mode: + self.module.exit_json(changed=True) + request_params = dict(self.module.params) + del request_params['id'] + response = self.rest.post('droplets', data=request_params) + json_data = response.json + if response.status_code >= 400: + self.module.fail_json(changed=False, msg=json_data['message']) + if self.wait: + json_data = self.ensure_power_on(json_data['droplet']['id']) + droplet_data = self.get_addresses(json_data) + self.module.exit_json(changed=True, data=droplet_data) + + def delete(self): + json_data = self.get_droplet() + if json_data: + if self.module.check_mode: + self.module.exit_json(changed=True) + response = self.rest.delete('droplets/{0}'.format(json_data['droplet']['id'])) + json_data = response.json + if response.status_code == 204: + self.module.exit_json(changed=True, msg='Droplet deleted') + self.module.fail_json(changed=False, msg='Failed to delete droplet') + else: + self.module.exit_json(changed=False, msg='Droplet not found') + + def ensure_power_on(self, droplet_id): + end_time = time.time() + self.wait_timeout + while time.time() < end_time: + response = self.rest.get('droplets/{0}'.format(droplet_id)) + json_data = response.json + if json_data['droplet']['status'] == 'active': + return json_data + time.sleep(min(2, end_time - time.time())) + self.module.fail_json(msg='Wait for droplet powering on timeout') + + +def core(module): + state = module.params.pop('state') + droplet = DODroplet(module) + if state == 'present': + droplet.create() + elif state == 'absent': + droplet.delete() + + +def main(): + module = AnsibleModule( + argument_spec=dict( + state=dict(choices=['present', 'absent'], default='present'), + oauth_token=dict( + aliases=['API_TOKEN'], + no_log=True, + fallback=(env_fallback, ['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN']) + ), + name=dict(type='str'), + size=dict(aliases=['size_id']), + image=dict(aliases=['image_id']), + region=dict(aliases=['region_id']), + ssh_keys=dict(type='list'), + private_networking=dict(type='bool', default=False), + vpc_uuid=dict(type='str'), + backups=dict(type='bool', default=False), + monitoring=dict(type='bool', default=False), + id=dict(aliases=['droplet_id'], type='int'), + user_data=dict(default=None), + ipv6=dict(type='bool', default=False), + volumes=dict(type='list'), + tags=dict(type='list'), + wait=dict(type='bool', default=True), + wait_timeout=dict(default=120, type='int'), + unique_name=dict(type='bool', default=False), + ), + required_one_of=( + ['id', 'name'], + ), + required_if=([ + ('state', 'present', ['name', 'size', 'image', 'region']), + ]), + supports_check_mode=True, + ) + + core(module) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_facts.py new file mode 100644 index 00000000..de078f9a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_facts.py @@ -0,0 +1,132 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Anthony Bond <ajbond2005@gmail.com> +# 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 = r''' +--- +module: digital_ocean_firewall_info +short_description: Gather information about DigitalOcean firewalls +description: + - This module can be used to gather information about DigitalOcean firewalls. + - This module was called C(digital_ocean_firewall_facts) before Ansible 2.9. The usage did not change. +author: "Anthony Bond (@BondAnthony)" +options: + name: + description: + - Firewall rule name that can be used to identify and reference a specific firewall rule. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all firewalls + community.digitalocean.digital_ocean_firewall_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about a specific firewall by name + community.digitalocean.digital_ocean_firewall_info: + oauth_token: "{{ oauth_token }}" + name: "firewall_name" + +- name: Gather information from a firewall rule + community.digitalocean.digital_ocean_firewall_info: + name: SSH + register: resp_out + +- set_fact: + firewall_id: "{{ resp_out.data.id }}" + +- debug: + msg: "{{ firewall_id }}" +''' + + +RETURN = r''' +data: + description: DigitalOcean firewall information + returned: success + type: list + sample: [ + { + "id": "435tbg678-1db53-32b6-t543-28322569t252", + "name": "metrics", + "status": "succeeded", + "inbound_rules": [ + { + "protocol": "tcp", + "ports": "9100", + "sources": { + "addresses": [ + "1.1.1.1" + ] + } + } + ], + "outbound_rules": [], + "created_at": "2018-01-15T07:04:25Z", + "droplet_ids": [ + 87426985 + ], + "tags": [], + "pending_changes": [] + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + firewall_name = module.params.get('name', None) + rest = DigitalOceanHelper(module) + base_url = 'firewalls?' + + response = rest.get("%s" % base_url) + status_code = response.status_code + if status_code != 200: + module.fail_json(msg="Failed to retrieve firewalls from Digital Ocean") + firewalls = rest.get_paginated_data(base_url=base_url, data_key_name='firewalls') + + if firewall_name is not None: + rule = {} + for firewall in firewalls: + if firewall['name'] == firewall_name: + rule.update(firewall) + module.exit_json(changed=False, data=rule) + else: + module.exit_json(changed=False, data=firewalls) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_firewall_facts', 'community.digitalocean.digital_ocean_firewall_facts'): + module.deprecate("The 'digital_ocean_firewall_facts' module has been renamed to 'digital_ocean_firewall_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_info.py new file mode 100644 index 00000000..de078f9a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_firewall_info.py @@ -0,0 +1,132 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Anthony Bond <ajbond2005@gmail.com> +# 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 = r''' +--- +module: digital_ocean_firewall_info +short_description: Gather information about DigitalOcean firewalls +description: + - This module can be used to gather information about DigitalOcean firewalls. + - This module was called C(digital_ocean_firewall_facts) before Ansible 2.9. The usage did not change. +author: "Anthony Bond (@BondAnthony)" +options: + name: + description: + - Firewall rule name that can be used to identify and reference a specific firewall rule. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all firewalls + community.digitalocean.digital_ocean_firewall_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about a specific firewall by name + community.digitalocean.digital_ocean_firewall_info: + oauth_token: "{{ oauth_token }}" + name: "firewall_name" + +- name: Gather information from a firewall rule + community.digitalocean.digital_ocean_firewall_info: + name: SSH + register: resp_out + +- set_fact: + firewall_id: "{{ resp_out.data.id }}" + +- debug: + msg: "{{ firewall_id }}" +''' + + +RETURN = r''' +data: + description: DigitalOcean firewall information + returned: success + type: list + sample: [ + { + "id": "435tbg678-1db53-32b6-t543-28322569t252", + "name": "metrics", + "status": "succeeded", + "inbound_rules": [ + { + "protocol": "tcp", + "ports": "9100", + "sources": { + "addresses": [ + "1.1.1.1" + ] + } + } + ], + "outbound_rules": [], + "created_at": "2018-01-15T07:04:25Z", + "droplet_ids": [ + 87426985 + ], + "tags": [], + "pending_changes": [] + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + firewall_name = module.params.get('name', None) + rest = DigitalOceanHelper(module) + base_url = 'firewalls?' + + response = rest.get("%s" % base_url) + status_code = response.status_code + if status_code != 200: + module.fail_json(msg="Failed to retrieve firewalls from Digital Ocean") + firewalls = rest.get_paginated_data(base_url=base_url, data_key_name='firewalls') + + if firewall_name is not None: + rule = {} + for firewall in firewalls: + if firewall['name'] == firewall_name: + rule.update(firewall) + module.exit_json(changed=False, data=rule) + else: + module.exit_json(changed=False, data=firewalls) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_firewall_facts', 'community.digitalocean.digital_ocean_firewall_facts'): + module.deprecate("The 'digital_ocean_firewall_facts' module has been renamed to 'digital_ocean_firewall_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip.py new file mode 100644 index 00000000..90c8d087 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip.py @@ -0,0 +1,311 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# (c) 2015, Patrick F. Marques <patrickfmarques@gmail.com> +# 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 = r''' +--- +module: digital_ocean_floating_ip +short_description: Manage DigitalOcean Floating IPs +description: + - Create/delete/assign a floating IP. +author: "Patrick Marques (@pmarques)" +options: + state: + description: + - Indicate desired state of the target. + default: present + choices: ['present', 'absent'] + ip: + description: + - Public IP address of the Floating IP. Used to remove an IP + region: + description: + - The region that the Floating IP is reserved to. + droplet_id: + description: + - The Droplet that the Floating IP has been assigned to. + oauth_token: + description: + - DigitalOcean OAuth token. + required: true +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: "Create a Floating IP in region lon1" + community.digitalocean.digital_ocean_floating_ip: + state: present + region: lon1 + +- name: "Create a Floating IP assigned to Droplet ID 123456" + community.digitalocean.digital_ocean_floating_ip: + state: present + droplet_id: 123456 + +- name: "Delete a Floating IP with ip 1.2.3.4" + community.digitalocean.digital_ocean_floating_ip: + state: absent + ip: "1.2.3.4" + +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#floating-ips +data: + description: a DigitalOcean Floating IP resource + returned: success and no resource constraint + type: dict + sample: { + "action": { + "id": 68212728, + "status": "in-progress", + "type": "assign_ip", + "started_at": "2015-10-15T17:45:44Z", + "completed_at": null, + "resource_id": 758603823, + "resource_type": "floating_ip", + "region": { + "name": "New York 3", + "slug": "nyc3", + "sizes": [ + "512mb", + "1gb", + "2gb", + "4gb", + "8gb", + "16gb", + "32gb", + "48gb", + "64gb" + ], + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata" + ], + "available": true + }, + "region_slug": "nyc3" + } + } +''' + +import json +import time + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import env_fallback +from ansible.module_utils.urls import fetch_url + + +class Response(object): + + def __init__(self, resp, info): + self.body = None + if resp: + self.body = resp.read() + self.info = info + + @property + def json(self): + if not self.body: + if "body" in self.info: + return json.loads(self.info["body"]) + return None + try: + return json.loads(self.body) + except ValueError: + return None + + @property + def status_code(self): + return self.info["status"] + + +class Rest(object): + + def __init__(self, module, headers): + self.module = module + self.headers = headers + self.baseurl = 'https://api.digitalocean.com/v2' + + def _url_builder(self, path): + if path[0] == '/': + path = path[1:] + return '%s/%s' % (self.baseurl, path) + + def send(self, method, path, data=None, headers=None): + url = self._url_builder(path) + data = self.module.jsonify(data) + timeout = self.module.params['timeout'] + + resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method, timeout=timeout) + + # Exceptions in fetch_url may result in a status -1, the ensures a + if info['status'] == -1: + self.module.fail_json(msg=info['msg']) + + return Response(resp, info) + + def get(self, path, data=None, headers=None): + return self.send('GET', path, data, headers) + + def put(self, path, data=None, headers=None): + return self.send('PUT', path, data, headers) + + def post(self, path, data=None, headers=None): + return self.send('POST', path, data, headers) + + def delete(self, path, data=None, headers=None): + return self.send('DELETE', path, data, headers) + + +def wait_action(module, rest, ip, action_id, timeout=10): + end_time = time.time() + 10 + while time.time() < end_time: + response = rest.get('floating_ips/{0}/actions/{1}'.format(ip, action_id)) + status_code = response.status_code + status = response.json['action']['status'] + # TODO: check status_code == 200? + if status == 'completed': + return True + elif status == 'errored': + module.fail_json(msg='Floating ip action error [ip: {0}: action: {1}]'.format( + ip, action_id), data=json) + + module.fail_json(msg='Floating ip action timeout [ip: {0}: action: {1}]'.format( + ip, action_id), data=json) + + +def core(module): + api_token = module.params['oauth_token'] + state = module.params['state'] + ip = module.params['ip'] + droplet_id = module.params['droplet_id'] + + rest = Rest(module, {'Authorization': 'Bearer {0}'.format(api_token), + 'Content-type': 'application/json'}) + + if state in ('present'): + if droplet_id is not None and module.params['ip'] is not None: + # Lets try to associate the ip to the specified droplet + associate_floating_ips(module, rest) + else: + create_floating_ips(module, rest) + + elif state in ('absent'): + response = rest.delete("floating_ips/{0}".format(ip)) + status_code = response.status_code + json_data = response.json + if status_code == 204: + module.exit_json(changed=True) + elif status_code == 404: + module.exit_json(changed=False) + else: + module.exit_json(changed=False, data=json_data) + + +def get_floating_ip_details(module, rest): + ip = module.params['ip'] + + response = rest.get("floating_ips/{0}".format(ip)) + status_code = response.status_code + json_data = response.json + if status_code == 200: + return json_data['floating_ip'] + else: + module.fail_json(msg="Error assigning floating ip [{0}: {1}]".format( + status_code, json_data["message"]), region=module.params['region']) + + +def assign_floating_id_to_droplet(module, rest): + ip = module.params['ip'] + + payload = { + "type": "assign", + "droplet_id": module.params['droplet_id'], + } + + response = rest.post("floating_ips/{0}/actions".format(ip), data=payload) + status_code = response.status_code + json_data = response.json + if status_code == 201: + wait_action(module, rest, ip, json_data['action']['id']) + + module.exit_json(changed=True, data=json_data) + else: + module.fail_json(msg="Error creating floating ip [{0}: {1}]".format( + status_code, json_data["message"]), region=module.params['region']) + + +def associate_floating_ips(module, rest): + floating_ip = get_floating_ip_details(module, rest) + droplet = floating_ip['droplet'] + + # TODO: If already assigned to a droplet verify if is one of the specified as valid + if droplet is not None and str(droplet['id']) in [module.params['droplet_id']]: + module.exit_json(changed=False) + else: + assign_floating_id_to_droplet(module, rest) + + +def create_floating_ips(module, rest): + payload = { + } + + if module.params['region'] is not None: + payload["region"] = module.params['region'] + if module.params['droplet_id'] is not None: + payload["droplet_id"] = module.params['droplet_id'] + + response = rest.post("floating_ips", data=payload) + status_code = response.status_code + json_data = response.json + if status_code == 202: + module.exit_json(changed=True, data=json_data) + else: + module.fail_json(msg="Error creating floating ip [{0}: {1}]".format( + status_code, json_data["message"]), region=module.params['region']) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + state=dict(choices=['present', 'absent'], default='present'), + ip=dict(aliases=['id'], required=False), + region=dict(required=False), + droplet_id=dict(required=False), + oauth_token=dict( + no_log=True, + # Support environment variable for DigitalOcean OAuth Token + fallback=(env_fallback, ['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN']), + required=True, + ), + validate_certs=dict(type='bool', default=True), + timeout=dict(type='int', default=30), + ), + required_if=[ + ('state', 'delete', ['ip']) + ], + mutually_exclusive=[ + ['region', 'droplet_id'] + ], + ) + + core(module) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_facts.py new file mode 100644 index 00000000..0346cda6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_facts.py @@ -0,0 +1,120 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (C) 2017-18, Ansible Project +# 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 = r''' +--- +module: digital_ocean_floating_ip_info +short_description: DigitalOcean Floating IPs information +description: + - This module can be used to fetch DigitalOcean Floating IPs information. + - This module was called C(digital_ocean_floating_ip_facts) before Ansible 2.9. The usage did not change. +author: "Patrick Marques (@pmarques)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: "Gather information about all Floating IPs" + community.digitalocean.digital_ocean_floating_ip_info: + register: result + +- name: "List of current floating ips" + debug: + var: result.floating_ips +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#floating-ips +floating_ips: + description: a DigitalOcean Floating IP resource + returned: success and no resource constraint + type: list + sample: [ + { + "ip": "45.55.96.47", + "droplet": null, + "region": { + "name": "New York 3", + "slug": "nyc3", + "sizes": [ + "512mb", + "1gb", + "2gb", + "4gb", + "8gb", + "16gb", + "32gb", + "48gb", + "64gb" + ], + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata" + ], + "available": true + }, + "locked": false + } + ] +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + page = 1 + has_next = True + floating_ips = [] + status_code = None + while has_next or status_code != 200: + response = rest.get("floating_ips?page={0}&per_page=20".format(page)) + status_code = response.status_code + # stop if any error during pagination + if status_code != 200: + break + page += 1 + floating_ips.extend(response.json["floating_ips"]) + has_next = "pages" in response.json["links"] and "next" in response.json["links"]["pages"] + + if status_code == 200: + module.exit_json(changed=False, floating_ips=floating_ips) + else: + module.fail_json(msg="Error fetching information [{0}: {1}]".format( + status_code, response.json["message"])) + + +def main(): + module = AnsibleModule( + argument_spec=DigitalOceanHelper.digital_ocean_argument_spec() + ) + if module._name in ('digital_ocean_floating_ip_facts', 'community.digitalocean.digital_ocean_floating_ip_facts'): + module.deprecate("The 'digital_ocean_floating_ip_facts' module has been renamed to 'digital_ocean_floating_ip_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e)) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_info.py new file mode 100644 index 00000000..0346cda6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_floating_ip_info.py @@ -0,0 +1,120 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (C) 2017-18, Ansible Project +# 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 = r''' +--- +module: digital_ocean_floating_ip_info +short_description: DigitalOcean Floating IPs information +description: + - This module can be used to fetch DigitalOcean Floating IPs information. + - This module was called C(digital_ocean_floating_ip_facts) before Ansible 2.9. The usage did not change. +author: "Patrick Marques (@pmarques)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: "Gather information about all Floating IPs" + community.digitalocean.digital_ocean_floating_ip_info: + register: result + +- name: "List of current floating ips" + debug: + var: result.floating_ips +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#floating-ips +floating_ips: + description: a DigitalOcean Floating IP resource + returned: success and no resource constraint + type: list + sample: [ + { + "ip": "45.55.96.47", + "droplet": null, + "region": { + "name": "New York 3", + "slug": "nyc3", + "sizes": [ + "512mb", + "1gb", + "2gb", + "4gb", + "8gb", + "16gb", + "32gb", + "48gb", + "64gb" + ], + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata" + ], + "available": true + }, + "locked": false + } + ] +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + page = 1 + has_next = True + floating_ips = [] + status_code = None + while has_next or status_code != 200: + response = rest.get("floating_ips?page={0}&per_page=20".format(page)) + status_code = response.status_code + # stop if any error during pagination + if status_code != 200: + break + page += 1 + floating_ips.extend(response.json["floating_ips"]) + has_next = "pages" in response.json["links"] and "next" in response.json["links"]["pages"] + + if status_code == 200: + module.exit_json(changed=False, floating_ips=floating_ips) + else: + module.fail_json(msg="Error fetching information [{0}: {1}]".format( + status_code, response.json["message"])) + + +def main(): + module = AnsibleModule( + argument_spec=DigitalOceanHelper.digital_ocean_argument_spec() + ) + if module._name in ('digital_ocean_floating_ip_facts', 'community.digitalocean.digital_ocean_floating_ip_facts'): + module.deprecate("The 'digital_ocean_floating_ip_facts' module has been renamed to 'digital_ocean_floating_ip_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e)) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_facts.py new file mode 100644 index 00000000..82306cac --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_facts.py @@ -0,0 +1,150 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_image_info +short_description: Gather information about DigitalOcean images +description: + - This module can be used to gather information about DigitalOcean provided images. + - These images can be either of type C(distribution), C(application) and C(private). + - This module was called C(digital_ocean_image_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + image_type: + description: + - Specifies the type of image information to be retrieved. + - If set to C(application), then information are gathered related to all application images. + - If set to C(distribution), then information are gathered related to all distribution images. + - If set to C(private), then information are gathered related to all private images. + - If not set to any of above, then information are gathered related to all images. + default: 'all' + choices: [ 'all', 'application', 'distribution', 'private' ] + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all images + community.digitalocean.digital_ocean_image_info: + image_type: all + oauth_token: "{{ oauth_token }}" + +- name: Gather information about application images + community.digitalocean.digital_ocean_image_info: + image_type: application + oauth_token: "{{ oauth_token }}" + +- name: Gather information about distribution images + community.digitalocean.digital_ocean_image_info: + image_type: distribution + oauth_token: "{{ oauth_token }}" + +- name: Get distribution about image with slug coreos-beta + community.digitalocean.digital_ocean_image_info: + register: resp_out +- set_fact: + distribution_name: "{{ item.distribution }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?slug=='coreos-beta']" +- debug: + var: distribution_name + +''' + + +RETURN = r''' +data: + description: DigitalOcean image information + returned: success + type: list + sample: [ + { + "created_at": "2018-02-02T07:11:43Z", + "distribution": "CoreOS", + "id": 31434061, + "min_disk_size": 20, + "name": "1662.1.0 (beta)", + "public": true, + "regions": [ + "nyc1", + "sfo1", + "nyc2", + "ams2", + "sgp1", + "lon1", + "nyc3", + "ams3", + "fra1", + "tor1", + "sfo2", + "blr1" + ], + "size_gigabytes": 0.42, + "slug": "coreos-beta", + "type": "snapshot" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + image_type = module.params['image_type'] + + rest = DigitalOceanHelper(module) + + base_url = 'images?' + if image_type == 'distribution': + base_url += "type=distribution&" + elif image_type == 'application': + base_url += "type=application&" + elif image_type == 'private': + base_url += "private=true&" + + images = rest.get_paginated_data(base_url=base_url, data_key_name='images') + + module.exit_json(changed=False, data=images) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + image_type=dict(type='str', + required=False, + choices=['all', 'application', 'distribution', 'private'], + default='all' + ) + ) + + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_image_facts', 'community.digitalocean.digital_ocean_image_facts'): + module.deprecate("The 'digital_ocean_image_facts' module has been renamed to 'digital_ocean_image_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_info.py new file mode 100644 index 00000000..82306cac --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_image_info.py @@ -0,0 +1,150 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_image_info +short_description: Gather information about DigitalOcean images +description: + - This module can be used to gather information about DigitalOcean provided images. + - These images can be either of type C(distribution), C(application) and C(private). + - This module was called C(digital_ocean_image_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + image_type: + description: + - Specifies the type of image information to be retrieved. + - If set to C(application), then information are gathered related to all application images. + - If set to C(distribution), then information are gathered related to all distribution images. + - If set to C(private), then information are gathered related to all private images. + - If not set to any of above, then information are gathered related to all images. + default: 'all' + choices: [ 'all', 'application', 'distribution', 'private' ] + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all images + community.digitalocean.digital_ocean_image_info: + image_type: all + oauth_token: "{{ oauth_token }}" + +- name: Gather information about application images + community.digitalocean.digital_ocean_image_info: + image_type: application + oauth_token: "{{ oauth_token }}" + +- name: Gather information about distribution images + community.digitalocean.digital_ocean_image_info: + image_type: distribution + oauth_token: "{{ oauth_token }}" + +- name: Get distribution about image with slug coreos-beta + community.digitalocean.digital_ocean_image_info: + register: resp_out +- set_fact: + distribution_name: "{{ item.distribution }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?slug=='coreos-beta']" +- debug: + var: distribution_name + +''' + + +RETURN = r''' +data: + description: DigitalOcean image information + returned: success + type: list + sample: [ + { + "created_at": "2018-02-02T07:11:43Z", + "distribution": "CoreOS", + "id": 31434061, + "min_disk_size": 20, + "name": "1662.1.0 (beta)", + "public": true, + "regions": [ + "nyc1", + "sfo1", + "nyc2", + "ams2", + "sgp1", + "lon1", + "nyc3", + "ams3", + "fra1", + "tor1", + "sfo2", + "blr1" + ], + "size_gigabytes": 0.42, + "slug": "coreos-beta", + "type": "snapshot" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + image_type = module.params['image_type'] + + rest = DigitalOceanHelper(module) + + base_url = 'images?' + if image_type == 'distribution': + base_url += "type=distribution&" + elif image_type == 'application': + base_url += "type=application&" + elif image_type == 'private': + base_url += "private=true&" + + images = rest.get_paginated_data(base_url=base_url, data_key_name='images') + + module.exit_json(changed=False, data=images) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + image_type=dict(type='str', + required=False, + choices=['all', 'application', 'distribution', 'private'], + default='all' + ) + ) + + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_image_facts', 'community.digitalocean.digital_ocean_image_facts'): + module.deprecate("The 'digital_ocean_image_facts' module has been renamed to 'digital_ocean_image_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_facts.py new file mode 100644 index 00000000..00a50450 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_facts.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_load_balancer_info +short_description: Gather information about DigitalOcean load balancers +description: + - This module can be used to gather information about DigitalOcean provided load balancers. + - This module was called C(digital_ocean_load_balancer_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + load_balancer_id: + description: + - Load balancer ID that can be used to identify and reference a load_balancer. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all load balancers + community.digitalocean.digital_ocean_load_balancer_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about load balancer with given id + community.digitalocean.digital_ocean_load_balancer_info: + oauth_token: "{{ oauth_token }}" + load_balancer_id: "4de7ac8b-495b-4884-9a69-1050c6793cd6" + +- name: Get name from load balancer id + community.digitalocean.digital_ocean_load_balancer_info: + register: resp_out +- set_fact: + load_balancer_name: "{{ item.name }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?id=='4de7ac8b-495b-4884-9a69-1050c6793cd6']" +- debug: + var: load_balancer_name +''' + + +RETURN = r''' +data: + description: DigitalOcean Load balancer information + returned: success + type: list + sample: [ + { + "id": "4de7ac8b-495b-4884-9a69-1050c6793cd6", + "name": "example-lb-01", + "ip": "104.131.186.241", + "algorithm": "round_robin", + "status": "new", + "created_at": "2017-02-01T22:22:58Z", + ... + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + load_balancer_id = module.params.get('load_balancer_id', None) + rest = DigitalOceanHelper(module) + + base_url = 'load_balancers?' + if load_balancer_id is not None: + response = rest.get("%s/%s" % (base_url, load_balancer_id)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve load balancers for DigitalOcean") + + resp_json = response.json + load_balancer = resp_json['load_balancer'] + else: + load_balancer = rest.get_paginated_data(base_url=base_url, data_key_name='load_balancers') + + module.exit_json(changed=False, data=load_balancer) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + load_balancer_id=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_load_balancer_facts', 'community.digitalocean.digital_ocean_load_balancer_facts'): + module.deprecate("The 'digital_ocean_load_balancer_facts' module has been renamed to 'digital_ocean_load_balancer_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_info.py new file mode 100644 index 00000000..00a50450 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_load_balancer_info.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_load_balancer_info +short_description: Gather information about DigitalOcean load balancers +description: + - This module can be used to gather information about DigitalOcean provided load balancers. + - This module was called C(digital_ocean_load_balancer_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + load_balancer_id: + description: + - Load balancer ID that can be used to identify and reference a load_balancer. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all load balancers + community.digitalocean.digital_ocean_load_balancer_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about load balancer with given id + community.digitalocean.digital_ocean_load_balancer_info: + oauth_token: "{{ oauth_token }}" + load_balancer_id: "4de7ac8b-495b-4884-9a69-1050c6793cd6" + +- name: Get name from load balancer id + community.digitalocean.digital_ocean_load_balancer_info: + register: resp_out +- set_fact: + load_balancer_name: "{{ item.name }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?id=='4de7ac8b-495b-4884-9a69-1050c6793cd6']" +- debug: + var: load_balancer_name +''' + + +RETURN = r''' +data: + description: DigitalOcean Load balancer information + returned: success + type: list + sample: [ + { + "id": "4de7ac8b-495b-4884-9a69-1050c6793cd6", + "name": "example-lb-01", + "ip": "104.131.186.241", + "algorithm": "round_robin", + "status": "new", + "created_at": "2017-02-01T22:22:58Z", + ... + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + load_balancer_id = module.params.get('load_balancer_id', None) + rest = DigitalOceanHelper(module) + + base_url = 'load_balancers?' + if load_balancer_id is not None: + response = rest.get("%s/%s" % (base_url, load_balancer_id)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve load balancers for DigitalOcean") + + resp_json = response.json + load_balancer = resp_json['load_balancer'] + else: + load_balancer = rest.get_paginated_data(base_url=base_url, data_key_name='load_balancers') + + module.exit_json(changed=False, data=load_balancer) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + load_balancer_id=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_load_balancer_facts', 'community.digitalocean.digital_ocean_load_balancer_facts'): + module.deprecate("The 'digital_ocean_load_balancer_facts' module has been renamed to 'digital_ocean_load_balancer_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_facts.py new file mode 100644 index 00000000..497f83cb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_facts.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_region_info +short_description: Gather information about DigitalOcean regions +description: + - This module can be used to gather information about regions. + - This module was called C(digital_ocean_region_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Gather information about all regions + community.digitalocean.digital_ocean_region_info: + oauth_token: "{{ oauth_token }}" + +- name: Get Name of region where slug is known + community.digitalocean.digital_ocean_region_info: + oauth_token: "{{ oauth_token }}" + register: resp_out +- debug: var=resp_out +- set_fact: + region_slug: "{{ item.name }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?slug==`nyc1`]" +- debug: + var: region_slug +''' + + +RETURN = r''' +data: + description: DigitalOcean regions information + returned: success + type: list + sample: [ + { + "available": true, + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata", + "install_agent", + "storage" + ], + "name": "New York 1", + "sizes": [ + "512mb", + "s-1vcpu-1gb", + "1gb", + "s-3vcpu-1gb", + "s-1vcpu-2gb", + "s-2vcpu-2gb", + "2gb", + "s-1vcpu-3gb", + "s-2vcpu-4gb", + "4gb", + "c-2", + "m-1vcpu-8gb", + "8gb", + "s-4vcpu-8gb", + "s-6vcpu-16gb", + "16gb" + ], + "slug": "nyc1" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + base_url = 'regions?' + regions = rest.get_paginated_data(base_url=base_url, data_key_name='regions') + + module.exit_json(changed=False, data=regions) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_region_facts', 'community.digitalocean.digital_ocean_region_facts'): + module.deprecate("The 'digital_ocean_region_facts' module has been renamed to 'digital_ocean_region_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_info.py new file mode 100644 index 00000000..497f83cb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_region_info.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_region_info +short_description: Gather information about DigitalOcean regions +description: + - This module can be used to gather information about regions. + - This module was called C(digital_ocean_region_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Gather information about all regions + community.digitalocean.digital_ocean_region_info: + oauth_token: "{{ oauth_token }}" + +- name: Get Name of region where slug is known + community.digitalocean.digital_ocean_region_info: + oauth_token: "{{ oauth_token }}" + register: resp_out +- debug: var=resp_out +- set_fact: + region_slug: "{{ item.name }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?slug==`nyc1`]" +- debug: + var: region_slug +''' + + +RETURN = r''' +data: + description: DigitalOcean regions information + returned: success + type: list + sample: [ + { + "available": true, + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata", + "install_agent", + "storage" + ], + "name": "New York 1", + "sizes": [ + "512mb", + "s-1vcpu-1gb", + "1gb", + "s-3vcpu-1gb", + "s-1vcpu-2gb", + "s-2vcpu-2gb", + "2gb", + "s-1vcpu-3gb", + "s-2vcpu-4gb", + "4gb", + "c-2", + "m-1vcpu-8gb", + "8gb", + "s-4vcpu-8gb", + "s-6vcpu-16gb", + "16gb" + ], + "slug": "nyc1" + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + base_url = 'regions?' + regions = rest.get_paginated_data(base_url=base_url, data_key_name='regions') + + module.exit_json(changed=False, data=regions) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_region_facts', 'community.digitalocean.digital_ocean_region_facts'): + module.deprecate("The 'digital_ocean_region_facts' module has been renamed to 'digital_ocean_region_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_facts.py new file mode 100644 index 00000000..8f75954d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_facts.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_size_info +short_description: Gather information about DigitalOcean Droplet sizes +description: + - This module can be used to gather information about droplet sizes. + - This module was called C(digital_ocean_size_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all droplet sizes + community.digitalocean.digital_ocean_size_info: + oauth_token: "{{ oauth_token }}" + +- name: Get droplet Size Slug where vcpus is 1 + community.digitalocean.digital_ocean_size_info: + oauth_token: "{{ oauth_token }}" + register: resp_out +- debug: var=resp_out +- set_fact: + size_slug: "{{ item.slug }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?vcpus==`1`]" +- debug: + var: size_slug + + +''' + + +RETURN = r''' +data: + description: DigitalOcean droplet size information + returned: success + type: list + sample: [ + { + "available": true, + "disk": 20, + "memory": 512, + "price_hourly": 0.00744, + "price_monthly": 5.0, + "regions": [ + "ams2", + "ams3", + "blr1", + "fra1", + "lon1", + "nyc1", + "nyc2", + "nyc3", + "sfo1", + "sfo2", + "sgp1", + "tor1" + ], + "slug": "512mb", + "transfer": 1.0, + "vcpus": 1 + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get('sizes') + if response.status_code != 200: + module.fail_json(msg="Failed to fetch 'sizes' information due to error : %s" % response.json['message']) + + module.exit_json(changed=False, data=response.json['sizes']) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule( + argument_spec=argument_spec, + ) + if module._name in ('digital_ocean_size_facts', 'community.digitalocean.digital_ocean_size_facts'): + module.deprecate("The 'digital_ocean_size_facts' module has been renamed to 'digital_ocean_size_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_info.py new file mode 100644 index 00000000..8f75954d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_size_info.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_size_info +short_description: Gather information about DigitalOcean Droplet sizes +description: + - This module can be used to gather information about droplet sizes. + - This module was called C(digital_ocean_size_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all droplet sizes + community.digitalocean.digital_ocean_size_info: + oauth_token: "{{ oauth_token }}" + +- name: Get droplet Size Slug where vcpus is 1 + community.digitalocean.digital_ocean_size_info: + oauth_token: "{{ oauth_token }}" + register: resp_out +- debug: var=resp_out +- set_fact: + size_slug: "{{ item.slug }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?vcpus==`1`]" +- debug: + var: size_slug + + +''' + + +RETURN = r''' +data: + description: DigitalOcean droplet size information + returned: success + type: list + sample: [ + { + "available": true, + "disk": 20, + "memory": 512, + "price_hourly": 0.00744, + "price_monthly": 5.0, + "regions": [ + "ams2", + "ams3", + "blr1", + "fra1", + "lon1", + "nyc1", + "nyc2", + "nyc3", + "sfo1", + "sfo2", + "sgp1", + "tor1" + ], + "slug": "512mb", + "transfer": 1.0, + "vcpus": 1 + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get('sizes') + if response.status_code != 200: + module.fail_json(msg="Failed to fetch 'sizes' information due to error : %s" % response.json['message']) + + module.exit_json(changed=False, data=response.json['sizes']) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + module = AnsibleModule( + argument_spec=argument_spec, + ) + if module._name in ('digital_ocean_size_facts', 'community.digitalocean.digital_ocean_size_facts'): + module.deprecate("The 'digital_ocean_size_facts' module has been renamed to 'digital_ocean_size_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_facts.py new file mode 100644 index 00000000..b6de2367 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_facts.py @@ -0,0 +1,163 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_snapshot_info +short_description: Gather information about DigitalOcean Snapshot +description: + - This module can be used to gather information about snapshot information based upon provided values such as droplet, volume and snapshot id. + - This module was called C(digital_ocean_snapshot_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + snapshot_type: + description: + - Specifies the type of snapshot information to be retrieved. + - If set to C(droplet), then information are gathered related to snapshots based on Droplets only. + - If set to C(volume), then information are gathered related to snapshots based on volumes only. + - If set to C(by_id), then information are gathered related to snapshots based on snapshot id only. + - If not set to any of the above, then information are gathered related to all snapshots. + default: 'all' + choices: [ 'all', 'droplet', 'volume', 'by_id'] + required: false + type: str + snapshot_id: + description: + - To retrieve information about a snapshot, please specify this as a snapshot id. + - If set to actual snapshot id, then information are gathered related to that particular snapshot only. + - This is required parameter, if C(snapshot_type) is set to C(by_id). + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: all + oauth_token: "{{ oauth_token }}" + +- name: Gather information about droplet snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: droplet + oauth_token: "{{ oauth_token }}" + +- name: Gather information about volume snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: volume + oauth_token: "{{ oauth_token }}" + +- name: Gather information about snapshot by snapshot id + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: by_id + snapshot_id: 123123123 + oauth_token: "{{ oauth_token }}" + +- name: Get information about snapshot named big-data-snapshot1 + community.digitalocean.digital_ocean_snapshot_info: + register: resp_out +- set_fact: + snapshot_id: "{{ item.id }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='big-data-snapshot1']" +- debug: + var: snapshot_id + +''' + + +RETURN = r''' +data: + description: DigitalOcean snapshot information + returned: success + type: list + sample: [ + { + "id": "4f60fc64-85d1-11e6-a004-000f53315871", + "name": "big-data-snapshot1", + "regions": [ + "nyc1" + ], + "created_at": "2016-09-28T23:14:30Z", + "resource_id": "89bcc42f-85cf-11e6-a004-000f53315871", + "resource_type": "volume", + "min_disk_size": 10, + "size_gigabytes": 0 + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + snapshot_type = module.params['snapshot_type'] + + rest = DigitalOceanHelper(module) + + base_url = 'snapshots?' + snapshot = [] + + if snapshot_type == 'by_id': + base_url += "/{0}".format(module.params.get('snapshot_id')) + response = rest.get(base_url) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to fetch snapshot information due to error : %s" % response.json['message']) + + snapshot.extend(response.json["snapshot"]) + else: + if snapshot_type == 'droplet': + base_url += "resource_type=droplet&" + elif snapshot_type == 'volume': + base_url += "resource_type=volume&" + + snapshot = rest.get_paginated_data(base_url=base_url, data_key_name='snapshots') + module.exit_json(changed=False, data=snapshot) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + snapshot_type=dict(type='str', + required=False, + choices=['all', 'droplet', 'volume', 'by_id'], + default='all'), + snapshot_id=dict(type='str', + required=False), + ) + module = AnsibleModule( + argument_spec=argument_spec, + required_if=[ + ['snapshot_type', 'by_id', ['snapshot_id']], + ], + ) + if module._name in ('digital_ocean_snapshot_facts', 'community.digitalocean.digital_ocean_snapshot_facts'): + module.deprecate("The 'digital_ocean_snapshot_facts' module has been renamed to 'digital_ocean_snapshot_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_info.py new file mode 100644 index 00000000..b6de2367 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_snapshot_info.py @@ -0,0 +1,163 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_snapshot_info +short_description: Gather information about DigitalOcean Snapshot +description: + - This module can be used to gather information about snapshot information based upon provided values such as droplet, volume and snapshot id. + - This module was called C(digital_ocean_snapshot_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + snapshot_type: + description: + - Specifies the type of snapshot information to be retrieved. + - If set to C(droplet), then information are gathered related to snapshots based on Droplets only. + - If set to C(volume), then information are gathered related to snapshots based on volumes only. + - If set to C(by_id), then information are gathered related to snapshots based on snapshot id only. + - If not set to any of the above, then information are gathered related to all snapshots. + default: 'all' + choices: [ 'all', 'droplet', 'volume', 'by_id'] + required: false + type: str + snapshot_id: + description: + - To retrieve information about a snapshot, please specify this as a snapshot id. + - If set to actual snapshot id, then information are gathered related to that particular snapshot only. + - This is required parameter, if C(snapshot_type) is set to C(by_id). + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: all + oauth_token: "{{ oauth_token }}" + +- name: Gather information about droplet snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: droplet + oauth_token: "{{ oauth_token }}" + +- name: Gather information about volume snapshots + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: volume + oauth_token: "{{ oauth_token }}" + +- name: Gather information about snapshot by snapshot id + community.digitalocean.digital_ocean_snapshot_info: + snapshot_type: by_id + snapshot_id: 123123123 + oauth_token: "{{ oauth_token }}" + +- name: Get information about snapshot named big-data-snapshot1 + community.digitalocean.digital_ocean_snapshot_info: + register: resp_out +- set_fact: + snapshot_id: "{{ item.id }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='big-data-snapshot1']" +- debug: + var: snapshot_id + +''' + + +RETURN = r''' +data: + description: DigitalOcean snapshot information + returned: success + type: list + sample: [ + { + "id": "4f60fc64-85d1-11e6-a004-000f53315871", + "name": "big-data-snapshot1", + "regions": [ + "nyc1" + ], + "created_at": "2016-09-28T23:14:30Z", + "resource_id": "89bcc42f-85cf-11e6-a004-000f53315871", + "resource_type": "volume", + "min_disk_size": 10, + "size_gigabytes": 0 + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + snapshot_type = module.params['snapshot_type'] + + rest = DigitalOceanHelper(module) + + base_url = 'snapshots?' + snapshot = [] + + if snapshot_type == 'by_id': + base_url += "/{0}".format(module.params.get('snapshot_id')) + response = rest.get(base_url) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to fetch snapshot information due to error : %s" % response.json['message']) + + snapshot.extend(response.json["snapshot"]) + else: + if snapshot_type == 'droplet': + base_url += "resource_type=droplet&" + elif snapshot_type == 'volume': + base_url += "resource_type=volume&" + + snapshot = rest.get_paginated_data(base_url=base_url, data_key_name='snapshots') + module.exit_json(changed=False, data=snapshot) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + snapshot_type=dict(type='str', + required=False, + choices=['all', 'droplet', 'volume', 'by_id'], + default='all'), + snapshot_id=dict(type='str', + required=False), + ) + module = AnsibleModule( + argument_spec=argument_spec, + required_if=[ + ['snapshot_type', 'by_id', ['snapshot_id']], + ], + ) + if module._name in ('digital_ocean_snapshot_facts', 'community.digitalocean.digital_ocean_snapshot_facts'): + module.deprecate("The 'digital_ocean_snapshot_facts' module has been renamed to 'digital_ocean_snapshot_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey.py new file mode 100644 index 00000000..4313c5df --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey.py @@ -0,0 +1,257 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_sshkey +short_description: Manage DigitalOcean SSH keys +description: + - Create/delete DigitalOcean SSH keys. +author: "Patrick Marques (@pmarques)" +options: + state: + description: + - Indicate desired state of the target. + default: present + choices: ['present', 'absent'] + fingerprint: + description: + - This is a unique identifier for the SSH key used to delete a key + aliases: ['id'] + name: + description: + - The name for the SSH key + ssh_pub_key: + description: + - The Public SSH key to add. + oauth_token: + description: + - DigitalOcean OAuth token. + required: true +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: "Create ssh key" + community.digitalocean.digital_ocean_sshkey: + oauth_token: "{{ oauth_token }}" + name: "My SSH Public Key" + ssh_pub_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example" + state: present + register: result + +- name: "Delete ssh key" + community.digitalocean.digital_ocean_sshkey: + oauth_token: "{{ oauth_token }}" + state: "absent" + fingerprint: "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa" +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#list-all-keys +data: + description: This is only present when C(state=present) + returned: when C(state=present) + type: dict + sample: { + "ssh_key": { + "id": 512189, + "fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa", + "name": "My SSH Public Key", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example" + } + } +''' + +import json +import hashlib +import base64 + +from ansible.module_utils.basic import env_fallback +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.urls import fetch_url + + +class Response(object): + + def __init__(self, resp, info): + self.body = None + if resp: + self.body = resp.read() + self.info = info + + @property + def json(self): + if not self.body: + if "body" in self.info: + return json.loads(self.info["body"]) + return None + try: + return json.loads(self.body) + except ValueError: + return None + + @property + def status_code(self): + return self.info["status"] + + +class Rest(object): + + def __init__(self, module, headers): + self.module = module + self.headers = headers + self.baseurl = 'https://api.digitalocean.com/v2' + + def _url_builder(self, path): + if path[0] == '/': + path = path[1:] + return '%s/%s' % (self.baseurl, path) + + def send(self, method, path, data=None, headers=None): + url = self._url_builder(path) + data = self.module.jsonify(data) + timeout = self.module.params['timeout'] + + resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method, timeout=timeout) + + # Exceptions in fetch_url may result in a status -1, the ensures a + if info['status'] == -1: + self.module.fail_json(msg=info['msg']) + + return Response(resp, info) + + def get(self, path, data=None, headers=None): + return self.send('GET', path, data, headers) + + def put(self, path, data=None, headers=None): + return self.send('PUT', path, data, headers) + + def post(self, path, data=None, headers=None): + return self.send('POST', path, data, headers) + + def delete(self, path, data=None, headers=None): + return self.send('DELETE', path, data, headers) + + +def core(module): + api_token = module.params['oauth_token'] + state = module.params['state'] + fingerprint = module.params['fingerprint'] + name = module.params['name'] + ssh_pub_key = module.params['ssh_pub_key'] + + rest = Rest(module, {'Authorization': 'Bearer {0}'.format(api_token), + 'Content-type': 'application/json'}) + + fingerprint = fingerprint or ssh_key_fingerprint(ssh_pub_key) + response = rest.get('account/keys/{0}'.format(fingerprint)) + status_code = response.status_code + json = response.json + + if status_code not in (200, 404): + module.fail_json(msg='Error getting ssh key [{0}: {1}]'.format( + status_code, response.json['message']), fingerprint=fingerprint) + + if state in ('present'): + if status_code == 404: + # IF key not found create it! + + if module.check_mode: + module.exit_json(changed=True) + + payload = { + 'name': name, + 'public_key': ssh_pub_key + } + response = rest.post('account/keys', data=payload) + status_code = response.status_code + json = response.json + if status_code == 201: + module.exit_json(changed=True, data=json) + + module.fail_json(msg='Error creating ssh key [{0}: {1}]'.format( + status_code, response.json['message'])) + + elif status_code == 200: + # If key found was found, check if name needs to be updated + if name is None or json['ssh_key']['name'] == name: + module.exit_json(changed=False, data=json) + + if module.check_mode: + module.exit_json(changed=True) + + payload = { + 'name': name, + } + response = rest.put('account/keys/{0}'.format(fingerprint), data=payload) + status_code = response.status_code + json = response.json + if status_code == 200: + module.exit_json(changed=True, data=json) + + module.fail_json(msg='Error updating ssh key name [{0}: {1}]'.format( + status_code, response.json['message']), fingerprint=fingerprint) + + elif state in ('absent'): + if status_code == 404: + module.exit_json(changed=False) + + if module.check_mode: + module.exit_json(changed=True) + + response = rest.delete('account/keys/{0}'.format(fingerprint)) + status_code = response.status_code + json = response.json + if status_code == 204: + module.exit_json(changed=True) + + module.fail_json(msg='Error creating ssh key [{0}: {1}]'.format( + status_code, response.json['message'])) + + +def ssh_key_fingerprint(ssh_pub_key): + key = ssh_pub_key.split(None, 2)[1] + fingerprint = hashlib.md5(base64.b64decode(key)).hexdigest() + return ':'.join(a + b for a, b in zip(fingerprint[::2], fingerprint[1::2])) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + state=dict(choices=['present', 'absent'], default='present'), + fingerprint=dict(aliases=['id'], required=False), + name=dict(required=False), + ssh_pub_key=dict(required=False), + oauth_token=dict( + no_log=True, + # Support environment variable for DigitalOcean OAuth Token + fallback=(env_fallback, ['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN']), + required=True, + ), + validate_certs=dict(type='bool', default=True), + timeout=dict(type='int', default=30), + ), + required_one_of=( + ('fingerprint', 'ssh_pub_key'), + ), + supports_check_mode=True, + ) + + core(module) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_facts.py new file mode 100644 index 00000000..71daaaf8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_facts.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_sshkey_facts +deprecated: + removed_in: 2.0.0 # was Ansible 2.13 + why: Deprecated in favour of C(_info) module. + alternative: Use M(community.digitalocean.digital_ocean_sshkey_info) instead. +short_description: DigitalOcean SSH keys facts +description: + - Fetch DigitalOcean SSH keys facts. +author: "Patrick Marques (@pmarques)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- community.digitalocean.digital_ocean_sshkey_facts: + oauth_token: "{{ my_do_key }}" + +- set_fact: + pubkey: "{{ item.public_key }}" + loop: "{{ ssh_keys | community.general.json_query(ssh_pubkey) }}" + vars: + ssh_pubkey: "[?name=='ansible_ctrl']" + +- debug: + msg: "{{ pubkey }}" +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#list-all-keys +data: + description: List of SSH keys on DigitalOcean + returned: success and no resource constraint + type: dict + sample: { + "ssh_keys": [ + { + "id": 512189, + "fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example", + "name": "My SSH Public Key" + } + ], + "links": { + }, + "meta": { + "total": 1 + } + } +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get("account/keys") + status_code = response.status_code + json = response.json + if status_code == 200: + module.exit_json(changed=False, ansible_facts=json) + else: + module.fail_json(msg='Error fetching facts [{0}: {1}]'.format( + status_code, response.json['message'])) + + +def main(): + module = AnsibleModule( + argument_spec=DigitalOceanHelper.digital_ocean_argument_spec(), + supports_check_mode=False, + ) + + module.deprecate("The 'digital_ocean_sshkey_facts' module has been deprecated, use the new 'digital_ocean_sshkey_info' module", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + core(module) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_info.py new file mode 100644 index 00000000..1467545b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_sshkey_info.py @@ -0,0 +1,92 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_sshkey_info +short_description: Gather information about DigitalOcean SSH keys +description: + - This module can be used to gather information about DigitalOcean SSH keys. + - This module replaces the C(digital_ocean_sshkey_facts) module. +author: "Patrick Marques (@pmarques)" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Version 2 of DigitalOcean API is used. +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Gather information about DigitalOcean SSH keys + community.digitalocean.digital_ocean_sshkey_info: + oauth_token: "{{ my_do_key }}" + register: ssh_keys + +- name: Set facts based on the gathered information + set_fact: + pubkey: "{{ item.public_key }}" + loop: "{{ ssh_keys.data | community.general.json_query(ssh_pubkey) }}" + vars: + ssh_pubkey: "[?name=='ansible_ctrl']" + +- name: Print SSH public key + debug: + msg: "{{ pubkey }}" +''' + + +RETURN = r''' +# Digital Ocean API info https://developers.digitalocean.com/documentation/v2/#list-all-keys +data: + description: List of SSH keys on DigitalOcean + returned: success and no resource constraint + type: dict + sample: [ + { + "id": 512189, + "fingerprint": "3b:16:bf:e4:8b:00:8b:b8:59:8c:a9:d3:f0:19:45:fa", + "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDDHr/jh2Jy4yALcK4JyWbVkPRaWmhck3IgCoeOO3z1e2dBowLh64QAM+Qb72pxekALga2oi4GvT+TlWNhzPH4V example", + "name": "My SSH Public Key" + } + ] +''' + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper + + +def core(module): + rest = DigitalOceanHelper(module) + + response = rest.get("account/keys") + status_code = response.status_code + json = response.json + if status_code == 200: + module.exit_json(changed=False, data=json['ssh_keys']) + else: + module.fail_json(msg='Error fetching SSH Key information [{0}: {1}]'.format( + status_code, response.json['message'])) + + +def main(): + module = AnsibleModule( + argument_spec=DigitalOceanHelper.digital_ocean_argument_spec(), + supports_check_mode=True, + ) + + core(module) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag.py new file mode 100644 index 00000000..67c5c2c8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag.py @@ -0,0 +1,209 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: Ansible Project +# 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 = r''' +--- +module: digital_ocean_tag +short_description: Create and remove tag(s) to DigitalOcean resource. +description: + - Create and remove tag(s) to DigitalOcean resource. +author: "Victor Volle (@kontrafiktion)" +options: + name: + description: + - The name of the tag. The supported characters for names include + alphanumeric characters, dashes, and underscores. + required: true + type: str + resource_id: + description: + - The ID of the resource to operate on. + - The data type of resource_id is changed from integer to string since Ansible 2.5. + aliases: ['droplet_id'] + type: str + resource_type: + description: + - The type of resource to operate on. Currently, only tagging of + droplets is supported. + default: droplet + choices: ['droplet'] + type: str + state: + description: + - Whether the tag should be present or absent on the resource. + default: present + type: str + choices: ['present', 'absent'] +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +notes: + - Two environment variables can be used, DO_API_KEY and DO_API_TOKEN. + They both refer to the v2 token. + - As of Ansible 2.0, Version 2 of the DigitalOcean API is used. + +requirements: + - "python >= 2.6" +''' + + +EXAMPLES = r''' +- name: Create a tag + community.digitalocean.digital_ocean_tag: + name: production + state: present + +- name: Tag a resource; creating the tag if it does not exist + community.digitalocean.digital_ocean_tag: + name: "{{ item }}" + resource_id: "73333005" + state: present + loop: + - staging + - dbserver + +- name: Untag a resource + community.digitalocean.digital_ocean_tag: + name: staging + resource_id: "73333005" + state: absent + +# Deleting a tag also untags all the resources that have previously been +# tagged with it +- name: Remove a tag + community.digitalocean.digital_ocean_tag: + name: dbserver + state: absent +''' + + +RETURN = r''' +data: + description: a DigitalOcean Tag resource + returned: success and no resource constraint + type: dict + sample: { + "tag": { + "name": "awesome", + "resources": { + "droplets": { + "count": 0, + "last_tagged": null + } + } + } + } +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + state = module.params['state'] + name = module.params['name'] + resource_id = module.params['resource_id'] + resource_type = module.params['resource_type'] + + rest = DigitalOceanHelper(module) + + if state == 'present': + response = rest.get('tags/{0}'.format(name)) + status_code = response.status_code + resp_json = response.json + changed = False + if status_code == 200 and resp_json['tag']['name'] == name: + changed = False + else: + # Ensure Tag exists + response = rest.post("tags", data={'name': name}) + status_code = response.status_code + resp_json = response.json + if status_code == 201: + changed = True + elif status_code == 422: + changed = False + else: + module.exit_json(changed=False, data=resp_json) + + if resource_id is None: + # No resource defined, we're done. + module.exit_json(changed=changed, data=resp_json) + else: + # Check if resource is already tagged or not + found = False + url = "{0}?tag_name={1}".format(resource_type, name) + if resource_type == 'droplet': + url = "droplets?tag_name={0}".format(name) + response = rest.get(url) + status_code = response.status_code + resp_json = response.json + if status_code == 200: + for resource in resp_json['droplets']: + if not found and resource['id'] == int(resource_id): + found = True + break + if not found: + # If resource is not tagged, tag a resource + url = "tags/{0}/resources".format(name) + payload = { + 'resources': [{ + 'resource_id': resource_id, + 'resource_type': resource_type}]} + response = rest.post(url, data=payload) + if response.status_code == 204: + module.exit_json(changed=True) + else: + module.fail_json(msg="error tagging resource '{0}': {1}".format(resource_id, response.json["message"])) + else: + # Already tagged resource + module.exit_json(changed=False) + else: + # Unable to find resource specified by user + module.fail_json(msg=resp_json['message']) + + elif state == 'absent': + if resource_id: + url = "tags/{0}/resources".format(name) + payload = { + 'resources': [{ + 'resource_id': resource_id, + 'resource_type': resource_type}]} + response = rest.delete(url, data=payload) + else: + url = "tags/{0}".format(name) + response = rest.delete(url) + if response.status_code == 204: + module.exit_json(changed=True) + else: + module.exit_json(changed=False, data=response.json) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + name=dict(type='str', required=True), + resource_id=dict(aliases=['droplet_id'], type='str'), + resource_type=dict(choices=['droplet'], default='droplet'), + state=dict(choices=['present', 'absent'], default='present'), + ) + + module = AnsibleModule(argument_spec=argument_spec) + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_facts.py new file mode 100644 index 00000000..41f57011 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_facts.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_tag_info +short_description: Gather information about DigitalOcean tags +description: + - This module can be used to gather information about DigitalOcean provided tags. + - This module was called C(digital_ocean_tag_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + tag_name: + description: + - Tag name that can be used to identify and reference a tag. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all tags + community.digitalocean.digital_ocean_tag_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about tag with given name + community.digitalocean.digital_ocean_tag_info: + oauth_token: "{{ oauth_token }}" + tag_name: "extra_awesome_tag" + +- name: Get resources from tag name + community.digitalocean.digital_ocean_tag_info: + register: resp_out +- set_fact: + resources: "{{ item.resources }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='extra_awesome_tag']" +- debug: + var: resources +''' + + +RETURN = r''' +data: + description: DigitalOcean tag information + returned: success + type: list + sample: [ + { + "name": "extra-awesome", + "resources": { + "droplets": { + "count": 1, + ... + } + } + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + tag_name = module.params.get('tag_name', None) + rest = DigitalOceanHelper(module) + + base_url = 'tags' + if tag_name is not None: + response = rest.get("%s/%s" % (base_url, tag_name)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve tags for DigitalOcean") + + resp_json = response.json + tag = resp_json['tag'] + else: + tag = rest.get_paginated_data(base_url=base_url + '?', data_key_name='tags') + + module.exit_json(changed=False, data=tag) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + tag_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_tag_facts', 'community.digitalocean.digital_ocean_tag_facts'): + module.deprecate("The 'digital_ocean_tag_facts' module has been renamed to 'digital_ocean_tag_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_info.py new file mode 100644 index 00000000..41f57011 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_tag_info.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_tag_info +short_description: Gather information about DigitalOcean tags +description: + - This module can be used to gather information about DigitalOcean provided tags. + - This module was called C(digital_ocean_tag_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + tag_name: + description: + - Tag name that can be used to identify and reference a tag. + required: false + type: str +requirements: + - "python >= 2.6" +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all tags + community.digitalocean.digital_ocean_tag_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about tag with given name + community.digitalocean.digital_ocean_tag_info: + oauth_token: "{{ oauth_token }}" + tag_name: "extra_awesome_tag" + +- name: Get resources from tag name + community.digitalocean.digital_ocean_tag_info: + register: resp_out +- set_fact: + resources: "{{ item.resources }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='extra_awesome_tag']" +- debug: + var: resources +''' + + +RETURN = r''' +data: + description: DigitalOcean tag information + returned: success + type: list + sample: [ + { + "name": "extra-awesome", + "resources": { + "droplets": { + "count": 1, + ... + } + } + }, + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + tag_name = module.params.get('tag_name', None) + rest = DigitalOceanHelper(module) + + base_url = 'tags' + if tag_name is not None: + response = rest.get("%s/%s" % (base_url, tag_name)) + status_code = response.status_code + + if status_code != 200: + module.fail_json(msg="Failed to retrieve tags for DigitalOcean") + + resp_json = response.json + tag = resp_json['tag'] + else: + tag = rest.get_paginated_data(base_url=base_url + '?', data_key_name='tags') + + module.exit_json(changed=False, data=tag) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + tag_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_tag_facts', 'community.digitalocean.digital_ocean_tag_facts'): + module.deprecate("The 'digital_ocean_tag_facts' module has been renamed to 'digital_ocean_tag_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_facts.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_facts.py new file mode 100644 index 00000000..18bd5f3e --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_facts.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_volume_info +short_description: Gather information about DigitalOcean volumes +description: + - This module can be used to gather information about DigitalOcean provided volumes. + - This module was called C(digital_ocean_volume_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + region_name: + description: + - Name of region to restrict results to volumes available in a specific region. + - Please use M(community.digitalocean.digital_ocean_region_info) for getting valid values related regions. + required: false + type: str +requirements: + - "python >= 2.6" + +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all volume + community.digitalocean.digital_ocean_volume_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about volume in given region + community.digitalocean.digital_ocean_volume_info: + region_name: nyc1 + oauth_token: "{{ oauth_token }}" + +- name: Get information about volume named nyc3-test-volume + community.digitalocean.digital_ocean_volume_info: + register: resp_out +- set_fact: + volume_id: "{{ item.id }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='nyc3-test-volume']" +- debug: var=volume_id +''' + + +RETURN = r''' +data: + description: DigitalOcean volume information + returned: success + type: list + sample: [ + { + "id": "506f78a4-e098-11e5-ad9f-000f53306ae1", + "region": { + "name": "New York 1", + "slug": "nyc1", + "sizes": [ + "s-1vcpu-1gb", + "s-1vcpu-2gb", + "s-1vcpu-3gb", + "s-2vcpu-2gb", + "s-3vcpu-1gb", + "s-2vcpu-4gb", + "s-4vcpu-8gb", + "s-6vcpu-16gb", + "s-8vcpu-32gb", + "s-12vcpu-48gb", + "s-16vcpu-64gb", + "s-20vcpu-96gb", + "s-24vcpu-128gb", + "s-32vcpu-192gb" + ], + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata" + ], + "available": true + }, + "droplet_ids": [ + + ], + "name": "example", + "description": "Block store for examples", + "size_gigabytes": 10, + "created_at": "2016-03-02T17:00:49Z" + } + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + region_name = module.params.get('region_name', None) + + rest = DigitalOceanHelper(module) + + base_url = 'volumes?' + if region_name is not None: + base_url += "region=%s&" % region_name + + volumes = rest.get_paginated_data(base_url=base_url, data_key_name='volumes') + + module.exit_json(changed=False, data=volumes) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + region_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_volume_facts', 'community.digitalocean.digital_ocean_volume_facts'): + module.deprecate("The 'digital_ocean_volume_facts' module has been renamed to 'digital_ocean_volume_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_info.py b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_info.py new file mode 100644 index 00000000..18bd5f3e --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/digitalocean/plugins/modules/digital_ocean_volume_info.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright: (c) 2018, Ansible Project +# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> +# 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 = r''' +--- +module: digital_ocean_volume_info +short_description: Gather information about DigitalOcean volumes +description: + - This module can be used to gather information about DigitalOcean provided volumes. + - This module was called C(digital_ocean_volume_facts) before Ansible 2.9. The usage did not change. +author: "Abhijeet Kasurde (@Akasurde)" +options: + region_name: + description: + - Name of region to restrict results to volumes available in a specific region. + - Please use M(community.digitalocean.digital_ocean_region_info) for getting valid values related regions. + required: false + type: str +requirements: + - "python >= 2.6" + +extends_documentation_fragment: +- community.digitalocean.digital_ocean.documentation + +''' + + +EXAMPLES = r''' +- name: Gather information about all volume + community.digitalocean.digital_ocean_volume_info: + oauth_token: "{{ oauth_token }}" + +- name: Gather information about volume in given region + community.digitalocean.digital_ocean_volume_info: + region_name: nyc1 + oauth_token: "{{ oauth_token }}" + +- name: Get information about volume named nyc3-test-volume + community.digitalocean.digital_ocean_volume_info: + register: resp_out +- set_fact: + volume_id: "{{ item.id }}" + loop: "{{ resp_out.data | community.general.json_query(name) }}" + vars: + name: "[?name=='nyc3-test-volume']" +- debug: var=volume_id +''' + + +RETURN = r''' +data: + description: DigitalOcean volume information + returned: success + type: list + sample: [ + { + "id": "506f78a4-e098-11e5-ad9f-000f53306ae1", + "region": { + "name": "New York 1", + "slug": "nyc1", + "sizes": [ + "s-1vcpu-1gb", + "s-1vcpu-2gb", + "s-1vcpu-3gb", + "s-2vcpu-2gb", + "s-3vcpu-1gb", + "s-2vcpu-4gb", + "s-4vcpu-8gb", + "s-6vcpu-16gb", + "s-8vcpu-32gb", + "s-12vcpu-48gb", + "s-16vcpu-64gb", + "s-20vcpu-96gb", + "s-24vcpu-128gb", + "s-32vcpu-192gb" + ], + "features": [ + "private_networking", + "backups", + "ipv6", + "metadata" + ], + "available": true + }, + "droplet_ids": [ + + ], + "name": "example", + "description": "Block store for examples", + "size_gigabytes": 10, + "created_at": "2016-03-02T17:00:49Z" + } + ] +''' + +from traceback import format_exc +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.digitalocean.plugins.module_utils.digital_ocean import DigitalOceanHelper +from ansible.module_utils._text import to_native + + +def core(module): + region_name = module.params.get('region_name', None) + + rest = DigitalOceanHelper(module) + + base_url = 'volumes?' + if region_name is not None: + base_url += "region=%s&" % region_name + + volumes = rest.get_paginated_data(base_url=base_url, data_key_name='volumes') + + module.exit_json(changed=False, data=volumes) + + +def main(): + argument_spec = DigitalOceanHelper.digital_ocean_argument_spec() + argument_spec.update( + region_name=dict(type='str', required=False), + ) + module = AnsibleModule(argument_spec=argument_spec) + if module._name in ('digital_ocean_volume_facts', 'community.digitalocean.digital_ocean_volume_facts'): + module.deprecate("The 'digital_ocean_volume_facts' module has been renamed to 'digital_ocean_volume_info'", + version='2.0.0', collection_name='community.digitalocean') # was Ansible 2.13 + + try: + core(module) + except Exception as e: + module.fail_json(msg=to_native(e), exception=format_exc()) + + +if __name__ == '__main__': + main() |