All Products
Search
Document Center

Terraform:Module variables and outputs

Last Updated:Apr 22, 2025

This topic describes the usage of variables and outputs of Terraform modules.

Overview

Variables and outputs are the core components of the Terraform modules. They make modules reusable, flexible, and composable. Module variables allow you to customize the behavior of a module without modifying its source code. Output values enable the module to pass key information to its caller or other dependent modules. This parameterization and information transfer mechanism is the basis for building maintainable, extensible, and composable infrastructure code.

Variables provide flexibility for modules, allowing different configuration values to be used in different environments (such as development, test, and production environments), while maintaining the consistency of the infrastructure code. Terraform ensures the correctness and security of input data by using the variable type system and validation rules. Output values create communication channels between modules, allowing resource attributes (such as resource identifiers, connection strings, or network addresses) of one module to become input to another module, thereby establishing a dependency graph of the overall infrastructure.

Proper use of module variables and outputs is critical to creating standardized components that can be reused across regions and environments. For example, with parameterized network modules, security group modules, and compute resource modules, organizations can ensure that all teams consistently deploy infrastructure that meets enterprise standards. This topic describes the declarations, usage, and best practices of module variables and outputs, and uses examples to show how to apply these concepts in Alibaba Cloud infrastructure.

Module variables

In the examples so far, we have used hard-coded resource attributes. For example, in the main.tf file of the server module, the network name is hard-coded. If you use the same server module multiple times, you receive a name collision error when you run terraform plan or terraform apply.

In this case, we need to be able to flexibly configure different attribute values in different environments while maintaining standardization in other aspects. By using variables, we can customize aspects of the module without modifying the source code.

Importance of variables

Variables are especially useful when dealing with different environments, such as development, production, and staging environments. The best practice is to use smaller machine types in staging environments and larger machine types in production environments.

Use input variables to parameterize modules

Step 1: Replace hard-coded values

Replace hard-coded values in a module with variables. For example, to parameterize the network name:

# Original code
resource "alicloud_vpc" "main" {
  vpc_name = "my-vpc" # Hard-coded value
}
# Parameterized code
resource "alicloud_vpc" "main" {
  vpc_name=var.vpc_name# Use variables
}

Step 2: Declare variables

Declare the parameterized attributes in the variables.tf file. Make sure that the declared variables are placed in the same directory as the defined resources:

# variables.tf
variable "vpc_name" {
  description = "Name of the VPC"
  type = string
}

Step 3: Pass a value when you call a module

When calling a module, pass the variable value:

module "vpc_dev" {
  source = "./modules/vpc"
  vpc_name = "dev-vpc"
}
module "vpc_prod" {
  source = "./modules/vpc"
  vpc_name = "prod-vpc"
}

Note: Unlike the root configuration, you cannot pass values to module variables when Terraform is running.

Module output values

To pass a resource parameter from one module to another, you must configure the parameter as an output value.

Why do I need an output value?

  • To pass resource attributes between modules

  • To expose necessary resource information

  • To support dependencies between modules

Define and use output values

  1. Define output values in the source module

# modules/vpc/outputs.tf
output "vpc_id" {
  description = "ID of the created VPC"
  value       = alicloud_vpc.main.id
}

output "vswitch_ids" {
  description = "IDs of the created vswitches"
  value       = alicloud_vswitch.vswitches[*].id
}
  1. Use output values in the destination module

# modules/ecs/main.tf
module "vpc" {
  source = "../vpc"
}

resource "alicloud_instance" "example" {
  vswitch_id = module.vpc.vswitch_ids[0]
}

Example

  1. Communication between the network module and the server module

# modules/network/main.tf
resource "alicloud_vpc" "main" {
  vpc_name   = var.vpc_name
  cidr_block = var.vpc_cidr
}

# modules/network/outputs.tf
output "vpc_id" {
  value = alicloud_vpc.main.id
}

# modules/ecs/variables.tf
variable "vpc_id" {
  description = "ID of the VPC"
  type        = string
}

# root main.tf
module "network" {
  source = "./modules/network"
  
  vpc_name = "example-vpc"
  vpc_cidr = "172.16.0.0/16"
}

module "ecs" {
  source = "./modules/ecs"
  
  vpc_id = module.network.vpc_id
}
  1. Multi-environment configuration example

# environments/dev.tfvars
environment     = "dev"
instance_type   = "ecs.g6.small"
instance_count  = 1

# environments/prod.tfvars
environment     = "prod"
instance_type   = "ecs.g6.2xlarge"
instance_count  = 3

# Use different environment configurations
terraform apply -var-file="environments/dev.tfvars"

Best practices

  1. Variable design

    • Define variables for all available configuration items

    • Provide reasonable default values

    • Use variable validation to ensure valid inputs

    • Add clear variable descriptions

  2. Output design

    • Expose only the necessary output values

    • Provide descriptions for output values

    • Consider the requirements of downstream modules

  3. Environment management

    • Separate environments by using workspaces

    • Create special variable files for different environments

    • Use conditional expressions to handle environment differences

  4. Usage notes

    • You cannot input module variables when Terraform is running

    • You need to run terraform init after each module modification

    • Take note of type matching of variable values