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 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 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 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 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 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 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 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 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 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"]))
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')
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 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)