From 69911ec86e2702fb37fd28664e72c789b17354de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20=C3=85ke=20Fransson?= Date: Wed, 25 Mar 2015 16:43:11 +0100 Subject: [PATCH 1/3] WIP: DigitalOcean API version 2 with user_data option --- cloud/digital_ocean/digital_ocean.py | 61 ++++++++++++++++------------ 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/cloud/digital_ocean/digital_ocean.py b/cloud/digital_ocean/digital_ocean.py index f3a904e8b24..044b6f39774 100644 --- a/cloud/digital_ocean/digital_ocean.py +++ b/cloud/digital_ocean/digital_ocean.py @@ -53,16 +53,16 @@ options: choices: [ "yes", "no" ] size_id: description: - - Numeric, this is the id of the size you would like the droplet created with. + - This is the slug of the size you would like the droplet created with. image_id: description: - - Numeric, this is the id of the image you would like the droplet created with. + - This is the slug of the image you would like the droplet created with. region_id: description: - - "Numeric, this is the id of the region you would like your server to be created in." + - This is the slug of the region you would like your server to be created in. ssh_key_ids: description: - - Optional, comma separated list of ssh_key_ids that you would like to be added to the server. + - Optional, array of of ssh_key_ids 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." @@ -81,6 +81,12 @@ options: version_added: "1.6" default: "no" choices: [ "yes", "no" ] + user_data: + description: + - opaque blob of data which is made available to the droplet + version_added: "1.10" + required: false + default: None wait: description: - Wait for the droplet to be in state 'running' before returning. If wait is "no" an ip_address may not be returned. @@ -120,11 +126,10 @@ EXAMPLES = ''' state=present command=droplet name=mydroplet - client_id=XXX api_key=XXX - size_id=1 - region_id=2 - image_id=3 + 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 }}" @@ -141,9 +146,9 @@ EXAMPLES = ''' name=mydroplet client_id=XXX api_key=XXX - size_id=1 - region_id=2 - image_id=3 + size_id=2gb + region_id=ams2 + image_id=fedora-19-x64 wait_timeout=500 # Create a droplet with ssh key @@ -153,13 +158,13 @@ EXAMPLES = ''' - digital_ocean: > state=present - ssh_key_ids=id1,id2 + ssh_key_ids=[id1,id2] name=mydroplet client_id=XXX api_key=XXX - size_id=1 - region_id=2 - image_id=3 + size_id=2gb + region_id=ams2 + image_id=fedora-19-x64 ''' import sys @@ -170,11 +175,11 @@ try: import dopy from dopy.manager import DoError, DoManager except ImportError, e: - print "failed=True msg='dopy >= 0.2.3 required for this module'" + print "failed=True msg='dopy >= 0.3.2 required for this module'" sys.exit(1) -if dopy.__version__ < '0.2.3': - print "failed=True msg='dopy >= 0.2.3 required for this module'" +if dopy.__version__ < '0.3.2': + print "failed=True msg='dopy >= 0.3.2 required for this module'" sys.exit(1) class TimeoutError(DoError): @@ -232,13 +237,13 @@ class Droplet(JsonfyMixIn): @classmethod def setup(cls, client_id, api_key): - cls.manager = DoManager(client_id, api_key) + cls.manager = DoManager(client_id, api_key, 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): + 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): private_networking_lower = str(private_networking).lower() backups_enabled_lower = str(backups_enabled).lower() - json = cls.manager.new_droplet(name, size_id, image_id, region_id, ssh_key_ids, virtio, private_networking_lower, backups_enabled_lower) + json = cls.manager.new_droplet(name, size_id, image_id, region_id, ssh_key_ids, virtio, private_networking_lower, backups_enabled_lower,user_data) droplet = cls(json) return droplet @@ -310,14 +315,14 @@ def core(module): try: # params['client_id'] will be None even if client_id is not passed in - client_id = module.params['client_id'] or os.environ['DO_CLIENT_ID'] - api_key = module.params['api_key'] or os.environ['DO_API_KEY'] + api_key = module.params['api_key'] or os.environ['DO_API_TOKEN'] or os.environ['DO_API_KEY'] except KeyError, e: module.fail_json(msg='Unable to load %s' % e.message) changed = True command = module.params['command'] state = module.params['state'] + client_id = 'notused' if command == 'droplet': Droplet.setup(client_id, api_key) @@ -343,6 +348,7 @@ def core(module): virtio=module.params['virtio'], private_networking=module.params['private_networking'], backups_enabled=module.params['backups_enabled'], + user_data=module.params.get('user_data'), ) if droplet.is_powered_on(): @@ -369,7 +375,7 @@ def core(module): module.exit_json(changed=False, msg='The droplet is not found.') event_json = droplet.destroy() - module.exit_json(changed=True, event_id=event_json['event_id']) + module.exit_json(changed=True) elif command == 'ssh': SSH.setup(client_id, api_key) @@ -397,15 +403,16 @@ def main(): client_id = dict(aliases=['CLIENT_ID'], no_log=True), api_key = dict(aliases=['API_KEY'], no_log=True), name = dict(type='str'), - size_id = dict(type='int'), - image_id = dict(type='int'), - region_id = dict(type='int'), + size_id = dict(), + image_id = dict(), + region_id = dict(), ssh_key_ids = dict(default=''), virtio = dict(type='bool', default='yes'), private_networking = dict(type='bool', default='no'), backups_enabled = dict(type='bool', default='no'), id = dict(aliases=['droplet_id'], type='int'), unique_name = dict(type='bool', default='no'), + user_data = dict(default=None), wait = dict(type='bool', default=True), wait_timeout = dict(default=300, type='int'), ssh_pub_key = dict(type='str'), From 41875984e51f7ce203207676690083de31c976f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20=C3=85ke=20Fransson?= Date: Thu, 26 Mar 2015 09:57:35 +0100 Subject: [PATCH 2/3] Make digital_ocean ssh command use API v2 --- cloud/digital_ocean/digital_ocean.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cloud/digital_ocean/digital_ocean.py b/cloud/digital_ocean/digital_ocean.py index 044b6f39774..c600ad15e25 100644 --- a/cloud/digital_ocean/digital_ocean.py +++ b/cloud/digital_ocean/digital_ocean.py @@ -101,7 +101,7 @@ options: - The public SSH key you want to add to your account. notes: - - Two environment variables can be used, DO_CLIENT_ID and DO_API_KEY. + - Two environment variables can be used, DO_API_KEY and DO_API_TOKEN. They both refer to the v2 token. requirements: [ dopy ] ''' @@ -116,7 +116,6 @@ EXAMPLES = ''' command=ssh name=my_ssh_key ssh_pub_key='ssh-rsa AAAA...' - client_id=XXX api_key=XXX # Create a new Droplet @@ -144,7 +143,6 @@ EXAMPLES = ''' command=droplet id=123 name=mydroplet - client_id=XXX api_key=XXX size_id=2gb region_id=ams2 @@ -160,7 +158,6 @@ EXAMPLES = ''' state=present ssh_key_ids=[id1,id2] name=mydroplet - client_id=XXX api_key=XXX size_id=2gb region_id=ams2 @@ -284,7 +281,7 @@ class SSH(JsonfyMixIn): @classmethod def setup(cls, client_id, api_key): - cls.manager = DoManager(client_id, api_key) + cls.manager = DoManager(client_id, api_key, api_version=2) @classmethod def find(cls, name): From 3f17ec489bf297d0adfed183c34d28736a6b9cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20=C3=85ke=20Fransson?= Date: Thu, 26 Mar 2015 13:56:39 +0100 Subject: [PATCH 3/3] Remove all reference to obsolete client_id and rename api_key to the for v2 more correct api_token --- cloud/digital_ocean/digital_ocean.py | 34 ++++++++++++---------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/cloud/digital_ocean/digital_ocean.py b/cloud/digital_ocean/digital_ocean.py index c600ad15e25..5c7cdf586e9 100644 --- a/cloud/digital_ocean/digital_ocean.py +++ b/cloud/digital_ocean/digital_ocean.py @@ -33,12 +33,9 @@ options: - Indicate desired state of the target. default: present choices: ['present', 'active', 'absent', 'deleted'] - client_id: - description: - - DigitalOcean manager id. - api_key: + api_token: description: - - DigitalOcean api key. + - DigitalOcean api token. id: description: - Numeric, the droplet id you want to operate on. @@ -116,7 +113,7 @@ EXAMPLES = ''' command=ssh name=my_ssh_key ssh_pub_key='ssh-rsa AAAA...' - api_key=XXX + api_token=XXX # Create a new Droplet # Will return the droplet details including the droplet id (used for idempotence) @@ -125,7 +122,7 @@ EXAMPLES = ''' state=present command=droplet name=mydroplet - api_key=XXX + api_token=XXX size_id=2gb region_id=ams2 image_id=fedora-19-x64 @@ -143,7 +140,7 @@ EXAMPLES = ''' command=droplet id=123 name=mydroplet - api_key=XXX + api_token=XXX size_id=2gb region_id=ams2 image_id=fedora-19-x64 @@ -158,7 +155,7 @@ EXAMPLES = ''' state=present ssh_key_ids=[id1,id2] name=mydroplet - api_key=XXX + api_token=XXX size_id=2gb region_id=ams2 image_id=fedora-19-x64 @@ -233,8 +230,8 @@ class Droplet(JsonfyMixIn): return self.manager.destroy_droplet(self.id, scrub_data=True) @classmethod - def setup(cls, client_id, api_key): - cls.manager = DoManager(client_id, api_key, api_version=2) + 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): @@ -280,8 +277,8 @@ class SSH(JsonfyMixIn): return True @classmethod - def setup(cls, client_id, api_key): - cls.manager = DoManager(client_id, api_key, api_version=2) + def setup(cls, api_token): + cls.manager = DoManager(None, api_token, api_version=2) @classmethod def find(cls, name): @@ -311,18 +308,16 @@ def core(module): return v try: - # params['client_id'] will be None even if client_id is not passed in - api_key = module.params['api_key'] or os.environ['DO_API_TOKEN'] or os.environ['DO_API_KEY'] + api_token = module.params['api_token'] or os.environ['DO_API_TOKEN'] or os.environ['DO_API_KEY'] except KeyError, e: module.fail_json(msg='Unable to load %s' % e.message) changed = True command = module.params['command'] state = module.params['state'] - client_id = 'notused' if command == 'droplet': - Droplet.setup(client_id, api_key) + Droplet.setup(api_token) if state in ('active', 'present'): # First, try to find a droplet by id. @@ -375,7 +370,7 @@ def core(module): module.exit_json(changed=True) elif command == 'ssh': - SSH.setup(client_id, api_key) + SSH.setup(api_token) name = getkeyordie('name') if state in ('active', 'present'): key = SSH.find(name) @@ -397,8 +392,7 @@ def main(): argument_spec = dict( command = dict(choices=['droplet', 'ssh'], default='droplet'), state = dict(choices=['active', 'present', 'absent', 'deleted'], default='present'), - client_id = dict(aliases=['CLIENT_ID'], no_log=True), - api_key = dict(aliases=['API_KEY'], no_log=True), + api_token = dict(aliases=['API_TOKEN'], no_log=True), name = dict(type='str'), size_id = dict(), image_id = dict(),