You are on page 1of 60

Cisco Education Series

Automate your DC Network using Terraform

Alejandro de Alda
Technical Marketing Engineer - CNBU
May, 2022
• What is Terraform?
• Terraform Building Blocks
• Provider
• Resources

Agenda •


Variables
Loops & Conditionals
• Data Sources

• Running your plan


• Infrastructure State

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 2
What is Terraform?

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 6
• Infrastructure Provisioning Tool
• Open Source
• Commercial support available
What is Terraform? • Declarative and idempotent
• Immutable Infrastructure paradigm
• Versatile: Can manage a wide range
of systems
• VMs, network devices, cloud instances,
etc.
• Zero server-side dependencies

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 7
Ansible or Terraform?
• Both Ansible and Terraform can coexist
• It’s not an either/or story
• Terraform can call Ansible for ad-hoc tasks after deploying a VM
• Terraform keeps state locally
• It knows what is configured vs desired end-state
• Can automatically destroy / recreate resources
• Ansible mutate the infrastructure
• Need to re-run everything
• Might need to create advanced controls to avoid long running scripts

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 8
Declarative vs. Imperative
• Define what the eventual target • Define how the infrastructure
configuration should be should be changed
• e.g., 1 Tenant with 2 BDs and 2 EPGs • e.g., Add BD X and EPG Y
• Define the desired state • Automate a common use case (e.g.,
add a network segment)
• Automation is responsible for the
desired state to be reflected in the • Automation defines steps
infrastructure (workflow) to end with the desired
conclusion

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 9
Terraform Building Blocks

Variables
Modules
Resources
Provisioners
...
Providers

HCL

Resources Execution
Plan REST

terraform.bin

Data Sources

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 10
Installing Terraform For Reference

• Terraform is shipped as a single binary file


• No dependencies, straight forward installation
• Download terraform from: https://www.terraform.io/downloads.html
• Unzip and move the executable to any directory that is part of your PATH
• i.e. /usr/local/bin
• Run terraform
ADEALDAG-M-D1S4:~ adealdag$ terraform --version
If you want to keep multiple
Terraform v0.15.5
on darwin_amd64 versions of terraform and
switch between them, there are
tools available for it
• Upgrade process is equivalent (i.e. tfenv, tfswitch)

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 11
Terraform Workflow

Write Init Plan Apply Destroy?

Write your code Calculate required changes Remove all resources

Download and initialize environment Apply changes into


(providers, modules, backend, ...) real infrastructure

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 12
Terraform Building Blocks

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 13
Provider

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 14
Terraform Providers
Overview

• Terraform relies on plugins called "providers" to interact with remote


systems
• Required providers must be declared so Terraform can install and use them
• Each provider adds a set of resource types and/or data sources that
Terraform can manage
• Terraform Registry is the main directory of publicly available providers

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 15
Terraform Providers
Cisco Providers

Data Center
ACI Multi Site DNA Center Intersight
Cloud / Onprem
Network
Orchestrator
Manager

For Cisco ACI: https://registry.terraform.io/providers/CiscoDevNet/aci/latest

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 16
Terraform Cisco ACI Provider
Declaring and configuring provider

terraform {
required_providers { Required starting from
aci = { terraform 0.13
source = "ciscodevnet/aci"
version = "0.7.0"
}
}
} If login domain is used,
username would be:
provider "aci" { “apic:demo_domain\\\\user”
username = ”admin"
password = ”password”
# private_key = ”/Users/adealdag/.ssh/labadmin.key" Authentication supported using
# cert_name = "labadmin.crt" username/password or
url = ”https://apic-ams.cisco.com” certificates (recommended)
insecure = true
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 17
Terraform Cisco ACI Provider
Initialization

ADEALDAG-M-D1S4:tfdemo01 adealdag$ terraform init

Initializing the backend... We are using ACI provider


version 0.6.0 in this example
Initializing provider plugins...
- Finding ciscodevnet/aci versions matching "0.6.0"...
- Installing ciscodevnet/aci v0.6.0...
- Installed ciscodevnet/aci v0.6.0 (signed by a HashiCorp partner, key ID 433649E2C56309DE)

Partner and community providers are signed by their developers.


If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html terraform {
required_providers {
Terraform has created a lock file .terraform.lock.hcl to record the provider
aci = {
selections it made above. Include this file in your version control repository
source = "ciscodevnet/aci"
so that Terraform can guarantee to make the same selections by default when
version = "0.6.0"
you run "terraform init" in the future. }
}
Terraform has been successfully initialized! }

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 18
Terraform Cisco ACI Provider
Upgrade

• Upgrade providers using: terraform {


required_providers {
$ terraform init -upgrade aci = {
source = "ciscodevnet/aci"
ADEALDAG-M-D1S4:demo01 adealdag$ terraform init version = "0.7.0"
}
Initializing the backend... }
}
Upgrade to 0.7.0
Initializing provider plugins...
- Reusing previous version of ciscodevnet/aci from the dependency lock file

│ Error: Failed to query available provider packages

│ Could not retrieve the list of available versions for provider ciscodevnet/aci: locked provider
│ registry.terraform.io/ciscodevnet/aci 0.6.0
│ does not match configured version constraint 0.7.0; If option –upgrade is
│ must use terraform init -upgrade to allow selection of new versions
missing, init fails

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 19
Terraform Cisco ACI Provider
Upgrade

• Upgrade providers using: terraform {


required_providers {
$ terraform init -upgrade aci = {
source = "ciscodevnet/aci"
ADEALDAG-M-D1S4:demo01 adealdag$ terraform init -upgrade version = "0.7.0"
}
Initializing the backend... }
}
Upgrade to 0.7.0
Initializing provider plugins...
- Finding ciscodevnet/aci versions matching "0.7.0"...
- Installing ciscodevnet/aci v0.7.0...
- Installed ciscodevnet/aci v0.7.0 (signed by a HashiCorp partner, key ID 433649E2C56309DE)

[...]

Terraform has been successfully initialized!

[...]

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 20
Resources

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 21
Terraform Resources
Overview

• A resource describe one or more infrastructure object


• In ACI, a resource describes one ACI object
• Adding a resource in the execution plan means that the resource must be
present in the infrastructure:
• Terraform will create/modify the object if needed
• Terraform will remove the object if removed from plan (or if the plan is destroyed)

• Resources may point to other resources


• i.e. aci_vrf has a reference to aci_tenant

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 22
Terraform Resources
Documentation

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 23
Terraform Resources
Building our first execution plan

Resource type Resource name

resource "aci_tenant" "demo" {


name = "demo_tn"
description = "This is a demo tenant created from Terraform"
}

resource "aci_vrf" "main" {


Reference to the parent tenant
tenant_dn = aci_tenant.demo.id id (=dn)
name = "main_vrf"
}

resource "aci_bridge_domain" ”bd_192_168_1_0" {


tenant_dn = aci_tenant.demo.id
name = "192.168.1.0_24_bd"
arp_flood = "yes" Bridge domains have a reference
unicast_route = "yes"
unk_mac_ucast_act = "proxy"
to the vrf (fvCtx) they are
unk_mcast_act = "flood" attached to
relation_fv_rs_ctx = aci_vrf.main.id
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 24
Variables

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 25
Variables
Overview

• Variables help making the code re-usable and shareable


• Values are no longer hard-coded in execution plan
• Variables are defined in a separated file and replaced when needed

• In Terraform, variables may have:


• a type: string, number, bool, list, set, map, object, tuple
• a description
• a default value
• validation rules
• sensitive flag: hide value in outputs

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 26
Variables
Definition

# Variables file (variables.tf)


# -- If no default value is specified,
Variable's definition
variable "tenant_name" { Default value if not and no value set afterwards,
default = "demo_tn" overridden anywhere Terraform will prompt user for
} the value
variable "vrf_name" { Variable value can be set or
default = "main_vrf" overridden in different ways
}
(more on this later)
variable "bd_name" {
default = "net01_bd"
} Validation rule
variable "bd_arp_flood" { │
description = "Specify whether ARP flooding is enabled" │ Error: Invalid value for variable
default = "yes" │
│ on variables.tf line 16:
validation {
│ 16: variable "bd_arp_flood" {
condition = (var.bd_arp_flood == "yes") || (var.bd_arp_flood == "no") │
error_message = "Allowed values are \"yes\" and \"no\”." │ Allowed values are "yes" and "no".
} │
} │ This was checked by the validation rule at
│ variables.tf:19,3-13.
© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential ╵ 27
Variables
Using defined variables
Variable interpolation syntax
resource "aci_tenant" "demo" { until 0.12
name = "${var.tenant_name}" Still used in some cases, such
description = "This is a demo tenant created from Terraform" as:
}
"my_${var.tenant_name}"
resource "aci_vrf" "main" {
tenant_dn = aci_tenant.demo.id
name = var.vrf_name
}

resource "aci_bridge_domain" "bd_192_168_1_0" {


tenant_dn = aci_tenant.demo.id
name = var.bd_name Variable interpolation syntax
arp_flood = var.bd_arp_flood starting from 0.13
unicast_route = var.bd_unicast_routing
unk_mac_ucast_act = var.bd_unk_ucast
unk_mcast_act = "flood"
relation_fv_rs_ctx = aci_vrf.main.id
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 28
Variables
Assigning variable values

• Different options available: # Variable definition file (myvars.tfvars)


# --
• In Terraform Cloud workspace*
tenant_name = "demo_prod_tn"
• Individually, with –var option vrf_name = "prod_vrf"
bd_name = "192.168.1.0_24_bd"
• In a variable definitions file (.tfvars), bd_arp_flood = ”yes"
specified with –var-file option bd_unicast_routing = "yes"
bd_unk_ucast = "proxy"
• In an automatically loaded variable
definitions file (.auto.tfvars),
To use this variable file, run as follows:
• As environment variables
$ terraform apply -var-file myvars.tfvars

Check Variable Definition Precedence

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 29
Loops

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 30
Terraform Loops
Count

resource "aci_tenant" "demo" {


name = "demo_tn"
description = "This is a demo tenant created from Terraform"
}

resource "aci_vrf" "main" {


tenant_dn = aci_tenant.demo.id
name = "main_vrf"
}

resource "aci_bridge_domain" ”bd_192_168_1_0" {


count = 10 Creates <count> resources
tenant_dn = aci_tenant.demo.id
name = "bd_${count.index}"
arp_flood = "yes" Index can be accessed as
unicast_route = "yes" count.index
unk_mac_ucast_act = "proxy"
unk_mcast_act = "flood"
relation_fv_rs_ctx = aci_vrf.main.id
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 31
Terraform Loops
Count

resource "aci_tenant" "demo" {


name = "demo_tn"
description = "This is a demo tenant created from Terraform"
}

resource "aci_vrf" "main" {


tenant_dn = aci_tenant.demo.id
name = "main_vrf"
}

resource "aci_bridge_domain" ”bd_192_168_1_0" {


count = 10 Creates <count> resources
tenant_dn = aci_tenant.demo.id
name = "${format("bd_%03d", count.index + 1)}"
arp_flood = "yes"
Index can be accessed as
unicast_route = "yes" count.index
unk_mac_ucast_act = "proxy"
unk_mcast_act = "flood" format can be used to further
relation_fv_rs_ctx = aci_vrf.main.id
} format the text

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 32
Terraform Loops
For_each

resource "aci_tenant" "demo" {


name = "${var.tenant_name}"
description = "This is a demo tenant created from Terraform"
}

resource "aci_vrf" "main" {


tenant_dn = aci_tenant.demo.id
name = var.vrf_name
}

resource "aci_bridge_domain" "bd" { Creates one instance of this


for_each = var.bridge_domains
resource for each element Only supported with map or set
tenant_dn = aci_tenant.demo.id (or list, using toset)
name = each.value.name
arp_flood = each.value.arp_flood
unicast_route = each.value.unicast_routing
unk_mac_ucast_act = each.value.unk_ucast
unk_mcast_act = "flood" Access the key and value of each element
relation_fv_rs_ctx = aci_vrf.main.id using each.key or each.value
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 33
Terraform Loops
For_each - Variable Definition

# Variables file # Variable definition file (myvars.tfvars)


# -- # --

[...] tenant_name = "demo_prod_tn"


vrf_name = "prod_vrf”
variable "bridge_domains" {
type = map(object({ bridge_domains = {
name = string bd01 = {
arp_flood = string name = "192.168.1.0_24_bd"
unicast_routing = string arp_flood = "yes"
unk_ucast = string unicast_routing = "yes"
})) unk_ucast = "proxy"
default = { },
default_bd = { bd02 = {
name = "default" name = "192.168.2.0_24_bd"
arp_flood = "yes" arp_flood = "yes"
unicast_routing = "yes" unicast_routing = "yes"
unk_ucast = "proxy" unk_ucast = "proxy"
} }
} }
}
map object is similar to python
dictionary

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 34
Conditionals

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 35
Terraform Conditionals
Using Count

resource "aci_bridge_domain" "bd_192_168_1_0" {


tenant_dn = aci_tenant.demo.id
name = var.bd_name
arp_flood = var.bd_arp_flood
unicast_route = var.bd_unicast_routing
unk_mac_ucast_act = var.bd_unk_ucast
unk_mcast_act = "flood"
relation_fv_rs_ctx = aci_vrf.main.id
} In-line conditional

resource "aci_subnet" "net" {


count = var.bd_unicast_routing == "yes" ? 1 : 0

parent_dn = aci_bridge_domain.bd_192_168_1_0.id
Creates the resource only if the
ip = var.bd_gateway condition is met
scope = var.bd_scope
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 36
Terraform Conditionals
Combined with for/for_each loops

resource "aci_bridge_domain" "bd" {


for_each = var.bridge_domains

tenant_dn = aci_tenant.demo.id
name = each.value.name
arp_flood = each.value.arp_flood
unicast_route = each.value.type == "L3" ? "yes" : "no" In-line conditional
unk_mac_ucast_act = each.value.type == "L3" ? "proxy" : "flood"
unk_mcast_act = "flood"
relation_fv_rs_ctx = aci_vrf.main.id
}

resource "aci_subnet" "net" {


for_each = { for k, v in var.bridge_domains: k => v if v.type == "L3" }

parent_dn = aci_bridge_domain.bd[each.key].id Creates a new map with objects


ip = each.value.gateway
scope = each.value.scope that matches a condition
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 37
Data Sources

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 38
Terraform Data Sources
Overview

• A data source allow data defined outside of Terraform to be fetched


• Data Sources are always read-only
• The set of data sources available depends on the provider

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 39
Terraform Data Sources
Example

• Using data sources to get existing domain


resource "aci_application_epg" "epg" {
application_profile_dn = var.app_profile_id
name = var.name
name_alias = var.alias

relation_fv_rs_bd = var.bridge_domain_id
}

data "aci_vmm_domain" "vmm_vmware" { Fetching existing VMM


provider_profile_dn = "uni/vmmp-VMware" Domain data
name = var.vmm_domain
}

resource "aci_epg_to_domain" "epg_dom" {


application_epg_dn = aci_application_epg.epg.id Using fetched data
tdn = data.aci_vmm_domain.vmm_vmware.id
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 40
Running Plan

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 41
Terraform Plan
Calculating the delta

• When running terraform plan:


• Terraform queries the provider for the state of the resources you want to create or modify
• Terraform calculates the delta between the desired state and the actual configured state
• The output of the plan displays:
• What will be created (+)
• What will be modified in-place (~)
• What will be deleted (-)

• The plan can be saved to a file

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 42
Terraform Plan
Calculating the delta

ADEALDAG-M-D1S4:demo01 adealdag$ terraform plan -out myplan.tfplan

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create

Terraform will perform the following actions:


Resources to be added
# aci_bridge_domain.bd_192_168_1_0 will be created
+ resource "aci_bridge_domain" "bd_192_168_1_0" {
+ annotation = "orchestrator:terraform"
+ arp_flood = "yes"
+ bridge_domain_type = (known after apply) Parameters that are not specified
+ description = (known after apply)
[...]
will take default value, which is
known after applying the
Plan: 3 to add, 0 to change, 0 to destroy. changes to infra
──────────────────────────────────────────────────────────────────────────────────────────────────────────
Saved the plan to: myplan.tfplan

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 43
Terraform Apply
Applying the changes

• Terraform apply executes the actions proposed in the terraform plan


• When running terraform apply with no arguments:
• A new execution plan will be created (as in terraform plan)
• User will be prompted to approve it
• When approved, the changes will be applied in the infra

• When running terraform apply using a saved plan:


• Terraform will apply the changes in the plan without prompting for confirmation
• Typically used when Terraform is integrated in CI pipeline

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 44
Terraform Apply
Applying the changes

ADEALDAG-M-D1S4:demo01 adealdag$ terraform apply myplan.tfplan


aci_tenant.demo: Creating...
aci_tenant.demo: Creation complete after 1s [id=uni/tn-demo_tn]
aci_vrf.main: Creating...
aci_vrf.main: Creation complete after 3s [id=uni/tn-demo_tn/ctx-main_vrf]
aci_bridge_domain.bd_192_168_1_0: Creating...
aci_bridge_domain.bd_192_168_1_0: Creation complete after 4s [id=uni/tn-demo_tn/BD-192.168.1.0_24_bd]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

If something goes wrong, enable debugging in Terraform to investigate further:

$ export TF_LOG={TRACE|DEBUG|INFO|WARN|ERROR}

NOTE: Check Terraform documentation to learn about other options, such as TF_LOG_PROVIDER,
TF_LOG_PATH, logging to JSON, ...

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 45
Terraform State

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 46
Terraform State
Overview

• Terraform keeps state data to map which real-world object corresponds to


each resource
• This allows Terraform to modify existing objects when needed, detect config
drifts, ...
• Terraform updates state automatically during plan and apply
• State can be stored locally (in *.tfstate) or in a remote backend:
• Remote backend is recommended when using terraform to manage meaningful
infrastructure.

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 47
Terraform State
Remote Backends

Example using Terraform Cloud as remote backend:


terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = ”mycompany" State Management is
available in
workspaces { Terraform Cloud free
name = ”networking-prod"
tier
}
}
}

Use terraform login to log into Terraform Cloud and obtain the token.

Do not provide the token in the backend configuration.

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 48
Terraform State
Inspecting state

• Get list of resources managed by Terraform:


$ terraform state list

• Display detailed state about one of the resources:


$ terraform state show <resource_address>

• Trigger a manual refresh of the state:


$ terraform apply -refresh-only

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 49
Terraform State
Inspecting state

ADEALDAG-M-D1S4:demo05 adealdag$ terraform state list

data.aci_l3_domain_profile.core_l3dom
aci_bridge_domain.bd["bd01"]
aci_bridge_domain.bd["bd02"]
aci_subnet.net["bd01"]
aci_tenant.demo
aci_vrf.main
module.l3out_core.aci_bgp_peer_connectivity_profile.bgp_peer["asa"]
module.l3out_core.aci_external_network_instance_profile.l3instp["default"]
module.l3out_core.aci_l3_ext_subnet.l3instp_subnet["default.0.0.0.0"]
module.l3out_core.aci_l3_outside.l3out
module.l3out_core.aci_l3out_bgp_external_policy.bgp
module.l3out_core.aci_l3out_path_attachment.l3ip_path["103.1.19"]
module.l3out_core.aci_logical_interface_profile.l3ip
module.l3out_core.aci_logical_node_profile.l3np
module.l3out_core.aci_logical_node_to_fabric_node.l3np_node["103"]

[...]

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 50
Terraform State
Inspecting state

ADEALDAG-M-D1S4:demo05 adealdag$ terraform state show aci_tenant.demo


# aci_tenant.demo:
resource "aci_tenant" "demo" {
annotation = "orchestrator:terraform"
description = "This is a demo tenant created from Terraform"
id = "uni/tn-demo05_prod_tn"
name = "demo05_prod_tn"
relation_fv_rs_tn_deny_rule = []
}

ADEALDAG-M-D1S4:demo05 adealdag$ terraform state show 'aci_bridge_domain.bd["bd02"]'


# aci_bridge_domain.bd["bd02"]:
resource "aci_bridge_domain" "bd" {
annotation = "orchestrator:terraform"
arp_flood = "yes" Use single quotes for resources
bridge_domain_type = "regular" configured with a loop (count or
ep_clear = "no" for_each)
host_based_routing = "no"
id = "uni/tn-demo05_prod_tn/BD-192.168.2.0_24_bd"
[...]
}

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 51
Terraform State
Config Drifts

• How does Terraform react to a change in ACI outside Terraform?


• If the attribute is not set it Terraform Plan
• Detects the config drift
• Do not revert it
• After apply or refresh it will include those changes in the state

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 52
Terraform State
Config Drifts

Note: Objects have changed outside of Terraform


Config drift detected
Terraform detected the following changes made outside of Terraform since the last "terraform apply":

# aci_bridge_domain.demo_bd has been changed


~ resource "aci_bridge_domain" "demo_bd" {
+ description = "This has been changed in APIC"
id = "uni/tn-demo_tenant/BD-demo_bd"
name = "demo_bd"
# (24 unchanged attributes hidden)
}

Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using
ignore_changes, the following plan may
include actions to undo or respond to these changes.

──────────────────────────────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────── No changes to be made

No changes. Your infrastructure matches the configuration.

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 53
Terraform State
Config Drifts

• How does Terraform react to a change in ACI outside Terraform?


• If the attribute is not set it Terraform Plan
• Detects the config drift
• Do not revert it
• After apply or refresh it will include those changes in the state
• If the attribute is set in Terraform Plan
• Detects the config drift
• Reverts the change in the next apply
How Terraform deals with config drifts in
attributes that are not set depends on the
provider implementation.

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 54
Terraform State
Config Drifts

Note: Objects have changed outside of Terraform


Config drift detected
Terraform detected the following changes made outside of Terraform since the last "terraform apply":

# aci_bridge_domain.demo_bd has been changed


~ resource "aci_bridge_domain" "demo_bd" {
+ description = "This has been changed in APIC"
id = "uni/tn-demo_tenant/BD-demo_bd"
name = "demo_bd"
# (24 unchanged attributes hidden)
}

Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using
ignore_changes, the following plan may
include actions to undo or respond to these changes.

──────────────────────────────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────── No changes to be made

No changes. Your infrastructure matches the configuration.

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 55
Terraform State
Importing Infrastructure

• Terraform can import existing infrastructure and bring it under Terraform


management
• Currently, resources are only imported into the state
• Therefore, resource configuration needs to be in the plan
• This is required before the import can be performed’
• For Cisco ACI:
$ terraform import <resource_address> <dn>

$ terraform import aci_tenant.production uni/tn-prod_tn

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 56
Terraform State
FAQ

• What happens if I delete a resource from Terraform plan?


• If a resource is in the state file but not in the plan, Terraform will delete the object
from your infra
• What happens if I delete a resource from the infrastructure?
• If the resource is still in the plan, Terraform will recreate it with the configuration
from the plan
• Not from the configuration in the state!
• Consider this when dealing with config drifts

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 57
Terraform State
FAQ

• How can I make Terraform forget about a resource?


• The resource needs to be removed from the state and from the plan

$ terraform state rm <resource_address>

$ terraform state rm aci_vrf.prod

This is the process to follow to safely stop


Never manipulate the .tfstate file directly, use the managing a resource from Terraform without
CLI commands Terraform provides deleting it from the infrastructure.

Remember to use data sources when you only


need to read data from the infrastructure

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 58
Terraform State
FAQ

• How can I start managing an existing resource in Terraform?


• Use the terraform import command
• Three steps:
• Create the resource block in your code
resource “aci_vrf” “prod” { }

• Import the resource into the state


$ terraform import aci_vrf.prod uni/tn-common/ctx-prod_vrf

• Display the current state and configure your resource to match that
$ terraform state show aci_vrf.prod

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 59
Terraform State
FAQ

• What if I define a resource in the plan that already exists in the


infrastructure?
• If you don’t import the resource state, Terraform will not know about it
• Hence, Terraform will try to create the resource again
• Considerations:
• Depending on the target system, resource will be either recreated (e.g. ACI) or plan will fail because
object already exists (e.g. vSphere)
• If the configuration is not the same as the current state, the object will be modified (and
Terraform will not show those changes in the plan)

More about manipulating Terraform State here

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 60
• Terraform has become the de-facto
IaC tool
• Using Terraform, you write your
desired infrastructure state,
Key points to Terraform takes care of the rest
remember • There is an extensive (and growing)
list of resources within the Cisco
ACI provider for Terraform
• There are also providers for other
Cisco DCN products

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 61
• Terraform Cisco ACI Provider Documentation
https://registry.terraform.io/providers/CiscoDevNet/aci/latest

• Cisco DevNet ACI and Terraform Learning Labs


https://developer.cisco.com/learning/modules/terraform-aci-intro

• Cisco DCN Collection / Providers GitHub Repos

Reference
https://github.com/CiscoDevNet/terraform-provider-aci
https://github.com/CiscoDevNet/terraform-provider-mso
https://github.com/CiscoDevNet/terraform-provider-dcnm

• Terraform Language Documentation


https://www.terraform.io/docs/language/index.html

• Demo Code GitHub Repository


https://github.com/adealdag/aci-terraform-webinar

© 2021 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 62

You might also like