# Modules — Terraform

Source: https://www.skillbyai.com/en/terraform/m-modules

> Reusable building blocks.

## Inputs, resources, outputs

A **module** is a directory of Terraform files with input variables and outputs; every configuration is itself the root module. Calling a module with `module "name" { source = ... }` creates its resources under the address `module.name.`. Good modules have a focused purpose (a service, a network, a database with its alarms), a small set of well-documented inputs with sensible defaults, and outputs that callers need. Avoid thin wrappers around a single resource.

## A small module and two calls

The root module calls the same service module twice.

```hcl
# modules/service/main.tf
variable "name" { type = string }
variable "port" { type = number }

resource "local_file" "this" {
  filename = "${path.root}/out/${var.name}.env"
  content  = "SERVICE=${var.name}\nPORT=${var.port}\n"
}

output "path" {
  value = local_file.this.filename
}

# main.tf (root)
module "web" {
  source = "./modules/service"
  name   = "web"
  port   = 8080
}

module "api" {
  source = "./modules/service"
  name   = "api"
  port   = 3000
}

output "files" {
  value = [module.web.path, module.api.path]
}
```

## Applying the module calls, run

I ran this with Terraform 1.16.4 and the hashicorp/local 2.9.1 and hashicorp/random 3.9.1 providers, which manage local files and random values, so no cloud account was needed; each example starts from a fresh directory. Two module instances create two files; their resources appear in state under module.api and module.web.

```bash
terraform apply -auto-approve -no-color | tail -6
terraform state list
```

Output:

```
Outputs:

files = [
  "./out/web.env",
  "./out/api.env",
]
module.api.local_file.this
module.web.local_file.this
```

**Quiz:** What is the state address of the resource inside module "web"?

- [x] module.web.local_file.this
- [ ] local_file.web
- [ ] web.local_file
- [ ] module.local_file.web

*Answer:* module.web.local_file.this. Module resources are prefixed with module.<name>.
