Launch to Terraform with ACI – Part 2
In the event that you haven’t already seen Part 1 of the blog collection, please have a go through. This area shall protect ACI + Terraform, and we’ll add a couple of new subjects – Terraform importing and data resources.
- Launch to Terraform
- Terraform and ACI
- Description of the Terraform construction files
- Terraform Remote control State and Group Collaboration
- Terraform Suppliers – How are usually they built?
Program code Example
You may curently have your personal ACI lab to check out however in the event that you don’t you might like to utilize the ACI Simulator in the DevNet Sandbox.
Terraform ACI Service provider and Resources
Since explained in the last write-up, a Terraform provider is in charge of knowing API interactions and exposing assets.
This post shall cover the ACI Terraform Provider with a large numbers of resources.
The full set of available resources are available from the next link.
Terraform Resource vs Information Sources
Until we’ve only viewed the provider resource right now, for example “aci_tenant”.
reference "aci_tenant" "our_terraform_tenant" name = "tenant_for_terraform" explanation = "This tenant is established by the Terraform ACI service provider"
Terraform carries a concept referred to as data sources also.
Data resources allow a Terraform construction to utilize information defined beyond Terraform, or even defined by another individual Terraform configuration.
It’s important to remember that while resources are usually go through/write, data resources are study only. This implies we are able to include information inside our configuration apply for objects that we may not manage.
For example in the entire case of ACI, perhaps you want to manage our very own app profiles and EPGs in a shared tenant however don’t want Terraform to possess any handle of the tenant itself.
We are able to define the shared components (tenant, BD, VRF, agreements etc) as data resources (read only), and the ANP/EPGs as resources which is deleted and developed by Terraform.
provider "aci" # cisco-aci user name username = "$var.username" # cisco-aci password password = "$var.password" # cisco-aci url url = "$var.apic_url" insecure = true data "aci_tenant" "my_shared_tenant" name = "my_shared_tenant" data "aci_bridge_domain" "my_shared_bd" tenant_dn = "$data.aci_tenant. my_shared_tenant.id" name = "my_shared_bd" resource "aci_application_user profile" "terraform_app" tenant_dn = "$data.aci_tenant. my_shared_tenant.id" name = "demo_app_user profile" resource "aci_program_epg" "my_internet_epg" application_profile_dn = "$aci_application_profile.terraform_app.id" name = "db_epg" description = "%s" annotation = "tag_epg" exception_tag = "0" flood_on_encap = "disabled" fwd_ctrl = "none" has_mcast_source = "no" is_attr_based_e_pg = "no" match_t = "AtleastOne" name_alias = "alias_epg" pc_enf_pref = "unenforced" pref_gr_memb = "exclude" prio = "unspecified" shutdown = "no"
As you can see above we’ve defined two data sources (my_shared_tenant and my_shared_bd). They are referenced in the  then;aci_application_user profile resource utilizing the format, “$data.aci_tenant. my_shared_tenant.id“.
Remember from the prior post that some properties such as for example IDs are computed behind the scenes with no need to hard code values.
NOTE: You’ll must ensure that any data sources you’re referencing already exist in the ACI fabric. Including the bridge domain, “my_shared_bd”, exists in the tenant already, “my_shared_tenant” inside our lab. If these data sources already exists you’ll receive one don’t.
So using both of these concepts we are able to build the required configuration for the ACI fabric. Some Terraform ACI configuration has been provided above and in the last post already. To obtain started the ACI Business Unit have created a lot of example configuration files which you can find from the next link.
Additionally, for just about any customer configuration you might like to create, the next document includes the complete set of available resources for the ACI provider.
You should be distributed by these resources an excellent start on your own journey to managing ACI with Terraform.
But wait, there’s more! There are always a couple of questions which are asked with regards to the ACI provider often.
- Is this limited to greenfield deployments?
- Can I configure everything through Terraform?
- What happens easily manually configure ACI?
Importing With Terraform
ACI might already exist in lots of customer environments if they begin to use Terraform. Alternatively, a customer not used to Terraform and ACI might not desire to learn both at exactly the same time, choosing to first learn ACI and migrate configuration to Terraform then.
Luckily Terraform supports (for a few providers) the importing of existing configuration to handle these common scenarios.
Remember you can find two main files we’re dealing with, the configuration (.tf) and hawaii (terraform.tfstate) files.
The “Terraform Import” command is only going to import what it learns concerning the existing infrastructure in to the state (terraform.tfstate) file. It shall not automatically append this in to the configuration file.
This can be a manual process you need to complete.
Step 1 – Add the brand new resources to the configuration (.tf) file.
resource "aci_tenant" "myTenant"
You only have to define the resource.
If you configure a house like a name and import from a preexisting resource then, the values will be overwritten.
resource "aci_tenant" "myTenant" name = “myTenant1”
In this example if the ACI tenant is known as “myTenant”, when first importing Terraform use “myTenant” in hawaii file. The configuration file isn’t updated on an import and for that reason “myTenant1” will never be changed. Once you run the  later;apply command, Terraform shall update the ACI fabric with the brand new name, “myTenant1”
Step 2 – Run the import command
Terraform identifies ACI objects making use of their Distinguished Name (Dn) and the Terraform resource ID may be the absolute path of ACI object in the DMIT.
For instance, the ID of an ACI tenant, myTenant, is uni/tn-myTenant. The ID of an ACI VRF, vrf1, in myTenant is uni/tn-myTenant/ctx-vrf1
The import command can be used as follows:
e.g terraform import aci_tenant.myTenant uni/tn-myTenant
We added the aci_tenant.myTenant resource to the configuration file in Step one 1. This command is assigning an ID, the ACI Tenant Dn (uni/tn-myTenant), to the resource and can import existing configuration.
Step 3 – Repeat for several required resources
This used the ACI tenant for example however you could also have to import other resources such as for example bridge domains, VRFs, EPGs, contract. You’ll repeat the steps above for every of the resources. First add all of them as resources and run the import command referencing the name of the resource and the ACI Dn as ID.
ACI REST Resource
There are lots of properties of ACI that may be configured, not absolutely all exist as Terraform resources in the ACI provider however. Because of this the aci_rest resource was made and lets you configure ACI Objects through the others API. Any Model Object that’s not supported by the provider could be created/managed by using this resource.
As a result, anything that could be configured through the ACI REST API could be managed and configured by Terraform. Either by way of a native resource (e.g. aci_tenant), or utilizing the API (aci_rest resource).
Here’s a good example of creating an L3Out.
resource "aci_rest" "rest_l3_ext_out" path = "/api/node/mo/$aci_tenant.tenant_for_rest_example.id/out-test_ext.json" class_name = "l3extOut" content = "name" = "test_ext"
These may be the same configuration you’ll find in a Python script making raw calls to the ACI API, only that is wrapped in a Terraform resource.
Note as well you could reference existing variables or properties such as for example the  still;aci_tenant id.
“What goes on if someone manually configures a resource Terraform is managing?”
This can be a common question not merely for Terraform but we have been using external tools to control infrastructure anytime.
In the entire case of ACI we are able to test drive it out and see what goes on.
Step 1 – Create a tenant first, my_terraform_tenant, with the next description.
resource "aci_tenant" "my_terraform_tenant" name = "tenant_for_terraform" description = "This tenant is established by the Terraform ACI provider"
Step 2 – Login to the GUI and beneath the Tenant -> Policy, update the description.
Step 3 – Run the terraform plan command and see exactly what will happen
You should note that one change will be designed to reconfigure the tenant description.
This validates what we’ve learnt previously. Terraform will try to maintain consistency between your desired configuration (.tf files) and the existing state (terraform.tfstate file) of the infrastructure. If it notices that hawaii has been changed (manually inside our case), it shall reconfigure the infrastructure.
Modifying Attributes vs Resources
Be aware that the results above may possibly not be the same whenever using Terraform and ACI always. Let’s run another ensure that you see what happens.
Step 1 – Develop a tenant, BD, and subnet with the next configuration.
resource "aci_tenant" "myTenant" name = "myTenant" resource "aci_bridge_domain" "bd_for_subnet" tenant_dn = "$aci_tenant.myTenant.id" name = "bd_for_subnet" description = "This bridge domain is established by the Terraform ACI provider" resource "aci_subnet" "demosubnet" bridge_domain_dn = "$aci_bridge_domain.bd_for_subnet.id" ip = "10.1.1.1/24" scope = "private" description = "This subject is established by Terraform"
Step 2 – Through the ACI GUI, develop a new subnet in exactly the same bridge domain. I’ve used 172.16.1.1/24 for example.
Step 3 – Run the terraform plan again and also have a glance at the output. You shouldn’t see any changes.
Step 4 – Delete the 10.1.1.1/24 subnet from the bridge domain, keeping the brand new subnet.
Step 5 – Run another plan and start to see the output. You should note that Terraform will add the 10 back.1.1.1/24 subnet when applied. Nonetheless it doesn’t know about the brand new subnet ,172.16.1.1/24, which means this is left untouched.
This means we’ve two subnets on the bridge domain again.
Why is this happening?
Terraform tracks resources by an ID and a genuine name. When it notices a property (e.g. description) in a resource (e.g. aci_tenant) has changed, it updates the infrastructure to complement what’s in the configuration file. This is exactly what happened with the description. Note that the ID and name of the resource didn’t change, it had been exactly the same ACI tenant still.
If you’ve caused ACI you’ll understand that you can’t rename objects. That is inherent to how ACI stores information. All objects have a distinctive distinguished name which name can be used when together connecting various objects. You can view this in the configuration above in which a subnet points to the distinguished name of the bridge domain where it resides.
As previously mentioned also, the Terraform ACI provider uses the Dn because the ID for the resource.
In the entire case of ACI a subnet can be an object with a distinguished name. Since we can’t edit the name (10.1.1.1/24) we have to delete it and recreate it with another name (172.16.1.1/24). This results in a fresh object and Dn and a fresh Terraform resource and ID therefore.
Nevertheless the old subnet resource (10.1.1.1/24) still exists in the Terraform state file, as the new one hasn’t been imported. As a total result, Terraform re-implements the 10.1.1.1/24 nothing and subnet happens to the 172.16.1.1/24 subnet.
If you update the subnet in the Terraform configuration file you’ll note that Terraform manages the “renaming”. It’ll delete the old subnet and recreate a fresh one first, making it appear as if it’s been renamed.
Terraform can be an extremely powerful and flexible tool however as you’ve seen up to now, there are cases that could bring about unexpected behaviour. Like any deployment, it’s always far better understand how you’ll use Terraform in your environment. The ACI simulator is a superb solution to learn, test, and plan any noticeable changes you intend to make before pushing to production.