3.6 KiB
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)
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
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 barenautilus.txtplaces it at the bucket root. (You could usesome/prefix/nautilus.txtto 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. Usesourcefor file uploads; the alternativecontent = "..."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.txtis edited later, theetagchanges 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
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.