3. Cloud Resume Challenge: Creating S3 Bucket

3. Cloud Resume Challenge: Creating S3 Bucket

In this module, you will create an S3 bucket that will store your web files. Later you will convert this bucket into a static-hosted website. Let's get started!


Terraform S3 Reference


Create a new branch in GitHub

  • Login to GitHub

  • Select the Issues tab > Select New Issue

  • Add the a title, e.g. Create S3 Bucket

  • Select Submit new issue

  • On the right pane, under Development, Select Create a branch

  • Leave the defaults > Select Create branch

  • Open your IDE Terminal.

  • Input the following:

git fetch origin
git checkout YOUR_BRANCH_NAME

Modifying s3 files

main.tf

  • In your IDE, you will start by modifying the ./infra/modules/aws/s3/main.tf

  • Input the following to create an s3 bucket resource

      resource "aws_s3_bucket" "bucket" {
        bucket        = var.bucket_name
    
        tags = {
          Name        = "${var.bucket_name}"
        }
      }
    

This will create a bucket with a name that will be defined at a later time. The purpose of utilizing variables is so that you can reuse this configuration file by supplying a bucket_name.

  • Save the file

variables.tf

  • For var.bucket_name to be available for use, you have to define what the variable type is, e.g. string, number, map, object, etc.

    • Input the following:

        variable "bucket_name" {
          description = "Given name of the S3 bucket"
          type        = string
        }
      

Utilizing the variable block you are defining the input variable for bucket_name. The expected input will be a string value, e.g. "myveryuniquelynamedbucket".

Note: S3 Bucket names must be globally unique.

  • Save the file

outputs.tf

  • The outputs.tf is utilized for return variables. You can use these as references for other modules to utilize. These can also be return values to the terminal.

  • Input the following for the S3 Bucket return values

      output "id" {
        description = "Name of the bucket."
        value = aws_s3_bucket.bucket.id
      }
    
      output "arn" {
        description = "ARN of the bucket. Will be of format arn:aws:s3:::bucketname"
        value = aws_s3_bucket.bucket.arn
      }
    
      output "bucket_domain_name" {
        description = "Bucket domain name. Will be of format bucketname.s3.amazonaws.com."
        value = aws_s3_bucket.bucket.bucket_domain_name
      }
    
      output "bucket_regional_domain_name" {
        description = "Regional Domain Name for S3 Bucket"
        value = aws_s3_bucket.bucket.bucket_regional_domain_name
      }
    

    Referencing the Terraform S3 reference, these are the valid outputs available for the S3 Bucket.

    • Save the file

At this point you have almost all you need to create an S3 Bucket. You would just have to define what the bucket_name is. However, in the next few sections I will be walking you through creating additional modules so that in the event you wanted to create another static s3 bucket website, or if you wanted to build a replica of the original architecture, you can utilize that same module by defining different input variables. Essentially future proofing so that you do not have rewrite the code to tie these resources together all over again.


Modifying s3_cloudfront_site files

In this section, you will prepare the S3 static website module. This will be the main module for creating the static hosting website configuration.

You will start with the main.tf in ./infra/modules/s3_cloudfront_site. This module will reference the ./infra/modules/aws/s3/main.tf resource.

main.tf

  • In the ./infra/modules/s3_cloudfront_site/main.tf, input the following:

      module "bucket" {
        source = "../aws/s3"
    
        bucket_name = var.bucket_name
      }
    

The module block references the child module in ../aws/s3. This is the relative path to the current main.tf you are configuring.

bucket_name = comes from the var.bucket_name in the s3/main.tf.
For consistency, you'll pass var.bucket_name from this module to the s3/main.tf's var.bucket_name. This way there is no confusion on where that variable is going.

  • Save the file

variables.tf

  • Much like the variables.tf in the s3 folder, you will have to define what the input variable type is for var.bucket_name.

    • In your ./infra/modules/s3_cloudfront_site/variables.tf, input the following:

        variable "bucket_name" {
          description = "Given name of the S3 bucket"
          type        = string
        }
      

  • Save the file

outputs.tf

  • Define the outputs for this module. Here, you will define the S3 Bucket resource's outputs from this module.

    • In your ./infra/modules/s3_cloudfront_site/outputs.tf, input the following:

        output "bucket_id" {
          description = "Name of the bucket."
          value = module.bucket.id
        }
      
        output "bucket_arn" {
          description = "ARN of the bucket. Will be of format arn:aws:s3:::bucketname"
          value = module.bucket.arn
        }
      
        output "bucket_domain_name" {
          description = "Bucket domain name. Will be of format bucketname.s3.amazonaws.com."
          value = module.bucket.bucket_domain_name
        }
      
        output "bucket_regional_domain_name" {
          description = "Regional Domain Name for S3 Bucket"
          value = module.bucket.bucket_regional_domain_name
        }
      

The output variable names are different here because in the future, there will be other resources that have id and arn values as well. To distinguish between where the value comes from it's good to give a unique identifier where the output is coming from.

Note the values for the output variables. They reference the module in the main.tf.

  • Save the file

Modifying my_portfolio files

main.tf

Similar to the s3_cloud_site module, you will modify the main, variables and outputs Terraform files. The my_portfolio module will be the main module to reference when tying all the associated services together, e.g. S3, CloudFront, DynamoDB, SNS, etc.

This module will reference the s3_cloudfront_site module to create the S3 bucket, and then later to create the CloudFront distribution.

  • In the ./infra/modules/my_portfolio/main.tf, input the following:

      module "static_website" {
        source = "../s3_cloudfront_site"
    
        bucket_name       = var.bucket_name
      }
    

Similar to the other main.tf files, you are passing the variable bucket name, and referencing the s3_cloudfront_site module.

  • Save the file

variables.tf

  • In your ./infra/modules/my_portfolio/variables.tf, input the following:

      variable "bucket_name" {
        description = "Given name of the S3 bucket"
        type        = string
      }
    

    • Save the file

outputs.tf

In your ./infra/modules/my_portfolio/outputs.tf, input the following:

output "bucket_id" {
  description = "Name of the bucket."
  value = module.static_website.bucket_id
}

output "bucket_arn" {
  description = "ARN of the bucket. Will be of format arn:aws:s3:::bucketname"
  value = module.static_website.bucket_arn
}

output "bucket_domain_name" {
  description = "Bucket domain name. Will be of format bucketname.s3.amazonaws.com."
  value = module.static_website.bucket_domain_name
}

output "bucket_regional_domain_name" {
  description = "Regional Domain Name for S3 Bucket"
  value = module.static_website.bucket_regional_domain_name
}

  • Save the file

Modifying /infra/main.tf

./infra/main.tf will be the module where all variables will be defined. This module will reference the my_portfolio module.

main.tf

  • In your ./infra/main.tf, input the following:

      module "my_static_website" {
        source = "./modules/my_portfolio"
    
        bucket_name = "Your_Unique_Bucket_Name"
      }
    

    • Save the file

Since bucket_name is hard coded, you do not have to modify the variables.tf

outputs.tf

  • If you would like to see the values for your resource output in the Terraform Cloud outputs, include the following:

      output "bucket_id" {
        description = "Name of the bucket."
        value = module.my_static_website.bucket_id
      }
    
      output "bucket_arn" {
        description = "ARN of the bucket. Will be of format arn:aws:s3:::bucketname"
        value = module.my_static_website.arn
      }
    
      output "bucket_domain_name" {
        description = "Bucket domain name. Will be of format bucketname.s3.amazonaws.com."
        value = module.my_static_website.bucket_domain_name
      }
    
      output "bucket_regional_domain_name" {
        description = "Regional Domain Name for S3 Bucket"
        value = module.my_static_website.bucket_regional_domain_name
      }
    

I'm not too concerned about receiving these outputs, so I will not include it in my configuration. The only required output for CloudFront Invalidation will be the CloudFront ID.


Modifying .yml files

  • Modify your terraform-plan.yml and terraform-apply_cloudfront-invalidation.yml

  • Uncomment the on: arguments in each


Pushing to GitHub

  • Ensure your files are saved.

  • In your IDE Terminal, type the following:

git add .

Add all files that were changed.


git commit -m "modified modules to create S3 bucket"

Commit the changes with a comment.

git push

Push to GitHub.


Create Pull Request

  • Login to GitHub.

  • You should see the push on your repository.

  • Select Compare and pull request.

  • Validate the changes that were made to be pushed to main

  • Select Create pull request.

Your Terraform Plan should run before you can merge to main.

  • Select Merge pull request > Confirm merge.

  • Delete branch.

  • In your IDE Terminal, type the following:

git checkout main
git pull

Validation:

  • There are 2 ways for validation:

  • AWS CLI:

      aws s3 ls
      michaelmaratita-static-website-tutorial
    
  • AWS Management Console:

    • In the Search bar, search for "s3" > Select "Buckets"


You have completed this section on creating an S3 bucket. In the next module, you will upload your site files to your S3 bucket.