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