diff --git a/lib/ansible/modules/extras/packaging/language/maven_artifact.py b/lib/ansible/modules/extras/packaging/language/maven_artifact.py index 1a33d1b989..38802653c3 100644 --- a/lib/ansible/modules/extras/packaging/language/maven_artifact.py +++ b/lib/ansible/modules/extras/packaging/language/maven_artifact.py @@ -28,6 +28,11 @@ import sys import posixpath from ansible.module_utils.basic import * from ansible.module_utils.urls import * +try: + import boto3 + HAS_BOTO = True +except ImportError: + HAS_BOTO = False DOCUMENTATION = ''' --- @@ -42,6 +47,7 @@ author: "Chris Schmidt (@chrisisbeef)" requirements: - "python >= 2.6" - lxml + - boto if using a S3 repository (s3://...) options: group_id: description: @@ -68,19 +74,21 @@ options: default: jar repository_url: description: - - The URL of the Maven Repository to download from + - The URL of the Maven Repository to download from. Use s3://... if the repository is hosted on Amazon S3 required: false default: http://repo1.maven.org/maven2 username: description: - - The username to authenticate as to the Maven Repository + - The username to authenticate as to the Maven Repository. Use AWS secret key of the repository is hosted on S3 required: false default: null + aliases: [ "aws_secret_key" ] password: description: - - The password to authenticate with to the Maven Repository + - The password to authenticate with to the Maven Repository. Use AWS secret access key of the repository is hosted on S3 required: false default: null + aliases: [ "aws_secret_access_key" ] dest: description: - The path where the artifact should be written to @@ -185,7 +193,8 @@ class Artifact(object): class MavenDownloader: def __init__(self, module, base="http://repo1.maven.org/maven2"): self.module = module - base = base.rstrip("/") + if base.endswith("/"): + base = base.rstrip("/") self.base = base self.user_agent = "Maven Artifact Downloader/1.0" @@ -220,14 +229,23 @@ class MavenDownloader: return posixpath.join(self.base, artifact.path(), artifact.artifact_id + "-" + version + "." + artifact.extension) def _request(self, url, failmsg, f): + url_to_use = url + parsed_url = urlparse.urlparse(url) + if parsed_url.scheme=='s3': + parsed_url = urlparse.urlparse(url) + bucket_name = parsed_url.netloc[:parsed_url.netloc.find('.')] + key_name = parsed_url.path[1:] + client = boto3.client('s3',aws_access_key_id=self.module.params.get('username', ''), aws_secret_access_key=self.module.params.get('password', '')) + url_to_use = client.generate_presigned_url('get_object',Params={'Bucket':bucket_name,'Key':key_name},ExpiresIn=10) + # Hack to add parameters in the way that fetch_url expects self.module.params['url_username'] = self.module.params.get('username', '') self.module.params['url_password'] = self.module.params.get('password', '') self.module.params['http_agent'] = self.module.params.get('user_agent', None) - response, info = fetch_url(self.module, url) + response, info = fetch_url(self.module, url_to_use) if info['status'] != 200: - raise ValueError(failmsg + " because of " + info['msg'] + "for URL " + url) + raise ValueError(failmsg + " because of " + info['msg'] + "for URL " + url_to_use) else: return f(response) @@ -305,14 +323,20 @@ def main(): classifier = dict(default=None), extension = dict(default='jar'), repository_url = dict(default=None), - username = dict(default=None), - password = dict(default=None, no_log=True), + username = dict(default=None,aliases=['aws_secret_key']), + password = dict(default=None, no_log=True,aliases=['aws_secret_access_key']), state = dict(default="present", choices=["present","absent"]), # TODO - Implement a "latest" state dest = dict(type="path", default=None), validate_certs = dict(required=False, default=True, type='bool'), ) ) + + parsed_url = urlparse.urlparse(module.params["repository_url"]) + + if parsed_url.scheme=='s3' and not HAS_BOTO: + module.fail_json(msg='boto3 required for this module, when using s3:// repository URLs') + group_id = module.params["group_id"] artifact_id = module.params["artifact_id"] version = module.params["version"]