Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor DigitalOcean modules #35934

Merged
merged 1 commit into from
Feb 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 21 additions & 10 deletions lib/ansible/module_utils/digital_ocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import os
from ansible.module_utils.urls import fetch_url
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback


class Response(object):
Expand Down Expand Up @@ -62,10 +63,16 @@ def __init__(self, module):
self.module = module
self.baseurl = 'https://api.digitalocean.com/v2'
self.oauth_token = None
self.get_do_oauth_token()
self.headers = {'Authorization': 'Bearer {0}'.format(self.oauth_token),
'Content-type': 'application/json'}

# Check if api_token is valid or not
response = self.get('account')
if response.status_code == 401:
module.fail_json(msg='Failed to login using API token, please verify validity of API token.')

self.timeout = module.params.get('timeout', 30)

def _url_builder(self, path):
if path[0] == '/':
path = path[1:]
Expand All @@ -75,7 +82,7 @@ def send(self, method, path, data=None):
url = self._url_builder(path)
data = self.module.jsonify(data)

resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method)
resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method, timeout=self.timeout)

return Response(resp, info)

Expand All @@ -91,11 +98,15 @@ def post(self, path, data=None):
def delete(self, path, data=None):
return self.send('DELETE', path, data)

def get_do_oauth_token(self):
self.oauth_token = self.module.params.get('oauth_token') or \
self.module.params.get('api_token') or \
os.environ.get('DO_API_TOKEN') or \
os.environ.get('DO_API_KEY') or \
os.environ.get('OAUTH_TOKEN')
if self.oauth_token is None:
self.module.fail_json(msg='Unable to load api key: oauth_token')
@staticmethod
def digital_ocean_argument_spec():
return dict(
validate_certs=dict(type='bool', required=False, default=True),
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', 'OAUTH_TOKEN']),
required=False,
),
timeout=dict(type='int', default=30),
)
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@
- Indicate desired state of the target.
choices: ['present', 'absent']
required: true
api_token:
description:
- DigitalOcean api token.
required: true
block_size:
description:
- The size of the Block Storage volume in gigabytes. Required when command=create and state=present. If snapshot_id is included, this will be ignored.
Expand All @@ -56,11 +52,7 @@
droplet_id:
description:
- The droplet id you want to operate on. Required when command=attach.
timeout:
description:
- The timeout in seconds used for polling DigitalOcean's API.
default: 10

extends_documentation_fragment: digital_ocean.documentation
notes:
- Two environment variables can be used, DO_API_KEY and DO_API_TOKEN.
They both refer to the v2 token.
Expand Down Expand Up @@ -267,26 +259,28 @@ def handle_request(module):


def main():
module = AnsibleModule(
argument_spec=dict(
state=dict(choices=['present', 'absent'], required=True),
command=dict(choices=['create', 'attach'], required=True),
api_token=dict(aliases=['API_TOKEN'], no_log=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'),
timeout=dict(type='int', default=10),
),
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'),
timeout=dict(type='int', default=10)
)

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()
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,7 @@
- Whether the certificate should be present or absent.
default: present
choices: ['present', 'absent']
oauth_token:
description:
- DigitalOcean OAuth token.
required: true
aliases: ['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN']

extends_documentation_fragment: 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.
Expand Down Expand Up @@ -101,11 +96,6 @@ def core(module):

results = dict(changed=False)

# Check if oauth_token is valid or not
response = rest.get('account')
if response.status_code == 401:
module.fail_json(msg='Failed to login using oauth_token, please verify validity of oauth_token')

response = rest.get('certificates')
status_code = response.status_code
resp_json = response.json
Expand Down Expand Up @@ -157,15 +147,17 @@ def core(module):


def main():
argument_spec = DigitalOceanHelper.digital_ocean_argument_spec()
argument_spec.update(
name=dict(type='str'),
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=dict(
name=dict(type='str'),
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'),
oauth_token=dict(aliases=['DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN'], no_log=True),
),
argument_spec=argument_spec,
required_if=[('state', 'present', ['name', 'leaf_certificate', 'private_key']),
('state', 'absent', ['name'])
],
Expand All @@ -176,5 +168,6 @@ def main():
except Exception as e:
module.fail_json(msg=to_native(e))


if __name__ == '__main__':
main()
28 changes: 10 additions & 18 deletions lib/ansible/modules/cloud/digital_ocean/digital_ocean_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@
- Indicate desired state of the target.
default: present
choices: ['present', 'absent']
oauth_token:
description:
- DigitalOcean api token.
version_added: "1.9.5"
aliases: ['API_TOKEN']
id:
description:
- Numeric, the droplet id you want to operate on.
Expand All @@ -42,7 +37,7 @@
ip:
description:
- The IP address to point a domain at.

extends_documentation_fragment: 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).
Expand Down Expand Up @@ -84,7 +79,6 @@
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.digital_ocean import DigitalOceanHelper
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import env_fallback


class DoManager(DigitalOceanHelper, object):
Expand Down Expand Up @@ -185,18 +179,16 @@ def core(module):


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=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'),
id=dict(aliases=['droplet_id'], type='int'),
ip=dict(type='str'),
),
argument_spec=argument_spec,
required_one_of=(
['id', 'name'],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,27 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: Ansible Project
# 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


ANSIBLE_METADATA = {'status': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'}
ANSIBLE_METADATA = {
'status': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'
}

DOCUMENTATION = '''
---
module: digital_ocean_floating_ip_facts
short_description: DigitalOcean Floating IPs facts
description:
- Fetch DigitalOcean Floating IPs facts.
- This module can be used to fetch DigitalOcean Floating IPs facts.
version_added: "2.5"
author: "Patrick Marques (@pmarques)"
options:
oauth_token:
description:
- DigitalOcean OAuth token.
required: true
timeout:
description:
- The timeout in seconds used for polling DigitalOcean's API.
default: 30

extends_documentation_fragment: digital_ocean.documentation
notes:
- Version 2 of DigitalOcean API is used.
requirements:
Expand Down Expand Up @@ -84,12 +76,9 @@
]
'''

import json
import os

from ansible.module_utils.basic import env_fallback
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.digital_ocean import DigitalOceanHelper
from ansible.module_utils._text import to_native


def core(module):
Expand All @@ -98,41 +87,34 @@ def core(module):
page = 1
has_next = True
floating_ips = []
while has_next or 200 != status_code:
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 200 != status_code:
if status_code != 200:
break
page = page + 1
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 fecthing facts [{0}: {1}]".format(
module.fail_json(msg="Error fetching facts [{0}: {1}]".format(
status_code, response.json["message"]))


def main():
module = AnsibleModule(
argument_spec=dict(
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),
),
argument_spec=DigitalOceanHelper.digital_ocean_argument_spec()
)

try:
core(module)
except Exception as e:
module.fail_json(msg=str(e))
module.fail_json(msg=to_native(e))


if __name__ == '__main__':
main()