Integrating Remote and Local State - ivaramme/terraform-azurerm-caf GitHub Wiki
What?
Part of the advantages behind the design of CAF is the to segregate and reuse components different landing zones or levels. These objects are persisted in tfstate
files inside the launchpad.
The combined_object
pattern provides a way to access objects of a certain resource type regardless of where they were created by merging local objects (to the current landing zone) with objects referenced in other landing zones (external .tfstate
files).
How does it work?
When the rover
command is invoked passing the command launchpad
or landingzone
, an entry point is expected as an argument using the -lz
flag, pointing to the location of the entry point folder.
One of such entry points available is the caf_solution
. This entry point enables the deployment of any configurations on Azure using the respective Azure CAF module and the retrieval of remote objects (persisted as tfstate
files).
This entry point module works as follows:
To reference objects that have been created elsewhere they have to be defined as part of the variable files. These files are loaded by the rover
into the caf_solution
entry point among with the variables.
The caf_solution
then get the remote tfstate
files and combine them based on their resource-type. The result of this process is exposed in the landing zone and injected into the Azure Cloud Adoption Framework Terraform module
Inside the Azure CAF Terraform module, the file locals.combined_objects.tf
is responsible of merging the local and remote states based on the resources types. It will then proceed with the creation of resources.
Example
This example shows how to use the combined object in a context of an example module. After that there's an explanation of how this data is accessible.
Application
To use the combined_object
pattern in this example module, first, lets understand the attributes provided inside the resource_groups
object. These attributes are:
- name
- location
- tags
- rbac_id
- id
resource_groups
object
Referencing attributes from the For example, a module may require any combination of the id
, tags
, location
, and name
attributes. We opt to de-structure the combined objects at the resource level by passing the combined object local.combined_objects_resource_groups
at the root level as the value for the resource_groups
variable:
module "example" {
source = "./modules/some_module/example"
for_each = local.some_module.example
client_config = local.client_config
global_settings = local.global_settings
name = each.value.name
resource_groups = local.combined_objects_resource_groups
settings = each.value
}
Then in the modules
directory, for this specific resource, create a variables.tf
that expects this resource_groups
object
variable "resource_groups" {
}
Then de-structure this variable in the resource's .tf
file. In the example below, the resource_group_name
and location
are extracted from var.resource_groups
resource_group_name = coalesce(
try(var.resource_groups[var.settings.resource_group.lz_key][var.settings.resource_group.key].name, null),
try(var.resource_groups[var.client_config.landingzone_key][var.settings.resource_group.key].name, null),
try(var.resource_groups[var.settings.resource_group.lz_key][var.settings.resource_group_key].name, null),
try(var.resource_groups[var.client_config.landingzone_key][var.settings.resource_group_key].name, null),
)
location = coalesce(
try(var.resource_groups[var.settings.resource_group.lz_key][var.settings.resource_group.key].location, null),
try(var.resource_groups[var.client_config.landingzone_key][var.settings.resource_group.key].location, null),
try(var.resource_groups[var.settings.resource_group.lz_key][var.settings.resource_group_key].location, null),
try(var.resource_groups[var.client_config.landingzone_key][var.settings.resource_group_key].location, null),
)
Background
To use the combined_object
pattern in this example, we'll inspect three files and discover how the local state is combined with the remote state. These files are located in the root directory of the repository.
locals.combined_objects.tf
Combined objects located in Inside locals.combined_objects.tf
you can find all the combined objects for each resource type that are available.
For the context of this example, the relevant snippet defines combined_objects_resource_groups
and merges the local state that comes from local.resource_groups
with the remote state that comes from var.remote_objects.resource_groups
.
locals {
combined_objects_resource_groups = merge(
tomap({
(local.client_config.landingzone_key) = local.resource_groups
}),
try(var.remote_objects.resource_groups, {})
)
}
variables.tf
Remote Objects located in The remote objects is defined and initialized here. This is how locals.combined_objects.tf
can reference the remote resource groups by using var.remote_objects.resource_groups
. This variable has its values injected behind the scenes by the caf_launchpad
or landing zone.
variable "remote_objects" {
description = "Remote objects is used to allow the landing zone to retrieve remote tfstate objects and pass them to the caf module"
default = {}
}
resource_groups.tf
Local Objects located in This module initializes the resource groups and stores the outputs in the locals
namespace. This is how locals.combined_objects.tf
can reference the local resource groups by using local.resource_groups
.
locals {
resource_groups = merge(module.resource_groups, module.resource_group_reused)
}