89 lines
3.6 KiB
Markdown
89 lines
3.6 KiB
Markdown
# Assignment
|
|
|
|
The Nautilus DevOps team is presently immersed in data migrations, transferring data from on-premise storage systems to AWS S3 buckets. They have recently received some data that they intend to copy to one of the S3 buckets.
|
|
|
|
S3 bucket named nautilus-cp-32671 already exists. Copy the file /tmp/nautilus.txt to s3 bucket nautilus-cp-32671 using Terraform. The Terraform working directory is /home/bob/terraform. Update the main.tf file (do not create a separate .tf file) to accomplish this task.
|
|
|
|
Note: Right-click under the EXPLORER section in VS Code and select Open in Integrated Terminal to launch the terminal.
|
|
|
|
# Solution
|
|
|
|
# Upload File to S3 — `/tmp/nautilus.txt` → `nautilus-cp-32671`
|
|
|
|
The bucket (`aws_s3_bucket.my_bucket`) already exists in this `main.tf`. Uploading a
|
|
file is a native Terraform operation via the `aws_s3_object` resource — no CLI needed.
|
|
Append one block.
|
|
|
|
## `main.tf` (append this block; leave the existing bucket unchanged)
|
|
|
|
```hcl
|
|
resource "aws_s3_bucket" "my_bucket" {
|
|
bucket = "nautilus-cp-32671"
|
|
acl = "private"
|
|
|
|
tags = {
|
|
Name = "nautilus-cp-32671"
|
|
}
|
|
}
|
|
|
|
# Upload the local file into the bucket
|
|
resource "aws_s3_object" "nautilus_file" {
|
|
bucket = aws_s3_bucket.my_bucket.id
|
|
key = "nautilus.txt"
|
|
source = "/tmp/nautilus.txt"
|
|
etag = filemd5("/tmp/nautilus.txt")
|
|
}
|
|
```
|
|
|
|
## How to run
|
|
|
|
```bash
|
|
cd /home/bob/terraform
|
|
terraform plan # should show only the new aws_s3_object to add
|
|
terraform apply -auto-approve
|
|
```
|
|
|
|
## How it works
|
|
|
|
### `aws_s3_object`
|
|
|
|
This resource represents a single object (a file) stored in an S3 bucket. It's the
|
|
idiomatic, native way to put a file into S3 with Terraform — the `aws_s3_object` name
|
|
is the current one (it replaced the older `aws_s3_bucket_object`, which still works but
|
|
is deprecated).
|
|
|
|
- **`bucket = aws_s3_bucket.my_bucket.id`** — the target bucket, referenced by
|
|
attribute rather than hardcoded. This creates an **implicit dependency** so
|
|
Terraform ensures the bucket exists before uploading, and the plan shows only the
|
|
new object being added.
|
|
- **`key = "nautilus.txt"`** — the object key, i.e. its name/path *inside* the bucket.
|
|
A bare `nautilus.txt` places it at the bucket root. (You could use
|
|
`some/prefix/nautilus.txt` to nest it under a "folder".)
|
|
- **`source = "/tmp/nautilus.txt"`** — the path to the local file on the machine
|
|
running Terraform. Terraform reads this file and uploads its bytes. Use `source` for
|
|
file uploads; the alternative `content = "..."` is for inline string data instead of
|
|
a file.
|
|
- **`etag = filemd5("/tmp/nautilus.txt")`** — the MD5 of the local file. S3 stores an
|
|
object's ETag as its MD5, so wiring this lets Terraform detect **content changes**:
|
|
if `/tmp/nautilus.txt` is edited later, the `etag` changes and Terraform will
|
|
re-upload on the next apply. Without it, Terraform only tracks the object's
|
|
existence, not its contents.
|
|
|
|
### Why native resource over CLI
|
|
|
|
Some tasks require shelling out to the AWS CLI (e.g. syncing a whole bucket or a
|
|
force-delete). A single-file upload isn't one of them — `aws_s3_object` handles it
|
|
declaratively, tracks the object in state, and gives clean create/update/delete
|
|
lifecycle management. Reaching for `null_resource` + `local-exec` here would be
|
|
unnecessary and would put the upload outside Terraform's state tracking.
|
|
|
|
## Verify
|
|
|
|
```bash
|
|
aws s3 ls s3://nautilus-cp-32671/
|
|
|
|
aws s3api head-object --bucket nautilus-cp-32671 --key nautilus.txt \
|
|
--query '{Key:`nautilus.txt`,Size:ContentLength,ETag:ETag}'
|
|
```
|
|
|
|
Expected — `nautilus.txt` listed in the bucket, with a size matching the local file. |