> ## 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.

# Quickstart: AWS to Google Cloud

> Send AWS S3 requests through Cloud Adapter to Google Cloud Storage.

Keep an AWS S3 client unchanged while Cloud Adapter translates supported requests to Google Cloud Storage. This quickstart writes one object through the S3 API, verifies it natively in Google Cloud, exercises a translated not-found response, and removes the test object.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/tensor9/3qwgIru3kCfHriJC/images/diagrams/cloud-adapter-quickstart-aws-to-google-cloud-dark.svg?fit=max&auto=format&n=3qwgIru3kCfHriJC&q=85&s=a056f90b0da475fbce499d9a4b42fb9b" alt="AWS API requests pass through Tensor9 Cloud Adapter to Google Cloud services." width="1100" height="360" data-path="images/diagrams/cloud-adapter-quickstart-aws-to-google-cloud-dark.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/tensor9/3qwgIru3kCfHriJC/images/diagrams/cloud-adapter-quickstart-aws-to-google-cloud-light.svg?fit=max&auto=format&n=3qwgIru3kCfHriJC&q=85&s=2b8951e210551e65b14be12c82ad7d59" alt="AWS API requests pass through Tensor9 Cloud Adapter to Google Cloud services." width="1100" height="360" data-path="images/diagrams/cloud-adapter-quickstart-aws-to-google-cloud-light.svg" />
</Frame>

## What you will prove

| Boundary   | Test                                                                                    |
| ---------- | --------------------------------------------------------------------------------------- |
| Origin API | AWS CLI sends S3 `PutObject`, `HeadObject`, `GetObject`, and `DeleteObject`.            |
| Adaptation | Cloud Adapter translates S3 object behavior to Cloud Storage.                           |
| Target     | The object exists in the expected Google Cloud project and bucket with identical bytes. |
| Error path | A missing object returns an AWS-shaped not-found response with diagnostic context.      |

This test does not migrate existing objects, versions, bucket policies, or signed links.

## Before you begin

You need an installed AWS-origin Cloud Adapter endpoint, a configured S3 to Cloud Storage service adapter, an origin-side test identity, a Google Cloud runtime identity with access to one test bucket, AWS CLI v2, and `gcloud` for native verification.

Review [S3 on Google Cloud](/cloud-adapter/service-catalog/aws/databases-storage/s3#on-google-cloud). The core object lifecycle is supported. Multipart upload is composed through temporary objects; `ListMultipartUploads` and `UploadPartCopy` are outside this target profile. Bucket policy, ACL, retention, and legal-hold behavior are not provided by this object endpoint.

## Set test values

```bash theme={null}
export T9_CLOUD_ADAPTER_ENDPOINT="https://adapter.example.test"
export AWS_PROFILE="adapter-test"
export AWS_REGION="us-east-1"
export AWS_REQUEST_CHECKSUM_CALCULATION="WHEN_REQUIRED"
export ORIGIN_BUCKET="adapter-smoke-test"
export TARGET_BUCKET="adapter-smoke-test-gcs"
export TEST_KEY="quickstart/aws-gcp-$(date +%s).txt"
printf 'hello from S3 to Cloud Storage\n' > /tmp/cloud-adapter-smoke.txt
```

Use the origin-facing bucket name in AWS commands and the native bucket name in Google Cloud commands. They may differ.

`AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED` keeps this smoke test on the required S3 checksum path. Validate optional flexible-checksum behavior separately if your application enables it.

The commands below use an explicit `--endpoint-url`. To route every S3 client in the process instead, set `AWS_ENDPOINT_URL_S3="$T9_CLOUD_ADAPTER_ENDPOINT"` and omit the command-level override.

## Verify target access first

Confirm that your verification identity can see the target bucket without using Cloud Adapter:

```bash theme={null}
gcloud storage buckets describe "gs://$TARGET_BUCKET"
```

This is a read-only verification identity. The adapter's runtime identity is configured separately and should have only the target permissions needed by the mapped operations.

## Write through the S3 API

```bash theme={null}
aws s3api put-object \
  --bucket "$ORIGIN_BUCKET" \
  --key "$TEST_KEY" \
  --body /tmp/cloud-adapter-smoke.txt \
  --content-type text/plain \
  --metadata quickstart=aws-to-google-cloud \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"
```

Keep the ETag and command timestamp from the response. The normal AWS CLI output does not expose arbitrary response headers; use an SDK with structured, redacted response metadata when a support workflow requires them. Do not log authorization headers or request bodies.

## Read it through both sides

```bash theme={null}
aws s3api head-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION"

aws s3api get-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION" \
  /tmp/cloud-adapter-origin.txt

gcloud storage objects describe "gs://$TARGET_BUCKET/$TEST_KEY"
gcloud storage cat "gs://$TARGET_BUCKET/$TEST_KEY" > /tmp/cloud-adapter-target.txt

cmp /tmp/cloud-adapter-smoke.txt /tmp/cloud-adapter-origin.txt
cmp /tmp/cloud-adapter-smoke.txt /tmp/cloud-adapter-target.txt
```

The S3 ETag and Cloud Storage generation are not interchangeable identifiers. Use each API's returned identity in its own context.

## Exercise the error mapping

```bash theme={null}
aws s3api get-object \
  --bucket "$ORIGIN_BUCKET" \
  --key "quickstart/missing-object" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION" \
  /tmp/cloud-adapter-missing.txt
```

Expect an AWS-shaped not-found error. S3 can return permission denied instead when the caller lacks permission to establish that the object is missing. First separate that origin-side authorization case from the adapter's Google Cloud backend permission. If the request times out, inspect Cloud Storage before retrying a mutation.

## Clean up

```bash theme={null}
aws s3api delete-object \
  --bucket "$ORIGIN_BUCKET" --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" --profile "$AWS_PROFILE" --region "$AWS_REGION"

gcloud storage objects describe "gs://$TARGET_BUCKET/$TEST_KEY"
```

The final describe should report that the current object is no longer readable. Versioned or soft-delete-enabled targets can retain prior versions or recovery state; use an unversioned disposable target for this quickstart or remove the created version explicitly. Remove only the files and object created by this test; retain the shared bucket unless its owner authorizes deletion.

## Before production traffic

Inventory the application's S3 operations, conditional headers, pagination, metadata, multipart behavior, versioning, and retry policy. Test each documented operation with representative sizes. Plan data migration separately because a new target bucket starts empty. Establish target quotas, lifecycle policy, observability, backup, and an uncertain-write procedure.

Next, read the complete [S3 target profile](/cloud-adapter/service-catalog/aws/databases-storage/s3), then add the lifecycle to [CI/CD](/cloud-adapter/guides/ci-cd).
