> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ansible Guide

> Run one endpoint-aware Ansible module through Cloud Adapter and verify idempotence.

Ansible support is module-specific. Use a module only when its installed collection version exposes the endpoint and request behavior you need. This example scopes the test to `amazon.aws.s3_object`; it does not claim compatibility for the entire `amazon.aws` collection.

## Prerequisites

* `ansible-core` and a pinned `amazon.aws` collection;
* boto3 and Botocore versions supported by that collection;
* an installed AWS-origin adapter endpoint;
* an existing test bucket and an isolated key;
* an origin-side test identity.

```bash theme={null}
ansible-galaxy collection list amazon.aws
python -c 'import boto3, botocore; print(boto3.__version__, botocore.__version__)'
```

## Write a bounded playbook

```yaml theme={null}
---
- name: Verify S3 through Cloud Adapter
  hosts: localhost
  gather_facts: false
  vars:
    adapter_endpoint: "https://adapter.example.test"
    test_bucket: "adapter-smoke-test"
    test_key: "ansible/cloud-adapter-smoke.txt"
    expected_body: "hello through Cloud Adapter\n"

  tasks:
    - name: Upload the smoke-test object
      amazon.aws.s3_object:
        mode: put
        bucket: "{{ test_bucket }}"
        object: "{{ test_key }}"
        content: "{{ expected_body }}"
        endpoint_url: "{{ adapter_endpoint }}"
        region: us-east-1
        profile: adapter-test
      register: first_put

    - name: Allocate an isolated download file
      ansible.builtin.tempfile:
        state: file
        suffix: .cloud-adapter-smoke
      register: downloaded

    - name: Download the object through Cloud Adapter
      amazon.aws.s3_object:
        mode: get
        bucket: "{{ test_bucket }}"
        object: "{{ test_key }}"
        dest: "{{ downloaded.path }}"
        endpoint_url: "{{ adapter_endpoint }}"
        region: us-east-1
        profile: adapter-test
      register: object_read

    - name: Read the downloaded bytes
      ansible.builtin.slurp:
        src: "{{ downloaded.path }}"
      register: downloaded_bytes

    - name: Prove the remote read returned the expected bytes
      ansible.builtin.assert:
        that:
          - object_read is succeeded
          - downloaded_bytes.content | b64decode == expected_body
        success_msg: "Cloud Adapter returned the expected object bytes"
```

Avoid printing the full registered result at high verbosity. It may contain endpoints, signed values, or response details that do not belong in shared logs.

## Test idempotence

Run the playbook twice:

```bash theme={null}
ansible-playbook adapter-smoke.yml --diff
ansible-playbook adapter-smoke.yml --diff
```

The second run should match the module's documented idempotence behavior. If it reports a change every time, inspect which field differs and compare it with the target-specific fidelity table. Check mode is not proof of API compatibility because modules vary in how much remote state they read under `--check`.

## Verify and clean up

Inspect the object in the native target service. Confirm bytes, content type, and translated resource identity. Then remove only the test object:

```yaml theme={null}
- name: Delete the smoke-test object
  amazon.aws.s3_object:
    mode: delobj
    bucket: "{{ test_bucket }}"
    object: "{{ test_key }}"
    endpoint_url: "{{ adapter_endpoint }}"
    region: us-east-1
    profile: adapter-test
```

## Troubleshooting

Use `-vv` before `-vvv`; higher verbosity can expose sensitive request details. Separate collection validation, Python dependency failures, origin authentication, adapter translation, and target permissions. Reproduce the same operation with the [AWS CLI guide](/cloud-adapter/guides/aws-cli) when you need a smaller control.

Check every operation against [S3 service coverage](/cloud-adapter/service-catalog/aws/databases-storage/s3).
