How to create a Terraform module
In this article, we will see how to create reusable modules in Terraform. Modules allow us to avoid code duplication. It means the same code can be used to create resources of the same type. By using modules you do not need to copy-paste your code to create multiple resources of the same type.
For example, you can put the code inside a Terraform module and reuse that module in the staging and production environments, in this way we will be able to have both environments reuse the same code from the same module instead of writing the code multiple times.
In this article, we will write a module for creating an S3 Bucket as an example.
Pre-requisites
- Basic understanding of Terraform.
- Terraform installed on your system.
- AWS Account (Create if you don’t have one).
- 'access_key' & 'secret_key' of an AWS IAM User. (Click here to learn to create an IAM user with 'access_key' & 'secret_key' on AWS, )
What we will do
- Write our own module
- Create an S3 bucket using the Terraform Module.
- Delete the created resource using Terraform Module.
Write our own Terraform module
Create a dedicated directory where you can have your terraform "main.tf" file and a module.
Use the following command to create a directory
mkdir -p modules/aws-s3
Create a main.tf file under modules/aws-s3 and copy paste the following block of code which will be used as a module to create an S3 Bucket.
vim modules/aws-s3/main.tf
resource "aws_s3_bucket" "s3_bucket" {
bucket = var.bucket_name
acl = "public-read"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::${var.bucket_name}/*"
]
}
]
}
EOF
website {
index_document = "index.html"
error_document = "error.html"
}
tags = var.tags
}
Declare the required variable in "modules/aws-s3/variables.tf". If you want you can specify the default values to the variables. Copy paste the following block of code to create the file.
vim modules/aws-s3/variables.tf
variable "bucket_name" { description = "Name of the s3 bucket. Must be unique." type = string } variable "tags" { description = "Tags to set on the bucket." type = map(string) default = {} }
Now, create the "main.tf" file which will call the module we defined in the above step. To call a module means to include the contents of that module into the configuration with specific values for its variable. Modules are called from within other modules using module
blocks:
vim main.tf
provider "aws" {
region = "${var.region}"
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
}
module "website_s3_bucket" {
source = "./modules/aws-s3"
bucket_name = "${var.bucket_name}"
tags = {
Terraform = "true"
Environment = "dev"
}
}
All modules require a source argument. Its value is either the path to a local directory of the module's configuration files, or a remote module source that Terraform should download and use.
The same source address can be specified in multiple module blocks to create multiple copies of the resources defined within, possibly with different variable values.
Create "variables.tf" which will contain the definition of variables. This will hold the default values which need to be passed to the module along with AWS "access_key" and "secret_key".
vim variables.tf
variable "access_key" { description = "Access key to AWS console" } variable "secret_key" { description = "Secret key to AWS console" } variable "region" { description = "Region of AWS VPC" } variable "bucket_name" { description = "(Required) Creates a unique bucket name" type = "string" default = "test-bucket-rahul-delete" }
Now create "terraform.tfvars" which will hold the AWS User Credentials. The following keys need to be changed with the keys of your IAM user. Before specifying these keys, you need to create them from the AWS Console and do not share these keys with anyone.
vim terraform.tfvars
region = "eu-west-3" access_key = "AKIAQ6GAIA5XX54GLLNG" secret_key = "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"
Create an S3 bucket using the Terraform Module
Before you execute the following commands make sure you have configured the valid access_key and secret_key.
The first command to be used is 'terraform init'. This command downloads and installs plugins for providers used within the configuration. In our case it is AWS.
terraform init
The second command to be used is 'terraform plan'. This command is used to see the changes that will take place on the infrastructure.
terraform plan
'terraform apply' command will create the resources on the AWS mentioned in the main.tf file. You will be prompted to provide your input to create the resources.
terraform apply
When you execute the above command, upon successful completion, you can see that 1 new resource has been added and 0 has been destroyed.
You can go to the AWS S3 console to verify if the S3 Bucket is created or not.
Delete the created S3 Bucket using Terraform
If you no longer require a resource you created using the configuration mentioned in the main.tf file, You can use the "terraform destroy" command to delete all those resources. Here, the S3 bucket will get deleted upon executing the following command.
terraform destroy
Conclusion
In this article, we saw the steps to write our own module and create an S3 bucket using it. Now the same module can be used to create multiple S3 Buckets, to do so we just need to change the values of variables and reuse the same module.