Summary

This tutorial will show you how to apply one or more licenses to vCenter through the use of Terraform. This can be expanded on to create a module that can be used across multiple vSphere environments.

 

Structure

First of all, we are going to create a folder called configure_licensing. In this folder we create the following files

 

filenamepurpose
variables.tfdefinitions of the variables required (i.e. license keys to apply)
main.tfthe terraform definition that will apply the license keys
provider.tfspecifies the provider to use (in this case the vSphere provider)
provider_variables.tfcontains a list of variables with default values for the provider
outputs.tfSpecifies information to output once an apply operation has been completed successfully

 

You could in theory combine the provider.tf and provider_variables.tf files, but my personal preference is to keep them seperate. One file defines the provider to use whilst the other defines what you need to pass in to enable the provider. In terms of file content, it is actually quite light!

 

provider_variables.tf
# Variables section for vSphere connectivity
variable "vsphere_server" {
  description = "fqdn for the vsphere server for the environment"
  default     = "testvc.automationcore.com"
}

variable "vsphere_user" {
  description = "user with sufficient rights to vsphere server for the environment"
  default     = "administrator@vsphere.local"
}

variable "vsphere_password" {
  description = "vsphere server password for the environment"
  default     = "topsecret123!"
}

variable "allow_unverified_ssl" {
  description = "specify whether we can use unverified ssl certificates"
  default     = true
}

 

provider.tf
provider "vsphere" {
  user           = var.vsphere_user
  password       = var.vsphere_password
  vsphere_server = var.vsphere_server

  # if you have a self-signed cert
  allow_unverified_ssl = var.allow_unverified_ssl
}

 

variables.tf
# The licenses to add
variable "licenses" {
  type = list(string)
}

 

main.tf
resource "vsphere_license" "licenseKey" {
 count                           = length(var.licenses) 
 license_key                     = var.licenses[count.index]
}

 

outputs.tf
output "edition_key" {
  value = vsphere_license.licenseKey.*.edition_key
}

output "total" {
  value = vsphere_license.licenseKey.*.total
}

output "used" {
  value = vsphere_license.licenseKey.*.used
}

output "name" {
  value = vsphere_license.licenseKey.*.name
}

 

Let’s concentrate on the variables.tf, main.tf and outputs.tf files.

 

variables.tf

As you can see we have declared a variable called licenses. The type is list(string) which means it expects to recieve one or more license keys, wrapped in quotes and comma seperated. We wrap the entire entry in ‘[]‘ brackets. As an example, we would pass in something like the following

 

[“12345-abcde-fghjk-67890-qwerf”, “67890-qwerf-12345-01CU4-987VC”]

 

 

main.tf

As you can see we are declaring a resource type of vsphere_license.licenseKey. According to the documentation, there are two arguments

argumentdescriptionrequired
license_keyspecifies the license key that you want to add to vSpheretrue
labelsallows you to specify key/value pairs that can be allocated to the license key in the form of a tagfalse

 

I am only going to bother specifying the required argument. The documentation provides an example of how to add a license key, however we want to allow for adding multiple keys. So how do we do this? Quite simply actually! Lets break it all down.

resource "vsphere_license" "licenseKey" {
 count                           = length(var.licenses) 
 license_key                     = var.licenses[count.index]
}

 

count = length(var.licenses)

Remember how we declared our licenses variable type as a list(string)? Since we have declared it as a list, we can use a built in method to find the length of the list, or to think of it differently, the size of the list. If we passed in two values (two license keys) into this variable, then the length will be 2. Count will be set to the length.

 

license_key = var.licenses[count.index]

If you have any experience with programming in any language then you may recognise the following style of syntax (this is a syntax example, not workable code)

for each (var fruit in fruitbowl)
{
  echo "This is a " + fruit
}

 

The idea is that if there are 5 items of fruit in the fruitbowl, we will echo out “This is a ” followed by a type of fruit, five times; a bit like this

var fruitbowl = ["banana","orange","apple","pear","grape"]

for each (var fruit in fruitbowl)
{
  echo "This is a " + fruit
}

example output:
       This is a banana
       This is a orange
       This is a apple
       This is a pear
       This is a grape

 

The way that our license_key = var.licenses[count.index] line is processed, is actually very similar to my fruitbowl example (despite to very different syntax!). Terraform will set license_key equal to each of the items in our list(string). I know, it really doesn’t look like it would considering the syntax. Think of it as being executed something like this

 

licenses = ["12345-abcde-fghjk-67890-qwerf", "67890-qwerf-12345-01CU4-987VC"]

for each (var license in licenses) {
     resource "vsphere_license" "licenseKey"
     {
       license_key = license
     }
}

 

Which would execute something like this on the first iteration

for each (var license in licenses)
{ 
    resource "vsphere_license" "licenseKey" {
        license_key = "12345-abcde-fghjk-67890-qwerf"
    }
}

 

and like this on the second iteration

for each (var license in licenses)
{ 
    resource "vsphere_license" "licenseKey" {
        license_key = "67890-qwerf-12345-01CU4-987VC"
   }
}

 

So, Terraform creates the resource one at a time. Simple, hey?

 

outputs.tf

As you can see we are declaring a number of outputs that we would like sent to the console when the application has been successful. How do we know these exist? They are documented in the attributes reference section of the documentation. Each of the outputs is assigned a name. This enables you to reference and use the output value in another script later on. Because we are going to accept multiple license keys as input we have to format each output to contain a ‘*’ character to enable the value of each iteration to be output.

 

Execution

Lets run a terraform plan and pass in some license keys. Create a definitions file with the license keys that you want to register, like this [editor: why? because it is easier than trying to specify on the command line!]

definitions
# License keys to register with the vCenter server
licenses = ["abc-def-ghj-klm-npq", "123-456-789-abcd-efgh"]

 

Now, lets run a terraform plan and have a look at what is going to change. We will pass the definitions file to terraform plan, as well request that the plan output be saved to disk.

Run terraform plan to check what changes will be made

 

Once we happy with the changes, we can run terraform apply, passing in the plan. As you can see, the outputs that we requested are shown at the end of a successful execution.

terraform apply output

paul_davey

CIO at Sonar, Automation Practice Lead at Xtravirt and guitarist in The Waders. Loves IT, automation, programming, music