diff --git a/library/cloud/digital_ocean b/library/cloud/digital_ocean index 610c18132e..31ec50888f 100644 --- a/library/cloud/digital_ocean +++ b/library/cloud/digital_ocean @@ -45,6 +45,11 @@ options: 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, digital ocean allows multiple hosts with the same name. Setting this to "yes" allows only one host per name. Useful for idempotence. + default: "no" + choices: [ "yes", "no" ] size_id: description: - Numeric, this is the id of the size you would like the droplet created at. @@ -102,7 +107,8 @@ EXAMPLES = ''' image_id=3 wait_timeout=500 register: my_droplet -- debug: msg="ID: {{ my_droplet.droplet.id }} IP: {{ my_droplet.droplet.ip_address }}" +- 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 @@ -186,9 +192,9 @@ class Droplet(JsonfyMixIn): self.power_on() if wait: - end_time = time.time()+wait_timeout + end_time = time.time() + wait_timeout while time.time() < end_time: - time.sleep(min(20, end_time-time.time())) + time.sleep(min(20, end_time - time.time())) self.update_attr() if self.is_powered_on(): if not self.ip_address: @@ -210,13 +216,22 @@ class Droplet(JsonfyMixIn): return droplet @classmethod - def find(cls, id): - if not id: + 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 @@ -280,27 +295,49 @@ def core(module): if command == 'droplet': Droplet.setup(client_id, api_key) if state in ('active', 'present'): - droplet = Droplet.find(module.params['id']) + + # 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'] - ) + 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'] + ) + if droplet.is_powered_on(): changed = False + droplet.ensure_powered_on( - wait=getkeyordie('wait'), - wait_timeout=getkeyordie('wait_timeout') - ) + wait=getkeyordie('wait'), + wait_timeout=getkeyordie('wait_timeout') + ) + module.exit_json(changed=changed, droplet=droplet.to_json()) elif state in ('absent', 'deleted'): - droplet = Droplet.find(getkeyordie('id')) + # First, try to find a droplet by id. + droplet = Droplet.find(id=getkeyordie('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.') + event_json = droplet.destroy() module.exit_json(changed=True, event_id=event_json['event_id']) @@ -335,6 +372,7 @@ def main(): region_id = dict(type='int'), ssh_key_ids = dict(default=''), id = dict(aliases=['droplet_id'], type='int'), + unique_name = dict(type='bool', choices=BOOLEANS, default='no'), wait = dict(type='bool', choices=BOOLEANS, default='yes'), wait_timeout = dict(default=300, type='int'), ssh_pub_key = dict(type='str'),