From 6fee6f71f7ffa103f7ddb69b43d29dcd4ff49201 Mon Sep 17 00:00:00 2001 From: Sloane Hertel Date: Tue, 10 Oct 2017 13:12:58 -0400 Subject: [PATCH] aws_s3: fix upload_file's ExtraArgs - fixes #31232 (#31487) * Module option metadata are extra arguments rather than S3 object metadata: update ExtraArgs variable. * Remove hyphens from ExtraArgs to maintain backwards compatibility * Map lowercase extra args to CamelCase * Maintain backwards compatibility by guessing at content type rather than always defaulting to binary/octet-stream. * Fix ExtraArgs for non-hyphenated options * Simplify logic --- lib/ansible/modules/cloud/amazon/aws_s3.py | 34 +++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/ansible/modules/cloud/amazon/aws_s3.py b/lib/ansible/modules/cloud/amazon/aws_s3.py index f6bd942be9..81c28ef599 100644 --- a/lib/ansible/modules/cloud/amazon/aws_s3.py +++ b/lib/ansible/modules/cloud/amazon/aws_s3.py @@ -268,6 +268,7 @@ s3_keys: ''' import os +import mimetypes import traceback from ansible.module_utils.six.moves.urllib.parse import urlparse from ssl import SSLError @@ -423,6 +424,21 @@ def path_check(path): return False +def option_in_extra_args(option): + temp_option = option.replace('-', '').lower() + + allowed_extra_args = {'acl': 'ACL', 'cachecontrol': 'CacheControl', 'contentdisposition': 'ContentDisposition', + 'contentencoding': 'ContentEncoding', 'contentlanguage': 'ContentLanguage', + 'contenttype': 'ContentType', 'expires': 'Expires', 'grantfullcontrol': 'GrantFullControl', + 'grantread': 'GrantRead', 'grantreadacp': 'GrantReadACP', 'grantwriteacp': 'GrantWriteACP', + 'metadata': 'Metadata', 'requestpayer': 'RequestPayer', 'serversideencryption': 'ServerSideEncryption', + 'storageclass': 'StorageClass', 'ssecustomeralgorithm': 'SSECustomerAlgorithm', 'ssecustomerkey': 'SSECustomerKey', + 'ssecustomerkeymd5': 'SSECustomerKeyMD5', 'ssekmskeyid': 'SSEKMSKeyId', 'websiteredirectlocation': 'WebsiteRedirectLocation'} + + if temp_option in allowed_extra_args: + return allowed_extra_args[temp_option] + + def upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers): if module.check_mode: module.exit_json(msg="PUT operation skipped - running in check mode", changed=True) @@ -431,7 +447,23 @@ def upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, heade if encrypt: extra['ServerSideEncryption'] = 'AES256' if metadata: - extra['Metadata'] = dict(metadata) + extra['Metadata'] = {} + + # determine object metadata and extra arguments + for option in metadata: + extra_args_option = option_in_extra_args(option) + if extra_args_option is not None: + extra[extra_args_option] = metadata[option] + else: + extra['Metadata'][option] = metadata[option] + + if 'ContentType' not in extra: + content_type = mimetypes.guess_type(src)[0] + if content_type is None: + # s3 default content type + content_type = 'binary/octet-stream' + extra['ContentType'] = content_type + s3.upload_file(Filename=src, Bucket=bucket, Key=obj, ExtraArgs=extra) for acl in module.params.get('permission'): s3.put_object_acl(ACL=acl, Bucket=bucket, Key=obj)