- The OpenTofu Language
- Modules
- Module Blocks
Module Blocks
A module is a container for multiple resources that are used together.
Every OpenTofu configuration has at least one module, known as its
root module, which consists of the resources defined in the .tf and .tofu
files in the main working directory.
A module can call other modules, which lets you include the child module's resources into the configuration in a concise way. Modules can also be called multiple times, either within the same configuration or in separate configurations, allowing resource configurations to be packaged and re-used.
This page describes how to call one module from another. For more information about creating re-usable child modules, see Module Development.
Calling a Child Module​
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:
module "servers" {
source = "./app-cluster"
servers = 5
}
A module that includes a module block like this is the calling module of the
child module.
The label immediately after the module keyword is a local name, which the
calling module can use to refer to this instance of the module.
Within the block body (between { and }) are the arguments for the module.
Module calls use the following kinds of arguments:
-
The
sourceargument is mandatory for all modules. -
The
versionargument is recommended for modules from a registry. -
Most other arguments correspond to input variables defined by the module. (The
serversargument in the example above is one of these.) -
OpenTofu defines a few other meta-arguments that can be used with all modules, including
for_eachanddepends_on.
Source​
All modules require a source argument, which is a meta-argument defined by
OpenTofu. Its value is either the path to a local directory containing the
module's configuration files, or a remote module source that OpenTofu should
download and use. For more information on
possible values for this argument, see Module Sources.
The same source address can be specified in multiple module blocks to create
multiple copies of the resources defined within, possibly with different
variable values.
After adding, removing, or modifying module blocks, you must re-run
tofu init to allow OpenTofu the opportunity to adjust the installed
modules. By default this command will not upgrade an already-installed module;
use the -upgrade option to instead upgrade to the newest available version.
Version​
When using modules installed from a module registry, we recommend explicitly constraining the acceptable version numbers to avoid unexpected or unwanted changes.
Use the version argument in the module block to specify versions:
module "consul" {
source = "hashicorp/consul/aws"
version = "0.0.5"
servers = 3
}
The version argument accepts a version constraint string.
OpenTofu 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.
Version constraints are supported only for modules installed from a module
registry, such as the Public OpenTofu Registry
or any TACOS (TF Automation and Collaboration Software) private modules 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; since
they're loaded from the same source repository, they always share the same
version as their caller.
Meta-arguments​
Along with source and version, OpenTofu defines a few more
optional meta-arguments that have special meaning across all modules,
described in more detail in the following pages:
-
count- Creates multiple instances of a module from a singlemoduleblock. See thecountpage for details. -
for_each- Creates multiple instances of a module from a singlemoduleblock. See thefor_eachpage for details. -
providers- Passes provider configurations to a child module. See theproviderspage for details. If not specified, the child module inherits all of the default (un-aliased) provider configurations from the calling module. -
depends_on- Creates explicit dependencies between the entire module and the listed targets. See thedepends_onpage for details. -
lifecycle- Allows lifecycle customizations for modules, as described in Module Lifecycle below.
Module Lifecycle​
A lifecycle block inside a module block allows some customization of
OpenTofu's behavior relating to the overall module call, rather than to
individual resources inside the module.
module "example" {
# ...normal module call arguments...
lifecycle {
# ...lifecycle arguments...
}
}
Module call lifecycle currently supports only a single argument:
-
enabled(bool) - Controls whether the module call will be used by OpenTofu. When set tofalse, the content of the module is excluded from the configuration as if the call didn't exist. When set totrue(the default), the module operates normally.For more information, refer to the
enabledmeta-argument.
Accessing Module Output Values​
The resources defined in a module are encapsulated, so the calling module cannot access their attributes directly. However, the child module can declare output values to selectively export certain values to be accessed by the calling module.
For example, if the ./app-cluster module referenced in the example above
exported an output value named instance_ids then the calling module
can reference that result using the expression module.servers.instance_ids:
resource "aws_elb" "example" {
# ...
instances = module.servers.instance_ids
}
For more information about referring to named values, see Expressions.
Transferring Resource State Into Modules​
Moving resource blocks from one module into several child modules causes
OpenTofu to see the new location as an entirely different resource. As a
result, OpenTofu plans to destroy all resource instances at the old address
and create new instances at the new address.
To preserve existing objects, you can use refactoring blocks to record the old and new addresses for each resource instance. This directs OpenTofu to treat existing objects at the old addresses as if they had originally been created at the corresponding new addresses.
Replacing resources within a module​
You may have an object that needs to be replaced with a new object for a reason
that isn't automatically visible to OpenTofu, such as if a particular virtual
machine is running on degraded underlying hardware. In this case, you can use
the -replace=... planning option
to force OpenTofu to propose replacing that object.
If the object belongs to a resource within a nested module, specify the full path to that resource including all of the nested module steps leading to it. For example:
$ tofu plan -replace=module.example.aws_instance.example
The above selects a resource "aws_instance" "example" declared inside a
module "example" child module declared inside your root module.
Because replacing is a very disruptive action, OpenTofu only allows selecting individual resource instances. There is no syntax to force replacing all resource instances belonging to a particular module.
Removing a module​
The same as any resource, a module can be removed as well by using the removed refactoring block.
When you remove the configuration of a module, OpenTofu will destroy all the resources that the removed module was managing.
There are cases when the module is wanted to be removed from the configuration (and from the state) but the resources managed by it should stay untouched. To achieve this, follow these steps:
- Delete the module from your configuration.
- Add a removed block instead, specifying the module address you want to "forget" in the
fromattribute. - Specify the
lifecycle.destroy = false
removed {
from = module.some_module
lifecycle {
destroy = false
}
}
In contrast with resource blocks removal, removed blocks pointing to modules, do not allow usage of provisioners.