Bird
Raised Fist0
Terraformcloud~5 mins

Module structure and conventions in Terraform - Commands & Configuration

Choose your learning style10 modes available
Introduction
Terraform modules help organize and reuse infrastructure code. They solve the problem of repeating the same code by grouping resources into reusable units.
When you want to create a reusable set of infrastructure components like a network or server setup.
When you need to share infrastructure code across multiple projects or teams.
When you want to keep your Terraform code clean and easy to manage by splitting it into smaller parts.
When you want to version control infrastructure components separately.
When you want to test parts of your infrastructure independently before combining them.
Config File - main.tf
main.tf
variable "region" {
  description = "The cloud region to deploy resources"
  type        = string
  default     = "us-east-1"
}

resource "aws_s3_bucket" "example_bucket" {
  bucket = "example-terraform-module-bucket"
  acl    = "private"
  tags = {
    Name        = "ExampleBucket"
    Environment = "Dev"
  }
}

output "bucket_name" {
  description = "The name of the S3 bucket"
  value       = aws_s3_bucket.example_bucket.bucket
}

This file defines a simple Terraform module.

  • variable declares an input value for the module.
  • resource creates an AWS S3 bucket with a fixed name and tags.
  • output exposes the bucket name to whoever uses this module.
Commands
Initializes the Terraform working directory and downloads necessary provider plugins.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.0.0... - Installed hashicorp/aws v4.0.0 (signed by HashiCorp) Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work.
Checks the module files for syntax errors and validates the configuration is correct.
Terminal
terraform validate
Expected OutputExpected
Success! The configuration is valid.
Shows the changes Terraform will make to create the resources defined in the module.
Terminal
terraform plan
Expected OutputExpected
An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_s3_bucket.example_bucket will be created + resource "aws_s3_bucket" "example_bucket" { + acl = "private" + bucket = "example-terraform-module-bucket" + force_destroy = false + id = (known after apply) + tags = { + "Environment" = "Dev" + "Name" = "ExampleBucket" } } Plan: 1 to add, 0 to change, 0 to destroy.
Applies the planned changes to create the resources without asking for confirmation.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_s3_bucket.example_bucket: Creating... aws_s3_bucket.example_bucket: Creation complete after 2s [id=example-terraform-module-bucket] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
→
-auto-approve - Skips interactive approval before applying changes
Key Concept

If you remember nothing else from this pattern, remember: Terraform modules group related infrastructure code into reusable, easy-to-manage units.

Common Mistakes
Not including an output block to expose important resource attributes.
Without outputs, users of the module cannot access created resource details needed for integration.
Always define outputs for key resource attributes that other modules or configurations will need.
Hardcoding values inside the module instead of using variables.
Hardcoded values reduce reusability and flexibility of the module.
Use variables for values that may change between deployments and provide sensible defaults.
Not running 'terraform init' before other commands.
Terraform needs to download providers and initialize the working directory before planning or applying.
Always run 'terraform init' first when starting with a new or updated module.
Summary
Create a main.tf file defining variables, resources, and outputs for the module.
Run 'terraform init' to prepare the working directory and download providers.
Use 'terraform validate' to check for syntax and configuration errors.
Run 'terraform plan' to preview changes Terraform will make.
Apply changes with 'terraform apply -auto-approve' to create resources.

Practice

(1/5)
1. What is the main purpose of using a Terraform module?
easy
A. To group and reuse cloud resource configurations
B. To write scripts for cloud providers
C. To store cloud provider credentials
D. To monitor cloud resource usage

Solution

  1. Step 1: Understand module purpose

    Terraform modules are designed to group related cloud resources together for reuse and better organization.
  2. Step 2: Compare options

    Only To group and reuse cloud resource configurations correctly describes this purpose. Other options describe unrelated tasks.
  3. Final Answer:

    To group and reuse cloud resource configurations -> Option A
  4. Quick Check:

    Module purpose = reuse and grouping [OK]
Hint: Modules group resources for reuse and clarity [OK]
Common Mistakes:
  • Confusing modules with scripts
  • Thinking modules store credentials
  • Assuming modules monitor usage
2. Which of the following is the correct way to call a module named network located in a folder modules/network?
easy
A. module "network" { source = "modules/network" }
B. resource "network" { source = "modules/network" }
C. module network { path = "modules/network" }
D. resource "network" { path = "modules/network" }

Solution

  1. Step 1: Identify module call syntax

    Terraform uses module "name" { source = "path" } to call modules.
  2. Step 2: Check options

    Only module "network" { source = "modules/network" } uses correct module block and source attribute.
  3. Final Answer:

    module "network" { source = "modules/network" } -> Option A
  4. Quick Check:

    Module call uses module block and source [OK]
Hint: Use module block with source attribute for calling modules [OK]
Common Mistakes:
  • Using resource instead of module
  • Using path instead of source
  • Omitting quotes around module name
3. Given this module folder structure:
modules/
  webserver/
    main.tf
    variables.tf
    outputs.tf
What is the purpose of the variables.tf file inside the module?
medium
A. To declare output values from the module
B. To define input variables for the module
C. To write the main resource definitions
D. To store provider configurations

Solution

  1. Step 1: Understand file roles in module

    In Terraform modules, variables.tf defines input variables the module accepts.
  2. Step 2: Match options

    To define input variables for the module correctly states this. Outputs are in outputs.tf, main resources in main.tf, and provider configs are outside modules.
  3. Final Answer:

    To define input variables for the module -> Option B
  4. Quick Check:

    variables.tf = input variables [OK]
Hint: variables.tf defines inputs; outputs.tf defines outputs [OK]
Common Mistakes:
  • Confusing variables.tf with outputs.tf
  • Putting resource code in variables.tf
  • Adding provider config inside module
4. You wrote this module call:
module "db" {
  source = "modules/database"
  db_name = "prod"
}
But Terraform shows an error: "Unsupported argument: db_name". What is the likely cause?
medium
A. The source path is incorrect
B. Module names cannot contain underscores
C. The module does not declare an input variable named db_name
D. db_name should be declared inside main.tf

Solution

  1. Step 1: Understand error meaning

    "Unsupported argument" means the module does not expect the given input variable.
  2. Step 2: Check module inputs

    If db_name is not declared as a variable in the module's variables.tf, Terraform rejects it.
  3. Final Answer:

    The module does not declare an input variable named db_name -> Option C
  4. Quick Check:

    Input variables must be declared to be used [OK]
Hint: Declare input variables in module to avoid unsupported argument errors [OK]
Common Mistakes:
  • Assuming source path causes unsupported argument
  • Thinking module names restrict underscores
  • Trying to declare inputs inside main.tf
5. You want to create a reusable module for deploying a virtual machine with optional tags. Which structure correctly supports optional tags with a default empty map?
hard
A. In variables.tf: variable "tags" { type = list(string) }
B. In main.tf: variable "tags" { default = null }
C. In outputs.tf: output "tags" { value = var.tags }
D. In variables.tf: variable "tags" { type = map(string) default = {} }

Solution

  1. Step 1: Define optional input variable

    To make tags optional, define a variable with type map(string) and default empty map {}.
  2. Step 2: Evaluate options

    In variables.tf: variable "tags" { type = map(string) default = {} } correctly defines this in variables.tf. In main.tf: variable "tags" { default = null } lacks type and uses null default. In outputs.tf: output "tags" { value = var.tags } is output, not input. In variables.tf: variable "tags" { type = list(string) } uses list instead of map.
  3. Final Answer:

    In variables.tf: variable "tags" { type = map(string) default = {} } -> Option D
  4. Quick Check:

    Optional map variable needs default empty map [OK]
Hint: Use map(string) with default {} for optional tags [OK]
Common Mistakes:
  • Using list instead of map for tags
  • Not setting a default value
  • Declaring variables in outputs.tf
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard