Terraform

Terraform, OpenTofu and Terragrunt files share one language.

[languages.terraform]      # off unless the table is written
include = ["**/*.tf", "**/*.tofu", "**/terragrunt.hcl"]   # the default
ignore_unresolved = ["../../shared/*"]   # module sources not to warn about
registries = ["terraform-mirror.acme.com"]   # mirrors of the public registry
repository_hosts = ["*.ghe.acme.com"]        # read like github.com
bucket_hosts = ["minio.acme.com"]            # read like S3
Option
includeGlobs of the files to scan. A .hcl file that it matches is read as a Terragrunt file.
ignore_unresolvedName patterns of the module sources and dependency paths that are expected not to resolve, so are not reported as unresolved.
registriesName patterns of hosts that serve the public registry's modules, such as a mirror, whose modules are named as the public registry's are.
repository_hostsName patterns of hosts of repositories that module sources name without a scheme, as they name GitHub's, such as a GitHub Enterprise server.
bucket_hostsName patterns of hosts of buckets that module sources name without a scheme, as they name S3's.

Each host option adds to the public hosts: the public registries, github.com and bitbucket.org, and S3 (*.amazonaws.com) and GCS (www.googleapis.com). Hosts are matched in lowercase.

The .terraform and .terragrunt-cache directories, where Terraform and Terragrunt keep the modules they download, are never scanned.

Packages

Terraform has no manifest that names a package, so its projects have no packages, and pkg: selects none of their directories. Name a module by its directory instead, such as modules/vpc.

Imports

A module is a directory, so an import of a module of the project is an import of its directory, which is one node of the graph, and a contract names modules/vpc and not the files in it. Every import is a value import, and is located by its string:

FileImport
.tf, .tofuThe source of each module block.
terragrunt.hclThe source of the terraform block, the config_path of each dependency block, and each of the paths of the dependencies block.

A value made from an expression, such as "${get_repo_root()}/modules/vpc" or local.source, can't be read without evaluating it, so it is left out of the graph. include blocks and the other attributes of a block are not imports.

zenith-ignore comments are #, // or /* */ comments. One on the line where a block or an attribute starts, or on the line above it, applies to every import in it:

# zenith-ignore stacks-independent: shares the production database until the split
module "database" {
  source = "../prod"
}

Resolution

ImportedNode
a local path, such as ../../modules/vpcmodules/vpcThe directory it leads to from the importing file's directory, which must be in the project. A // before a subdirectory, as in ../modules//vpc, leads to the subdirectory.
a registry module, such as hashicorp/consul/awstfmod:hashicorp/consul/awsNamed by its namespace, name and target system. A private registry's hostname stays in front, as in tfmod:app.terraform.io/acme/vpc/aws, unless registries names it as a mirror of the public one. Terragrunt's tfr:// addresses are read the same.
a repository, a bucket or an archive, such as git::https://github.com/acme/modules.git//vpc?ref=v1.2.0tfmod:github.com/acme/modulesNamed by its host and path, without the getter, scheme, credentials, port, .git, subdirectory or query. On GitHub, Bitbucket and the repository_hosts, written without a scheme, the repository is the first two segments of the path, so github.com/acme/modules/vpc is tfmod:github.com/acme/modules too.

Registry names and hostnames ignore case, so both are in lowercase.

Each file resolves as its tool reads it:

  • In a Terraform file, as Terraform requires, a local path starts with ./ or ../, so modules/vpc is not a module source, and is reported as unresolved. Anything else that is not a repository is a registry address.
  • In a Terragrunt file, a registry module is written with tfr://, and anything else that is not a repository is a local path, so config_path = "vpc" is the directory vpc next to the file.