Skip to content

Integrating Remote and Local State

Arnaud Lheureux edited this page Mar 16, 2022 · 12 revisions

The file that is responsible for merging the local and remote state is locals.combined_objects.tf. This guide comprises the Application section which shows how to use the combined object in a module and the Background section which shows

  1. Application
  2. Background

Application

This section covers the pattern on how to use the combined_object in the module.

First, understand the attributes provided by the resource_groups object. These attributes are:

  1. name
  2. location
  3. tags
  4. rbac_id
  5. id

Referencing attributes from the resource_groups object

For example, a module may require any combination of the id, tags, location, and name attributes. We opt to destructure the combined objects at the resource level. Example:

At the root level, pass in the entire combined object for resource groups

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 that specific resource, create a variables.tf that expects this resource_groups object

variable "resource_groups" {
}

Then destructure this variable in the resource's .tf file. In the example below, the resource_group_name and location are extracted from var.resource_groups

location = can(local.global_settings.regions[each.value.region]) ? local.global_settings.regions[each.value.region] : local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group.key, each.value.resource_group_key)].location

resource_group_name = can(each.value.resource_group.name) || can(each.value.resource_group_name) ? try(each.value.resource_group.name, each.value.resource_group_name) : local.combined_objects_resource_groups[try(each.value.resource_group.lz_key, local.client_config.landingzone_key)][try(each.value.resource_group_key, each.value.resource_group.key)].name

DO NOT USE!!!

The following example is an anti-pattern that causes resources to be redeployed when a resource of the same type is added or removed.

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

We use the combined_objects_resource_groups to illustrate how the local state is combined with the remote state to create the combined object.

locals.combined_objects.tf

The relevant snippet shows that combined_objects_resource_groups 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, {})
  )
}

resource_groups.tf

This module initialize the resource groups and stores the outputs in the locals. 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)
}

variables.tf

The remote objects is 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     = {}
}
Clone this wiki locally