WintelGuy.com

Terraform Associate Exam Cram - Part 5

Interact with Terraform modules

This is Part 5 of the Terraform Associate Exam Cram. It covers the following Terraform Associate Certification exam objectives:

5a. Contrast and use different module source options including the public Terraform Registry

A Terraform module is a set of Terraform configuration files in a single directory. Every Terraform configuration has at least one module, known as its root module, which consists of the resources defined in the .tf files in the main working directory.

To call a module means to include the contents of that module into the configuration with specific values for its input variables. Modules are called from within other modules using module blocks. A module that includes a module block is the calling module of the child module.

module block configuration:

module "<MODULE_NAME>" { <module-specific-inputs> <module-meta-arguments> source = "<location-of-module-sources>" version = "<constraint>" # only available for modules listed in a registry providers = { <provider> = <provider>.<alias> } depends_on = [ <resource.address.reference> ] }
  • MODULE_NAME - The label immediately after the module keyword is the module's local name, which the calling module can use to refer to this instance of the module using the format module.<MODULE_NAME>.
  • source - Specifies where Terraform retrieves the module source code. One of the following options can be used:
    • Local path - use source = "<PATH-TO-MODULE>", where <PATH-TO-MODULE> is a relative (with ./ or ../ prefix) or absolute path to local module source code. For example: source = "./vpc".
    • Terraform Registry (public) - use source = "<NAMESPACE>/<NAME>/<PROVIDER>", e.g., source = "hashicorp/consul/aws".
    • Private Registry - use source = "<HOSTNAME>/<NAMESPACE>/<NAME>/<PROVIDER>", for example: source = "app.terraform.io/example_corp/vpc/aws".
    • GitHub repository - use source = "github.com/<ORGANIZATION>/<MODULE-FOLDER>" for GitHub over HTTPS, e.g., source = "github.com/org/repo/", or source = "git:github.com/<ORGANIZATION>/<MODULE-FOLDER>" for GitHub over SSH.
    • Git repository - use the git:: prefix followed by any valid Git URL, including the protocol.
    • Mercurial repository - use the hg:: prefix followed by a valid Mercurial URL.
    • Bitbucket - use an address with the bitbucket.org prefix.
    • HTTP URL - a valid URL, e.g., source = "https://example.com/module.zip".
    • S3 bucket - use the s3:: prefix followed by an S3 bucket object URL - source = "s3::https://s3.amazonaws.com/bucket/module.zip".
    • GCS bucket - use the gcs:: prefix followed by a GCS bucket object URL.
  • version - specifies which version of the module to use. This argument only applies when installing modules from a registry. The version argument accepts a version constraint string.

Whenever a new module is added to a configuration, Terraform must install the module before it can be used. Both the terraform get and terraform init commands will install and update modules. The terraform init command will also initialize backends and install plugins.

When installing a remote module, Terraform will download it into the .terraform directory in your configuration's root directory. Run terraform init after modifying the source argument or the version argument for a remote module.

When installing a local module, Terraform will instead refer directly to the source directory. Because of this, Terraform will automatically notice changes to local modules without having to re-run terraform init or terraform get.

Terraform Registry

The public Terraform Registry makes it simple to find and use modules. It is integrated directly into Terraform, so a Terraform configuration can refer to any module published in the registry.

The registry supports module versioning, automatically generates documentation, provides version histories, shows examples and READMEs, and more. It extracts information about the module from the module's source (Git and GitHub). The module name, provider, documentation, inputs/outputs, and dependencies are all parsed and available via the UI or API, as well as the same information for any submodules or examples in the module's source repository.

Back to Top

5b. Interact with module inputs and outputs

Similarly to the root module, child modules will define and use variables. Module's variables are used to supply input parameters and often called module's input variables.

Comparing Terraform modules to function definitions in traditional programming languages:

  • Input variables act as function arguments.
  • Output values are similar to function return values.
  • Local values are like a function's temporary local variables.

Inputs:

  • Defined with variable blocks inside a module:
# modules/vpc/vpc.tf variable "vpc_name" { type = string } variable "cidr_block" { type = string } variable "region" { type = string default = "us-east-1" }
  • Variables defined in the root module can be set with their values using CLI options and environment variables.
  • For variables declared in child modules, the calling module should pass values in the module block:
# main.tf module "vpc" { source = "./modules/vpc" vpc_name = "example_vpc" cidr_block = "10.0.0.0/16" }

Variables declared in modules that are not given a default value are required, and so must be set whenever the module is called (vpc_name and cidr_block in the example). Variables with a default value are optional and may be omitted in the module definition block (region in the example).

Outputs:

  • The resources defined in a module are encapsulated, so the calling module cannot access the child module's attributes directly. However, the child module can declare output values with output blocks to selectively export certain values to be accessed by the calling module:
output "vpc_id" { value = aws_vpc.main.id }
  • In a parent/root module, outputs of child modules can be referenced as module.<MODULE_NAME>.<OUTPUT_NAME>, e.g., network = module.vpc.vpc_id.

Back to Top

5c. Describe variable scope within modules/child modules

Variable scope rules:

  • Modules do not inherit variables form the parent module. Variables defined in a module are private and can not be directly used by other modules:
    • Child modules cannot directly access parent module's variables unless passed down.
    • Parent module cannot "see" child module's variables unless they are exposed as outputs.
  • Parent module supplies values to a child module's input variables using attributes in the module block.
  • Outputs are the only way to expose values from a child module.
  • Output values flow upward (from child to parent); variable values flow downward (from parent to child).

Back to Top

5d. Set module version

Use the version argument in the module block to specify version requirements. For example:

module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.0.0" }

Version - one or more version constraint conditions separated by commas: version = "<operator> <version>, ..."

  • = (or no operator): Exact version number. Cannot be combined with other conditions. For example: = 3.5.0
  • !=: Excludes an exact version number, e.g., != 3.5.0
  • >, >=, <, <=: Compares to a specified version, for example: >= 3.0
  • >= 3.0, <= 3.5: Defines version range
  • ~>: Allows only the right-most version component to increment, e.g., ~> 3.5 means >= 3.5.0 and < 4.0
  • A pre-release version is a version number that contains a suffix preceded by a dash 1.2.0-beta. Terraform does not match pre-release versions on >, >=, <, <=, or ~> operators

Version constraints are supported only for modules installed from a module registry, such as the public Terraform Registry or HCP Terraform's private module registry. Other module sources can provide their own versioning mechanisms within the source string itself, or might not support versions at all. In particular, modules sourced from local file paths do not support version.

Terraform will use the newest installed version of the module that meets the constraint. If no acceptable versions are installed, it will download the newest version that meets the constraint.

Back to Top

Practice Questions

What is a module in Terraform?
How can you define a reusable piece of configuration in Terraform?
Which syntax can be used to reference a specific module output?
In a module, how do you specify a variable with a default value?
What happens if a module is defined with source = path_to_local_module and the directory does not exist?
What is the purpose of the locals block in terraform?
How does variable assignment work between parent and child modules in Terraform?
Which Terraform feature allows you to split a complex configuration into smaller more manageable pieces?
How do you specify the version of a module in Terraform?
Which terraform feature allows you to define and use outputs from a module in other parts of your configuration?
How do you reference a resource attribute from a module in Terraform?
Which keyword is used to specify the block for a module call?
How do you specify that a resource should be created in one module before another resource in another module?
What information does the public Terraform Registry automatically expose about published modules?
In Terraform, if a child module defines a local value, can that local value be directly accessed from the parent module?
What sources can Terraform use to download modules?

Back to Top