Merge remote-tracking branch 'upstream/devel' into win_fw

reviewable/pr18780/r1
Timothy Vandenbrande 10 years ago
commit 27a2d8a729

@ -13,4 +13,4 @@ script:
- python2.4 -m compileall -fq -x 'cloud/|monitoring/zabbix.*\.py|/layman\.py|/maven_artifact\.py|clustering/consul.*\.py|notification/pushbullet\.py' .
- python2.6 -m compileall -fq .
- python2.7 -m compileall -fq .
- ./test-docs.sh extras
#- ./test-docs.sh extras

@ -15,14 +15,33 @@ options:
required: true
key_file:
description:
- path to the file containing the key pair used on the instance
- Path to the file containing the key pair used on the instance.
required: true
key_passphrase:
version_added: "2.0"
description:
- The passphrase for the instance key pair. The key must use DES or 3DES encryption for this module to decrypt it. You can use openssl to convert your password protected keys if they do not use DES or 3DES. ex) openssl rsa -in current_key -out new_key -des3.
required: false
default: null
region:
description:
- The AWS region to use. Must be specified if ec2_url is not used. If not specified then the value of the EC2_REGION environment variable, if any, is used.
required: false
default: null
aliases: [ 'aws_region', 'ec2_region' ]
wait:
version_added: "2.0"
description:
- Whether or not to wait for the password to be available before returning.
required: false
default: "no"
choices: [ "yes", "no" ]
wait_timeout:
version_added: "2.0"
description:
- Number of seconds to wait before giving up.
required: false
default: 120
extends_documentation_fragment: aws
'''
@ -36,12 +55,34 @@ tasks:
instance_id: i-XXXXXX
region: us-east-1
key_file: "~/aws-creds/my_test_key.pem"
# Example of getting a password with a password protected key
tasks:
- name: get the Administrator password
ec2_win_password:
profile: my-boto-profile
instance_id: i-XXXXXX
region: us-east-1
key_file: "~/aws-creds/my_protected_test_key.pem"
key_passphrase: "secret"
# Example of waiting for a password
tasks:
- name: get the Administrator password
ec2_win_password:
profile: my-boto-profile
instance_id: i-XXXXXX
region: us-east-1
key_file: "~/aws-creds/my_test_key.pem"
wait: yes
wait_timeout: 45
'''
from base64 import b64decode
from os.path import expanduser
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
import datetime
try:
import boto.ec2
@ -54,6 +95,9 @@ def main():
argument_spec.update(dict(
instance_id = dict(required=True),
key_file = dict(required=True),
key_passphrase = dict(no_log=True, default=None, required=False),
wait = dict(type='bool', default=False, required=False),
wait_timeout = dict(default=120, required=False),
)
)
module = AnsibleModule(argument_spec=argument_spec)
@ -63,26 +107,48 @@ def main():
instance_id = module.params.get('instance_id')
key_file = expanduser(module.params.get('key_file'))
key_passphrase = module.params.get('key_passphrase')
wait = module.params.get('wait')
wait_timeout = int(module.params.get('wait_timeout'))
ec2 = ec2_connect(module)
data = ec2.get_password_data(instance_id)
decoded = b64decode(data)
if wait:
start = datetime.datetime.now()
end = start + datetime.timedelta(seconds=wait_timeout)
while datetime.datetime.now() < end:
data = ec2.get_password_data(instance_id)
decoded = b64decode(data)
if wait and not decoded:
time.sleep(5)
else:
break
else:
data = ec2.get_password_data(instance_id)
decoded = b64decode(data)
if wait and datetime.datetime.now() >= end:
module.fail_json(msg = "wait for password timeout after %d seconds" % wait_timeout)
f = open(key_file, 'r')
key = RSA.importKey(f.read())
key = RSA.importKey(f.read(), key_passphrase)
cipher = PKCS1_v1_5.new(key)
sentinel = 'password decryption failed!!!'
try:
decrypted = cipher.decrypt(decoded, sentinel)
decrypted = cipher.decrypt(decoded, sentinel)
except ValueError as e:
decrypted = None
decrypted = None
if decrypted == None:
module.exit_json(win_password='', changed=False)
else:
module.exit_json(win_password=decrypted, changed=True)
if wait:
elapsed = datetime.datetime.now() - start
module.exit_json(win_password=decrypted, changed=True, elapsed=elapsed.seconds)
else:
module.exit_json(win_password=decrypted, changed=True)
# import module snippets
from ansible.module_utils.basic import *

@ -400,11 +400,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -246,11 +246,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -130,7 +130,7 @@ class CloudStackFacts(object):
if not filter:
for key,path in self.fact_paths.iteritems():
result[key] = self._fetch(CS_METADATA_BASE_URL + "/" + path)
result['cloudstack_user_data'] = self._get_user_data_json()
result['cloudstack_user_data'] = self._get_user_data_json()
else:
if filter == 'cloudstack_user_data':
result['cloudstack_user_data'] = self._get_user_data_json()

@ -451,11 +451,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -384,10 +384,11 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
self.module.fail_json(msg="Template are ISO are mutually exclusive.")
args = {}
args['account'] = self.get_account('name')
args['domainid'] = self.get_domain('id')
args['projectid'] = self.get_project('id')
args['zoneid'] = self.get_zone('id')
args['account'] = self.get_account(key='name')
args['domainid'] = self.get_domain(key='id')
args['projectid'] = self.get_project(key='id')
args['zoneid'] = self.get_zone(key='id')
args['isrecursive'] = True
if template:
if self.template:
@ -421,10 +422,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
if not disk_offering:
return None
args = {}
args['domainid'] = self.get_domain('id')
disk_offerings = self.cs.listDiskOfferings(**args)
disk_offerings = self.cs.listDiskOfferings()
if disk_offerings:
for d in disk_offerings['diskoffering']:
if disk_offering in [ d['displaytext'], d['name'], d['id'] ]:
@ -438,11 +436,10 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
instance_name = self.module.params.get('name')
args = {}
args['account'] = self.get_account('name')
args['domainid'] = self.get_domain('id')
args['projectid'] = self.get_project('id')
args['zoneid'] = self.get_zone('id')
args['account'] = self.get_account(key='name')
args['domainid'] = self.get_domain(key='id')
args['projectid'] = self.get_project(key='id')
# Do not pass zoneid, as the instance name must be unique across zones.
instances = self.cs.listVirtualMachines(**args)
if instances:
for v in instances['virtualmachine']:
@ -458,10 +455,10 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
return None
args = {}
args['account'] = self.get_account('name')
args['domainid'] = self.get_domain('id')
args['projectid'] = self.get_project('id')
args['zoneid'] = self.get_zone('id')
args['account'] = self.get_account(key='name')
args['domainid'] = self.get_domain(key='id')
args['projectid'] = self.get_project(key='id')
args['zoneid'] = self.get_zone(key='id')
networks = self.cs.listNetworks(**args)
if not networks:
@ -513,11 +510,11 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
args = {}
args['templateid'] = self.get_template_or_iso(key='id')
args['zoneid'] = self.get_zone('id')
args['zoneid'] = self.get_zone(key='id')
args['serviceofferingid'] = self.get_service_offering_id()
args['account'] = self.get_account('name')
args['domainid'] = self.get_domain('id')
args['projectid'] = self.get_project('id')
args['account'] = self.get_account(key='name')
args['domainid'] = self.get_domain(key='id')
args['projectid'] = self.get_project(key='id')
args['diskofferingid'] = self.get_disk_offering_id()
args['networkids'] = self.get_network_ids()
args['userdata'] = self.get_user_data()
@ -558,12 +555,12 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
args_instance_update['group'] = self.module.params.get('group')
args_instance_update['displayname'] = self.get_display_name()
args_instance_update['userdata'] = self.get_user_data()
args_instance_update['ostypeid'] = self.get_os_type('id')
args_instance_update['ostypeid'] = self.get_os_type(key='id')
args_ssh_key = {}
args_ssh_key['id'] = instance['id']
args_ssh_key['keypair'] = self.module.params.get('ssh_key')
args_ssh_key['projectid'] = self.get_project('id')
args_ssh_key['projectid'] = self.get_project(key='id')
if self._has_changed(args_service_offering, instance) or \
self._has_changed(args_instance_update, instance) or \
@ -636,7 +633,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
if instance['state'].lower() in [ 'destroying', 'destroyed' ]:
self.result['changed'] = True
if not self.module.check_mode:
res = self.cs.expungeVirtualMachine(id=instance['id'])
res = self.cs.destroyVirtualMachine(id=instance['id'], expunge=True)
elif instance['state'].lower() not in [ 'expunging' ]:
self.result['changed'] = True
@ -648,7 +645,7 @@ class AnsibleCloudStackInstance(AnsibleCloudStack):
poll_async = self.module.params.get('poll_async')
if poll_async:
instance = self._poll_job(res, 'virtualmachine')
res = self._poll_job(res, 'virtualmachine')
return instance
@ -855,11 +852,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -223,11 +223,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -354,11 +354,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -627,11 +627,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -427,11 +427,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -332,11 +332,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -190,11 +190,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -429,11 +429,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -249,11 +249,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -623,11 +623,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -317,11 +317,9 @@ def main():
except CloudStackException, e:
module.fail_json(msg='CloudStackException: %s' % str(e))
except Exception, e:
module.fail_json(msg='Exception: %s' % str(e))
module.exit_json(**result)
# import module snippets
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

@ -78,6 +78,9 @@ import socket
def vmware_path(datastore, datacenter, path):
''' Constructs a URL path that VSphere accepts reliably '''
path = "/folder/%s" % path.lstrip("/")
# Due to a software bug in vSphere, it fails to handle ampersand in datacenter names
# The solution is to do what vSphere does (when browsing) and double-encode ampersands, maybe others ?
datacenter = datacenter.replace('&', '%26')
if not path.startswith("/"):
path = "/" + path
params = dict( dsName = datastore )
@ -146,6 +149,7 @@ def main():
else:
module.fail_json(msg='Failed to upload', status=resp.status, reason=resp.reason, length=resp.length, version=resp.version, headers=resp.getheaders(), chunked=resp.chunked, url=url)
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
# Import module snippets
from ansible.module_utils.basic import *
main()

@ -1,4 +1,4 @@
#! /usr/bin/python
#!/usr/bin/python
#
# Create a Webfaction application using Ansible and the Webfaction API
#
@ -7,7 +7,9 @@
#
# ------------------------------------------
#
# (c) Quentin Stafford-Fraser 2015
# (c) Quentin Stafford-Fraser 2015, with contributions gratefully acknowledged from:
# * Andy Baker
# * Federico Tarantini
#
# This file is part of Ansible
#
@ -80,6 +82,12 @@ options:
description:
- The webfaction password to use
required: true
machine:
description:
- The machine name to use (optional for accounts with only one machine)
required: false
'''
EXAMPLES = '''
@ -90,6 +98,7 @@ EXAMPLES = '''
type=mod_wsgi35-python27
login_name={{webfaction_user}}
login_password={{webfaction_passwd}}
machine={{webfaction_machine}}
'''
import xmlrpclib
@ -108,6 +117,7 @@ def main():
port_open = dict(required=False, choices=BOOLEANS, default=False),
login_name = dict(required=True),
login_password = dict(required=True),
machine = dict(required=False, default=False),
),
supports_check_mode=True
)
@ -115,10 +125,17 @@ def main():
app_type = module.params['type']
app_state = module.params['state']
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password']
)
if module.params['machine']:
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password'],
module.params['machine']
)
else:
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password']
)
app_list = webfaction.list_apps(session_id)
app_map = dict([(i['name'], i) for i in app_list])

@ -1,10 +1,12 @@
#! /usr/bin/python
#!/usr/bin/python
#
# Create a webfaction database using Ansible and the Webfaction API
#
# ------------------------------------------
#
# (c) Quentin Stafford-Fraser and Andy Baker 2015
# (c) Quentin Stafford-Fraser 2015, with contributions gratefully acknowledged from:
# * Andy Baker
# * Federico Tarantini
#
# This file is part of Ansible
#
@ -68,6 +70,11 @@ options:
description:
- The webfaction password to use
required: true
machine:
description:
- The machine name to use (optional for accounts with only one machine)
required: false
'''
EXAMPLES = '''
@ -81,6 +88,7 @@ EXAMPLES = '''
type: mysql
login_name: "{{webfaction_user}}"
login_password: "{{webfaction_passwd}}"
machine: "{{webfaction_machine}}"
# Note that, for symmetry's sake, deleting a database using
# 'state: absent' will also delete the matching user.
@ -103,6 +111,7 @@ def main():
password = dict(required=False, default=None),
login_name = dict(required=True),
login_password = dict(required=True),
machine = dict(required=False, default=False),
),
supports_check_mode=True
)
@ -111,10 +120,17 @@ def main():
db_type = module.params['type']
db_passwd = module.params['password']
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password']
)
if module.params['machine']:
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password'],
module.params['machine']
)
else:
session_id, account = webfaction.login(
module.params['login_name'],
module.params['login_password']
)
db_list = webfaction.list_dbs(session_id)
db_map = dict([(i['name'], i) for i in db_list])
@ -130,7 +146,7 @@ def main():
if db_state == 'present':
# Does an database with this name already exist?
# Does a database with this name already exist?
if existing_db:
# Yes, but of a different type - fail
if existing_db['db_type'] != db_type:

@ -1,4 +1,4 @@
#! /usr/bin/python
#!/usr/bin/python
#
# Create Webfaction domains and subdomains using Ansible and the Webfaction API
#

@ -1,4 +1,4 @@
#! /usr/bin/python
#!/usr/bin/python
#
# Create webfaction mailbox using Ansible and the Webfaction API
#

@ -1,4 +1,4 @@
#! /usr/bin/python
#!/usr/bin/python
#
# Create Webfaction website using Ansible and the Webfaction API
#

@ -225,10 +225,10 @@ def main():
update_password = module.params['update_password']
try:
if replica_set:
client = MongoClient(login_host, int(login_port), replicaset=replica_set, ssl=ssl)
else:
client = MongoClient(login_host, int(login_port), ssl=ssl)
if replica_set:
client = MongoClient(login_host, int(login_port), replicaset=replica_set, ssl=ssl)
else:
client = MongoClient(login_host, int(login_port), ssl=ssl)
if login_user is None and login_password is None:
mongocnf_creds = load_mongocnf()

@ -40,18 +40,22 @@ options:
default: present
chdir:
description:
- The directory to execute the bundler commands from. This directoy needs to contain a valid Gemfile or .bundle/ directory
- The directory to execute the bundler commands from. This directoy
needs to contain a valid Gemfile or .bundle/ directory
required: false
default: temporary working directory
exclude_groups:
description:
- A list of Gemfile groups to exclude during operations. This only applies when state is C(present). Bundler considers this a 'remembered'
property for the Gemfile and will automatically exclude groups in future operations even if C(exclude_groups) is not set
- A list of Gemfile groups to exclude during operations. This only
applies when state is C(present). Bundler considers this
a 'remembered' property for the Gemfile and will automatically exclude
groups in future operations even if C(exclude_groups) is not set
required: false
default: null
clean:
description:
- Only applies if state is C(present). If set removes any gems on the target host that are not in the gemfile
- Only applies if state is C(present). If set removes any gems on the
target host that are not in the gemfile
required: false
choices: [yes, no]
default: "no"
@ -68,8 +72,9 @@ options:
default: "no"
deployment_mode:
description:
- Only applies if state is C(present). If set it will only install gems that are in the default or production groups. Requires a Gemfile.lock
file to have been created prior
- Only applies if state is C(present). If set it will only install gems
that are in the default or production groups. Requires a Gemfile.lock
file to have been created prior
required: false
choices: [yes, no]
default: "no"
@ -81,22 +86,28 @@ options:
default: "yes"
gem_path:
description:
- Only applies if state is C(present). Specifies the directory to install the gems into. If C(chdir) is set then this path is relative to C(chdir)
required: false
default: RubyGems gem paths
- Only applies if state is C(present). Specifies the directory to
install the gems into. If C(chdir) is set then this path is relative to
C(chdir)
required: false
default: RubyGems gem paths
binstub_directory:
description:
- Only applies if state is C(present). Specifies the directory to install any gem bins files to. When executed the bin files will run within
the context of the Gemfile and fail if any required gem dependencies are not installed. If C(chdir) is set then this path is relative to C(chdir)
- Only applies if state is C(present). Specifies the directory to
install any gem bins files to. When executed the bin files will run
within the context of the Gemfile and fail if any required gem
dependencies are not installed. If C(chdir) is set then this path is
relative to C(chdir)
required: false
default: null
extra_args:
description:
- A space separated string of additional commands that can be applied to the Bundler command. Refer to the Bundler documentation for more
information
- A space separated string of additional commands that can be applied to
the Bundler command. Refer to the Bundler documentation for more
information
required: false
default: null
author: Tim Hoiberg
author: "Tim Hoiberg (@thoiberg)"
'''
EXAMPLES='''
@ -196,4 +207,5 @@ def main():
from ansible.module_utils.basic import *
main()
if __name__ == '__main__':
main()

Loading…
Cancel
Save