Files
kodekloud-engineer/terraform/task-34.md

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.