amazon.aws icon indicating copy to clipboard operation
amazon.aws copied to clipboard

s3_object in copy mode cannot change metadata

Open andreiboost opened this issue 4 months ago • 0 comments

Summary

The documentation suggests that metadata can be set when mode=copy but this doesn't appear to be the case. I cannot get metadata to be changed on the copy whatever I do.

This appears to be because the module doesn't override (or provide the option to override) the MetadataDirective parameter, which defaults to COPY (search for it in the boto3 docs).

I first observed this trying to copy an object while modifying its metadata (not shown here, but the copy always has the same metadata as its source). I suspect the reason is that objects have system defined metadata called Content-Type (visible in the console), which in essence is copied due to the directive, but this is speculation on my part.

Additionally, please consider updating the examples which show metadata as a comma separated string while the documentation lists it as a dict (which works as shown below).

Issue Type

Bug Report

Component Name

s3_object

Ansible Version

$ ansible --version
ansible [core 2.16.3]
  config file = /home/andrei/work/tools/andrei/playbooks/ansible.cfg
  configured module search path = ['/home/andrei/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.11/site-packages/ansible
  ansible collection location = /home/andrei/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.11.7 (main, Jan 29 2024, 16:03:57) [GCC 13.2.1 20230801] (/usr/bin/python)
  jinja version = 3.1.3
  libyaml = True

Collection Versions

$ ansible-galaxy collection list

# /home/andrei/.ansible/collections/ansible_collections
Collection                               Version
---------------------------------------- -------
amazon.aws                               7.2.0  
ansible.netcommon                        4.1.0  
ansible.posix                            1.5.1  
ansible.utils                            3.0.0  
cloud.common                             2.1.3  
community.aws                            7.1.0  
community.crypto                         2.10.0 
community.docker                         3.4.0  
community.general                        7.4.0  
community.postgresql                     3.3.0  
community.routeros                       2.5.0  
kubernetes.core                          2.4.0  

# /usr/lib/python3.11/site-packages/ansible_collections
Collection                               Version
---------------------------------------- -------
amazon.aws                               7.2.0  
ansible.netcommon                        5.3.0  
ansible.posix                            1.5.4  
ansible.utils                            2.12.0 
ansible.windows                          2.2.0  
arista.eos                               6.2.2  
awx.awx                                  23.6.0 
azure.azcollection                       1.19.0 
check_point.mgmt                         5.2.2  
chocolatey.chocolatey                    1.5.1  
cisco.aci                                2.8.0  
cisco.asa                                4.0.3  
cisco.dnac                               6.10.2 
cisco.intersight                         2.0.7  
cisco.ios                                5.3.0  
cisco.iosxr                              6.1.1  
cisco.ise                                2.7.0  
cisco.meraki                             2.17.2 
cisco.mso                                2.5.0  
cisco.nxos                               5.3.0  
cisco.ucs                                1.10.0 
cloud.common                             2.1.4  
cloudscale_ch.cloud                      2.3.1  
community.aws                            7.1.0  
community.azure                          2.0.0  
community.ciscosmb                       1.0.7  
community.crypto                         2.17.1 
community.digitalocean                   1.26.0 
community.dns                            2.8.0  
community.docker                         3.7.0  
community.general                        8.3.0  
community.grafana                        1.7.0  
community.hashi_vault                    6.1.0  
community.hrobot                         1.9.0  
community.library_inventory_filtering_v1 1.0.0  
community.libvirt                        1.3.0  
community.mongodb                        1.6.3  
community.mysql                          3.8.0  
community.network                        5.0.2  
community.okd                            2.3.0  
community.postgresql                     3.3.0  
community.proxysql                       1.5.1  
community.rabbitmq                       1.2.3  
community.routeros                       2.12.0 
community.sap                            2.0.0  
community.sap_libs                       1.4.2  
community.sops                           1.6.7  
community.vmware                         4.1.0  
community.windows                        2.1.0  
community.zabbix                         2.3.1  
containers.podman                        1.11.0 
cyberark.conjur                          1.2.2  
cyberark.pas                             1.0.25 
dellemc.enterprise_sonic                 2.4.0  
dellemc.openmanage                       8.7.0  
dellemc.powerflex                        2.1.0  
dellemc.unity                            1.7.1  
f5networks.f5_modules                    1.27.1 
fortinet.fortimanager                    2.3.1  
fortinet.fortios                         2.3.4  
frr.frr                                  2.0.2  
gluster.gluster                          1.0.2  
google.cloud                             1.3.0  
grafana.grafana                          2.2.4  
hetzner.hcloud                           2.4.1  
hpe.nimble                               1.1.4  
ibm.qradar                               2.1.0  
ibm.spectrum_virtualize                  2.0.0  
ibm.storage_virtualize                   2.2.0  
infinidat.infinibox                      1.3.12 
infoblox.nios_modules                    1.6.1  
inspur.ispim                             2.2.0  
inspur.sm                                2.3.0  
junipernetworks.junos                    5.3.1  
kubernetes.core                          2.4.0  
lowlydba.sqlserver                       2.2.2  
microsoft.ad                             1.4.1  
netapp.aws                               21.7.1 
netapp.azure                             21.10.1
netapp.cloudmanager                      21.22.1
netapp.elementsw                         21.7.0 
netapp.ontap                             22.9.0 
netapp.storagegrid                       21.11.1
netapp.um_info                           21.8.1 
netapp_eseries.santricity                1.4.0  
netbox.netbox                            3.16.0 
ngine_io.cloudstack                      2.3.0  
ngine_io.exoscale                        1.1.0  
openstack.cloud                          2.2.0  
openvswitch.openvswitch                  2.1.1  
ovirt.ovirt                              3.2.0  
purestorage.flasharray                   1.26.0 
purestorage.flashblade                   1.15.0 
purestorage.fusion                       1.6.0  
sensu.sensu_go                           1.14.0 
splunk.es                                2.1.2  
t_systems_mms.icinga_director            2.0.1  
telekom_mms.icinga_director              1.35.0 
theforeman.foreman                       3.15.0 
vmware.vmware_rest                       2.3.1  
vultr.cloud                              1.12.1 
vyos.vyos                                4.1.0  
wti.remote                               1.0.5

AWS SDK versions

$ pip show boto boto3 botocore
WARNING: Package(s) not found: boto
Name: boto3
Version: 1.34.34
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email: 
License: Apache License 2.0
Location: /usr/lib/python3.11/site-packages
Requires: botocore, jmespath, s3transfer
Required-by: 
---
Name: botocore
Version: 1.34.34
Summary: Low-level, data-driven core of boto 3.
Home-page: https://github.com/boto/botocore
Author: Amazon Web Services
Author-email: 
License: Apache License 2.0
Location: /usr/lib/python3.11/site-packages
Requires: jmespath, python-dateutil, urllib3
Required-by: boto3, s3transfer

Configuration

$ ansible-config dump --only-changed
CONFIG_FILE() = /home/andrei/work/tools/andrei/playbooks/ansible.cfg
DEFAULT_HOST_LIST(/home/andrei/work/tools/andrei/playbooks/ansible.cfg) = ...
DEFAULT_ROLES_PATH(/home/andrei/work/tools/andrei/playbooks/ansible.cfg) = ...
EDITOR(env: EDITOR) = vim
INVENTORY_ENABLED(/home/andrei/work/tools/andrei/playbooks/ansible.cfg) = ['ini', 'constructed', 'script']
PAGER(env: PAGER) = less

OS / Environment

Arch Linux

Steps to Reproduce

- name: Test playbook
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Create test bucket
      amazon.aws.s3_bucket:
        name: ansiblemetatest
        state: present

    - name: Create test object
      amazon.aws.s3_object:
        bucket: ansiblemetatest
        object: nometa
        mode: put
        content: "some content"

    - name: Copy and add metadata
      amazon.aws.s3_object:
        bucket: ansiblemetatest
        object: "metacopy"
        mode: copy
        copy_src:
          bucket: ansiblemetatest
          object: nometa
        metadata:
          something: exists
          version: "1.0.2"

    - name: Create test object with metadata
      amazon.aws.s3_object:
        bucket: ansiblemetatest
        object: withmeta
        mode: put
        content: "some content"
        metadata:
          something: exists
          version: "1.0.2"

    - name: Get object info
      amazon.aws.s3_object_info:
        bucket_name: ansiblemetatest
        object_name: "{{ item }}"
      loop:
        - nometa
        - metacopy
        - withmeta
      register: obj_info

    - debug:
        var: obj_info.results

Expected Results

metacopy should have its metadata set, like withmeta does.

Actual Results

PLAY [Test playbook] **********************************************************************************************************

TASK [Create test bucket] *****************************************************************************************************
changed: [localhost]

TASK [Create test object] *****************************************************************************************************
changed: [localhost]

TASK [Copy and add metadata] **************************************************************************************************
[WARNING]: PutObjectAcl operation : The bucket does not allow ACLs.
changed: [localhost]

TASK [Create test object with metadata] ***************************************************************************************
changed: [localhost]

TASK [Get object info] ********************************************************************************************************
ok: [localhost] => (item=nometa)
ok: [localhost] => (item=metacopy)
ok: [localhost] => (item=withmeta)

TASK [debug] ******************************************************************************************************************
ok: [localhost] => {
    "obj_info.results": [
        {
            "ansible_loop_var": "item",
            "changed": false,
            "failed": false,
            "invocation": {
                "module_args": {
                    "access_key": null,
                    "aws_ca_bundle": null,
                    "aws_config": null,
                    "bucket_name": "ansiblemetatest",
                    "ceph": false,
                    "debug_botocore_endpoint_logs": false,
                    "dualstack": false,
                    "endpoint_url": null,
                    "object_details": null,
                    "object_name": "nometa",
                    "profile": "sandbox",
                    "region": null,
                    "secret_key": null,
                    "session_token": null,
                    "validate_certs": true
                }
            },
            "item": "nometa",
            "object_info": [
                {
                    "object_data": {
                        "accept_ranges": "bytes",
                        "content_length": 12,
                        "content_type": "binary/octet-stream",
                        "e_tag": "\"9893532233caff98cd083a116b013c0b\"",
                        "last_modified": "2024-02-23T07:51:24+00:00",
                        "metadata": {},
                        "server_side_encryption": "AES256"
                    }
                }
            ]
        },
        {
            "ansible_loop_var": "item",
            "changed": false,
            "failed": false,
            "invocation": {
                "module_args": {
                    "access_key": null,
                    "aws_ca_bundle": null,
                    "aws_config": null,
                    "bucket_name": "ansiblemetatest",
                    "ceph": false,
                    "debug_botocore_endpoint_logs": false,
                    "dualstack": false,
                    "endpoint_url": null,
                    "object_details": null,
                    "object_name": "metacopy",
                    "profile": "sandbox",
                    "region": null,
                    "secret_key": null,
                    "session_token": null,
                    "validate_certs": true
                }
            },
            "item": "metacopy",
            "object_info": [
                {
                    "object_data": {
                        "accept_ranges": "bytes",
                        "content_length": 12,
                        "content_type": "binary/octet-stream",
                        "e_tag": "\"9893532233caff98cd083a116b013c0b\"",
                        "last_modified": "2024-02-23T07:51:26+00:00",
                        "metadata": {},
                        "server_side_encryption": "AES256"
                    }
                }
            ]
        },
        {
            "ansible_loop_var": "item",
            "changed": false,
            "failed": false,
            "invocation": {
                "module_args": {
                    "access_key": null,
                    "aws_ca_bundle": null,
                    "aws_config": null,
                    "bucket_name": "ansiblemetatest",
                    "ceph": false,
                    "debug_botocore_endpoint_logs": false,
                    "dualstack": false,
                    "endpoint_url": null,
                    "object_details": null,
                    "object_name": "withmeta",
                    "profile": "sandbox",
                    "region": null,
                    "secret_key": null,
                    "session_token": null,
                    "validate_certs": true
                }
            },
            "item": "withmeta",
            "object_info": [
                {
                    "object_data": {
                        "accept_ranges": "bytes",
                        "content_length": 12,
                        "content_type": "binary/octet-stream",
                        "e_tag": "\"9893532233caff98cd083a116b013c0b\"",
                        "last_modified": "2024-02-23T07:51:28+00:00",
                        "metadata": {
                            "something": "exists",
                            "version": "1.0.2"
                        },
                        "server_side_encryption": "AES256"
                    }
                }
            ]
        }
    ]
}

PLAY RECAP ********************************************************************************************************************
localhost                  : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Code of Conduct

  • [X] I agree to follow the Ansible Code of Conduct

andreiboost avatar Feb 23 '24 08:02 andreiboost