From 1150b78bb00acbae5c904abb8671afd8ec2b94c3 Mon Sep 17 00:00:00 2001 From: Vincent Viallet Date: Thu, 12 Dec 2013 12:23:58 +0800 Subject: [PATCH 1/3] Add ec2_key module. --- library/cloud/ec2_key | 211 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 library/cloud/ec2_key diff --git a/library/cloud/ec2_key b/library/cloud/ec2_key new file mode 100644 index 00000000000..7a4926171f2 --- /dev/null +++ b/library/cloud/ec2_key @@ -0,0 +1,211 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +DOCUMENTATION = ''' +--- +module: ec2_key +version_added: "1.3" +short_description: maintain an ec2 key pair. +description: + - maintains ec2 key pairs. This module has a dependency on python-boto >= 2.5 +options: + name: + description: + - Name of the key pair. + required: true + key_material: + description: + - Public key material. + required: false + region: + description: + - the EC2 region to use + required: false + default: null + aliases: [] + ec2_url: + description: + - Url to use to connect to EC2 or your Eucalyptus cloud (by default the module will use EC2 endpoints) + required: false + default: null + aliases: [] + ec2_secret_key: + description: + - EC2 secret key + required: false + default: null + aliases: ['aws_secret_key'] + ec2_access_key: + description: + - EC2 access key + required: false + default: null + aliases: ['aws_access_key'] + state: + version_added: "1.4" + description: + - create or delete security group + required: false + default: 'present' + aliases: [] + +requirements: [ "boto" ] +author: Vincent Viallet +''' + +EXAMPLES = ''' +# Creates a new ec2 key pair named `example` if not present, returns generated +# private key +- name: example ec2 key + local_action: + module: ec2_key + name: example + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + +# Creates a new ec2 key pair named `example` if not present using provided key +# material +- name: example2 ec2 key + local_action: + module: ec2_key + name: example2 + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + key_material: 'ssh-rsa AAAAxyz...== me@example.com' + state: present + +# Creates a new ec2 key pair named `example` if not present using provided key +# material +- name: example3 ec2 key + local_action: + module: ec2_key + name: example3 + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + key_material: "{{ item }}" + with_file: /path/to/public_key.id_rsa.pub + +# Removes ec2 key pair by name +- name: remove example key + local_action: + module: ec2_key + name: example + state: absent + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS +''' + +try: + import boto.ec2 +except ImportError: + print "failed=True msg='boto required for this module'" + sys.exit(1) + +# Required if importing key +import base64 + +def main(): + module = AnsibleModule( + argument_spec=dict( + name=dict(required=True), + key_material=dict(required=False), + ec2_url=dict(aliases=['EC2_URL']), + ec2_secret_key=dict(aliases=['EC2_SECRET_KEY', 'aws_secret_key'], no_log=True), + ec2_access_key=dict(aliases=['EC2_ACCESS_KEY', 'aws_access_key']), + region=dict(choices=['eu-west-1', 'sa-east-1', 'us-east-1', 'ap-northeast-1', 'us-west-2', 'us-west-1', 'ap-southeast-1', 'ap-southeast-2']), + state = dict(default='present', choices=['present', 'absent']), + ), + supports_check_mode=True, + ) + + # def get_ec2_creds(module): + # return ec2_url, ec2_access_key, ec2_secret_key, region + ec2_url, ec2_access_key, ec2_secret_key, region = get_ec2_creds(module) + + name = module.params['name'] + state = module.params.get('state') + key_material = module.params.get('key_material') + + changed = False + + # If we have a region specified, connect to its endpoint. + if region: + try: + ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=ec2_access_key, aws_secret_access_key=ec2_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg=str(e)) + # Otherwise, no region so we fallback to the old connection method + else: + try: + if ec2_url: # if we have an URL set, connect to the specified endpoint + ec2 = boto.connect_ec2_endpoint(ec2_url, ec2_access_key, ec2_secret_key) + else: # otherwise it's Amazon. + ec2 = boto.connect_ec2(ec2_access_key, ec2_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg=str(e)) + + # find the key if present + key = ec2.get_key_pair(name) + + # Ensure requested key is absent + if state == 'absent': + if key: + '''found a match, delete it''' + try: + key.delete() + except Exception, e: + module.fail_json(msg="Unable to key pair '%s' - %s" % (key, e)) + else: + key = None + changed = True + else: + '''no match found, no changes required''' + + # Ensure requested group is present + elif state == 'present': + if key: + '''existing key found''' + # Should check if the fingerprint is the same - but lack of info + # and different fingerprint provided (pub or private) depending if + # the key has been created of imported. + pass + + # if the group doesn't exist, create it now + else: + '''no match found, create it''' + if not module.check_mode: + if key_material: + '''We are providing the key, need to import''' + key = ec2.import_key_pair(name, key_material) + else: + ''' + No material provided, let AWS handle the key creation and + retrieve the private key + ''' + key = ec2.create_key_pair(name) + changed = True + else: + module.fail_json(msg="Unsupported state requested: %s" % state) + + if key: + data = { + 'name': key.name, + 'fingerprint': key.fingerprint + } + if key.material: + data.update({'private_key': key.material}) + + module.exit_json(changed=changed, key=data) + else: + module.exit_json(changed=changed, key=None) + +# import module snippets +from ansible.module_utils.basic import * +from ansible.module_utils.ec2 import * + +main() From 30820437bb3dd5f80788553f8dea7afd2c9f41b4 Mon Sep 17 00:00:00 2001 From: Vincent Viallet Date: Thu, 12 Dec 2013 12:30:22 +0800 Subject: [PATCH 2/3] Minor typos and remove extra dependencies. --- library/cloud/ec2_key | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/library/cloud/ec2_key b/library/cloud/ec2_key index 7a4926171f2..dc51c2ab19d 100644 --- a/library/cloud/ec2_key +++ b/library/cloud/ec2_key @@ -106,9 +106,6 @@ except ImportError: print "failed=True msg='boto required for this module'" sys.exit(1) -# Required if importing key -import base64 - def main(): module = AnsibleModule( argument_spec=dict( @@ -159,14 +156,14 @@ def main(): try: key.delete() except Exception, e: - module.fail_json(msg="Unable to key pair '%s' - %s" % (key, e)) + module.fail_json(msg="Unable to delete key pair '%s' - %s" % (key, e)) else: key = None changed = True else: '''no match found, no changes required''' - # Ensure requested group is present + # Ensure requested key is present elif state == 'present': if key: '''existing key found''' @@ -175,7 +172,7 @@ def main(): # the key has been created of imported. pass - # if the group doesn't exist, create it now + # if the key doesn't exist, create it now else: '''no match found, create it''' if not module.check_mode: From db37528fd26d389d76f3b2985adb3e99013c0e1a Mon Sep 17 00:00:00 2001 From: Vincent Viallet Date: Fri, 13 Dec 2013 08:59:52 +0800 Subject: [PATCH 3/3] Bumped to v1.5 --- library/cloud/ec2_key | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/cloud/ec2_key b/library/cloud/ec2_key index dc51c2ab19d..c7e85a8cd37 100644 --- a/library/cloud/ec2_key +++ b/library/cloud/ec2_key @@ -5,7 +5,7 @@ DOCUMENTATION = ''' --- module: ec2_key -version_added: "1.3" +version_added: "1.5" short_description: maintain an ec2 key pair. description: - maintains ec2 key pairs. This module has a dependency on python-boto >= 2.5 @@ -43,7 +43,7 @@ options: default: null aliases: ['aws_access_key'] state: - version_added: "1.4" + version_added: "1.5" description: - create or delete security group required: false