How to use Modules in Terraform
Tags: terraform, cloud, cloudskills, cloudnative
Published: 2022-12-18 14:34:41

A module makes a set of resources reusable by wrapping it into a package that we can use in the context of different Terraform projects.

In essence, a module is a folder with one or multiple `*.tf` files that describe resources. There must be at least one `*.tf` file in the module, the so-called root module.

## Module Distribution

There are multiple ways to re-use Terraform from another system

- You have the module code checked out nearby, and reference the module directly
- The module is available in the Terraform Registry
- The module is available in a private registry
    - Github
    - Bitbucket
    - HTTP URLs
    - S3 Bucket
    - GCS buckets

### Referencing Modules from the File System

Here is an example of how we reference the `vpc` module in a Terraform project relative to the current directory.

```jsx
module "vpc" {
  source = "../vpc"
}
```

### Using Registry Modules

Using a module from a Terraform registry is quite the same than referencing a module on the local file system.

```jsx
module "vpc" {
	source = "terraform-aws-module"
	version = "3.14.0"
  # variable values can be passed here
}
```

This example refers to a module called `terraform-aws-module` . the biggest difference between local and registry modules is that registry modules are versioned, so you need to provide a version string.

### Hosting Modules in Github

You can reference a module from a GitHub repository by URL. This is convenient since most Terraform modules need to be stored in a version control system anyways.

You can checkout GitHub modules in two ways

- Through HTTPS
- Through SSH


```jsx
module "vpc" {
	source = "github.com/gdenn/my-vpc"
	# variables values go here
}
```

**Example SSH**

```jsx
module "vpc" {
	source = "git@github.com:gdenn/my-vpc.git"
	# variables values go here
}
```

You can reference your GitHub credentials in multiple ways

- `~/.ssh/config` set a `Host` entry and point to your `IdentiyFile` (SSH key)

```jsx
Host USERNAME.github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa
```

- Pass the credentials to the source parameter

```jsx
module "vpc" {
  source = "git::https://${git_username}:${git_password}@github.com/folder/terraform-azure-core-resource-group.git"
  ...
}
```

## Passing Variables

Every module can have a variables file that stores configurable config parameters that the resource scripts might use.

Values for the variables can be passed in the module block.

```jsx
module "vpc" {
  source = "../vpc"
  profile = var.profile
	region = "eu-central-1"
	...
}
```

You can still pass variables through the environment or use the default values.

## Provider Configuration

A module can inherit the provider config from the caller module (parent module). Although it is advisable to define a provider with a range of compliant versions.

```jsx
terraform {
  required_version = ">= 0.13.1"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.0"
    }
  }
}
```

Terraform will try to use a pre-installed provider version (e.g. used by another module or the parent) if it fits the version constrained by this child module.

In many cases, this might prevent the installation of an unnecessary additional provider and ensures that the module uses a provider this is compatible.