Many of the customers that I speak to are looking for a way to standardize and automate more of their IT operations. Most feel ready to tackle automation but feel that infrastructure as code (IaC) is too large of a leap for their organization. Terraform is one of the most popular IaC tools in use today. In this blog, I'll cover how to get started using the Cisco Intersight provider for Terraform from the perspective of someone who may not be very familiar with Terraform. I hope to show that getting started with managing pieces of your Intersight configuration with Terraform is not difficult thanks for the Intersight provider.
There are both free and paid versions of Terraform. This blog will use the free version of Terraform. To learn more about the benefits of paid versions of Terraform, visit the Hashicorp site.
You'll need to install Terraform on your computer. Hashicorp recommends using Homebrew on MacOS or Chocolatey on Windows to install Terraform. Type the following command to verify that Terraform is installed. The exact version of Terraform that you're using doesn't matter, but if you're just getting started, you might as well run the latest! The point of running this command, though, is just to verify that you don't get any errors.
terraform -version
Browse to the Intersight provider on the Terraform Registry. In the upper right corner of the page, there is a dropdown labeled "Use Provider" as shown in the screenshot below. The text that is displayed is the text that you'll need to use the latest Intersight provider for your Terraform configuration.
Start with an empty folder and create a new file called main.tf. Copy the text above from the Intersight registry website and paste it into main.tf.
As a side note, the filename doesn't matter as long as it ends in .tf. Terraform is very flexible with your naming conventions. It looks at all of the configuration files and variable files in your current directory and combines them into a single Terraform plan. So you organize your configuration into as many or as few files as you like! For simple configurations, it makes sense to keep the file count small.
Back to our configuration... if. you look at what you just pasted into main.tf, you'll notice that it specifies the provider name (CiscoDevNet/intersight) and version, but it doesn't specify any of the configuration options (the URL for Intersight, your API key, and your API secret). The Intersight guide for this provider suggests the following syntax:
provider "intersight" {
apikey = "<api key>"
secretkey = "<secret key as a string or in a file>"
endpoint = "https://intersight.com"
}
But you should never put your credentials into a file like this, especially when you're working with IaC, where checking your code into a version control system (VCS) like GitHub is common. Instead, I suggest that you set your credentials as local environment variables as shown below. If you don't specify your credentials in one of the .tf files, the provider will look for those two environment variables for the information.
export INTERSIGHT_API_KEY=625143a...
export INTERSIGHT_SECRET_KEY=~/path/to/secret/key.txt
This simplifies your main.tf file to look like the following, where your version number and Intersight endpoint might differ.
terraform {
required_providers {
intersight = {
source = "CiscoDevNet/intersight"
version = "1.0.35"
}
}
}
provider "intersight" {
endpoint = "https://intersight.com"
}
Checkpoint: At this point, you've installed Terraform, set your credentials as environment variables, and created a single file called main.tf (or a .tf file by some other name if you prefer) with the contents above. You haven't actually defined any kind of configuration yet, and that's what you'll do next.
If you read my blog about getting started with the API browser or getting started with the PowerShell SDK, you'll know that I consider retrieving an organization from Intersight to be the "hello world" of programmability with Intersight. It's the first thing you should do since any policies or profiles that you create will be created within an organization. So how do you do that? Let's check the documentation.
Going back to the Intersight provider page in the Terraform registry:
In Terraform, they keyword resource refers to some infrastructure object that you would like to create/manage through the Terraform configuration. They keyword data refers to an existing infrastructure object that you would like to read into your Terraform configuration in order to refer to it elsewhere. The documentation you're looking at shows how to create an organization, but you'll use that structure to refer to an existing object. Add the following lines to your main.tf file.
data "intersight_organization_organization" "myorg1" {
name = "default"
}
The block of code above tells Terraform to find an Intersight organization in your account whose name is "default" and to assign it to the name intersight_organization_organization.myorg1 within the Terraform configuration.
Your main.tf file now contains a Terraform configuration. It's not very interesting, but it will run. First type:
terraform init
A few things will happen. You will get a message that Terraform has been successfully initialized. You would also see a new directory in your project directory called .terraform. Terraform has placed a local copy of the Intersight provider in this directory so that it does not need to constantly retrieve it from the internet. It will also create a file called .terraform.lock.hcl that contains exact version numbers of the providers you are using. The main thing you want to look for is that message that says the initialization was successful.
Now it's time to run the configuration. Run the following command:
terraform apply
The output won't be very interesting, but there is a new file in your local directory called terraform.tfstate. You should probably read Haschicorp's explanation of the state file, but I'll try to provide a brief one here. The state file contains a mapping of infrastructure resources to the code blocks in your configuration. For example, your state file now contains a mapping between intersight_organization_organization.org1 from your main.tf file and the actual organization named "default" in your Intersight account. Later, when you create and modify resources, the state file will play a more important role than it seems to at this point. You can look at the state file in any text editor, but you should never make any edits to it.
If you look in the state file, you'll find the Moid for the default organization, but the state file is not made to be easily human readable. Instead, you should display information that is important to you on the screen using an output block. Add the following lines to your main.tf file.
output "myorg1_moid" {
value = data.intersight_organization_organization.myorg1.results[0].moid
}
Now run "terraform apply" again and you'll see output similar to the following.
myorg1_moid = "625043ad6972652d3085fedb"
Checkpoint: So far you have used Terraform to discover an object that already exists within Intersight (an organization) and displayed it on the screen. Your main.tf file contains details about the Intersight provider, one data block, and one output block. Things get more interesting when you start creating objects inside that organization. Let's do that next.
It's time to go back to the documentation and locate an example for how to create an NTP policy using a resource block. You can go back to the search box and type "ntp" or click here. The example provided in the documentation creates an NTP policy in an organization specified as a variable. In the last step, you already discovered the Moid for the default organization, so I propose adding this block to your main.tf file instead.
resource "intersight_ntp_policy" "myntp" {
name = "my_first_ntp"
description = "test policy"
enabled = true
ntp_servers = [
"ntp.esl.cisco.com",
"time-a-g.nist.gov",
"time-b-g.nist.gov"
]
organization {
object_type = "organization.Organization"
moid = data.intersight_organization_organization.myorg1.results[0].moid
}
}
This block is very similar to the example in the documentation. I changed the name of the policy itself as well as the name of the resource just to illustrate a few points later.
Now running "terraform apply" will actually create a new NTP policy in the default organization! Terraform will warn you of all the changes it is going to make and ask you to agree to them. The state file now also contains a mapping for intersight_ntp_policy.myntp to the Moid for the policy that was actually created in Intersight. You should log in to Intersight to confirm that the NTP policy is there (spoiler: it is).
Now try changing the name of the NTP policy in main.tf from "my_first_ntp" to "something_else". Notice that if you run "terraform apply" again, Terraform will change the existing policy in place. In addition to containing the Moid for the policy, the state file contains every setting for that policy. When you run "terraform apply", it compares the state file and your actual environment (the Intersight account) with the configuration stored in main.tf.
Checkpoint: At this point, you have created discovered an existing organization and created a new NTP policy in that organization. Your entire configuration is still contained in one file, and the order of the blocks in that file do not matter. If you don't believe me, try moving them around and running terraform apply again! What happens when an administrator changes an object you created via Terraform? We will experiment with that next.
Log in to the Intersight UI and make a change to the NTP policy you just created. I'll go into mine and delete one of the NTP servers. Run "terraform apply" again and Terraform will report that it has to change the existing policy in place. You should see a message similar to the one below, detailing exactly what will change.
Terraform will perform the following actions:
# intersight_ntp_policy.myntp will be updated in-place
~ resource "intersight_ntp_policy" "myntp" {
id = "644de241627572300101dcc7"
name = "my_first_ntp"
~ ntp_servers = [
# (1 unchanged element hidden)
"time-a-g.nist.gov",
+ "time-b-g.nist.gov",
]
tags = []
# (20 unchanged attributes hidden)
}
Terraform expects to have sole ownership of any resources that it creates. If you make manual changes to those objects, your changes will be overwritten next time Terraform applies your configuration.
Now try deleting the policy from the Intersight UI. Running "terraform apply" again will do two things: it will create a new NTP policy with the exact same settings and remove any references to the old policy from the state file. Why? The policy that you manually deleted had a Moid in Intersight that will never exist again. It is gone forever, so Terraform has to create a new policy (with a new Moid) with the same settings.
Checkpoint: You have seen what happens when a user makes changes to Intersight objects managed by Terraform. Terraform will edit those objects in place to to return them to their intended settings or recreate them if they were deleted. Terraform's purpose is to ensure your environment mirrors the configuration specified in the .tf files in your current directory. Next I'll discuss my favorite Terraform feature.
At some point in your project's lifecycle, it will be time to retire the policies, pools and profiles that you created in Intersight. There is a single command that you can run to remove all the objects that Terraform created in your environment.
terraform destroy
It is important to note that both "terraform apply" and "terraform destroy" work only in the context of the current working directory. In other words, you could have dozens of directories with different Terraform configurations, but those commands only look at the files in the current working directory when deciding which objects to create and which objects to destroy.
It makes sense to organize your files in different directories by project, geography, department, or user. That will be a very personal choice.
Running "terraform destroy" for this project will remove the NTP policy from Intersight but will also remove both the NTP policy and the organization from the state file. The state file will be nearly empty. Note that the organization will not be deleted from Intersight because Terraform didn't originally create it or ever take ownership of it.
# intersight_ntp_policy.myntp will be destroyed
Checkpoint: You have witness that one configuration file can be used by Terraform to both create objects and destroy them. Unlike other methods, Terraform inherently understands dependencies. It knows the correct order in which to create objects and destroy objects. For example, it knows to create VLANs before creating the VLAN policy that uses those VLANs. It also knows to destroy the policy before destroying the VLANs within that policy.
This blog was geared towards getting started. A few key takeaways:
Because this blog was geared towards getting started, I covered the data block, output block, and resource block. I did not discuss using variables or locals. I also didn't discuss loops or conditionals. Despite that, I hope you found this blog useful. Let me know in the comments if there are any topics you would like to see addressed in future blogs.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: