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

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

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.