Brad Stinson

Antsle and Terraform

Published 5 Oct 2115 min read
image
Image Credit: Antsle and Hashicorp

The Antsle platform is an "All-in-one Virtualization Server" and the Java-based web application it uses to manage its virtualized instances is called "Antman". I'm the happy owner of an Antsle One, and the Antman software has undergone several evolutions over its lifespan. It has migrated from Gentoo Linux (part of how I discovered the product) to CentOS 7, added multiple quality-of-life features like distributed storage and load balancing, and concerning the subject of this post, provided documentation for using Terraform with the Antman API.

The Problem

The problem was, for the longest time, that successful compatibility between the Antman API and OpenAPI Provider was flaky despite a constant iteration tempo for both parties. To be fair, Antsle has made it clear that Antman's API should be viewed as nonstable, but given the community demand for this feature to work reliably, I wanted to explore the possibility of getting Terraform to work reliably with Antman. Because Antman is proprietary/closed source, complete with Terms and Conditions, contributing to or modifying Antman itself was out of the question. Fortunately, Antsle's proclaimed compatibility is derived from the Terraform Provider OpenAPI project which is capable of dynamically parsing a swagger file to enumerate available API calls. The provider can then make those API calls to create the platform's digital infrastructure. In the case of the Antman, we want Terraform to be able to create our Antlets... but it can only do that if the provider can reliably parse the swagger file.

As dikhan helped me realize, Antman's swagger file contained some problematic colon (":") characters that caused Terraform actions to crash.

Doh!

The OpenAPI Terraform provider attempts to convert the property names to terraform complaint names on the fly (eg: names containing dashes, or spaces, etc) but this particular use case has names with colons is not supported at the moment.

Dikhan

The Solution

At least there was a clear path forward. With his support, we managed to pull in a contribution complete with unit tests to extend the provider to support Antman's colon characters. By the time all of this had transpired, Terraform has undergone several more releases, most notably its milestone 1.0.0 release. While the Terraform Provider OpenAPI was now working with Terraform versions less than 1.0.0, I also sought to ensure it would work with the latest releases as well. After some time, the most recent versions of Antman and Terraform were happily working together!

Using the Provider

Antsle's official documentation captured the gist of what was needed to get the OpenAPI Provider to work with Antman, but I wanted to summarize a working recipe for the community including recent Terraform features. You will need:

  • An OpenAPI Provider binary, either downloaded or compiled yourself
  • A "terraform-provider-openapi.yaml" configuration file
  • A desired Terraform version installed
  • The latest version of Antman installed on your Antsle
  • A Terraform project

The Binary

At the time of writing, version 2.2.0 is the latest released version of the OpenAPI Provider. It only has PR #306 for colon character support in it, so you can download the pre-compiled binary, but it won't play nicely with Terraform versions greater than or equal to 1.0.0. You can, of course, wait for a subsequent release to roll in PR #314, but assuming your desire to get going immediately, you can, instead, clone the OpenAPI Provider project and compile the binary yourself from the master branch (you'll need golang installed).

					  
git clone <REPO URL> && cd terraform-provider-openapi
make build
                      
                    

This will create your binary called "terraform-provider-openapi" in the directory. Rename this binary to "terraform-provider-antsle" and place it at "~/.terraform.d/plugins/localhost/antsle/antsle/2.2.0/linux_amd64/" in order to conform to Terraform's provider source addresses specification. This will allow your Terraform project's configs to source the provider binary "hosted" on your localhost. You could, alternatively, host the binary somewhere and then adjust your Terraform provider config to retrieve the binary from where you host it, but this is the easiest route to get up and running. I'm choosing to label my self-compiled binary as version "2.2.0", which will be found in the Terraform config later, but if you've grabbed a later pre-compiled version, make sure to use the proper version in your path and *.tf file so that Terraform will be able to find the binary.

openapi_provider_binary_location

The YAML Config File

Once your binary is placed at the correct location, you'll need to follow Antsle's documentation for creating a yaml config file targeting your specific Antsle and placing that file at ~/.terraform.d/plugins/ . The binary will read this file to determine where to find the swagger file it needs to parse; doesn't make sense to bake that value into the binary itself, huh?

openapi_terraform_yaml_config

The Terraform Project Config

With your provider binary and yaml config file setup on your localhost, you now need to configure your Terraform project's config files to use that binary. This is where conflicting and outdated sources of information start to plague folks' implementation that I want to focus on clearing up. Antsle's documentation was created for earlier versions of Terraform that did not yet have the plugin/provider sourcing directory structure it does now, so neither the documentation nor video make any reference to the "required_providers" block of HCL. In addition, Antsle's documentation has not updated the correct name of the argument used by the antsle provider.

I happen to have a repo available whose Terraform configs create 4 Antlets intended to be used to compose a k8s cluster. Let's use it as an up-to-date reference to highlight working Terraform config files and check out the provider.tf file first.

                      
terraform {
  required_providers {
    antsle = {
      source  = "localhost/antsle/antsle"
      version = ">= 2.2.0"
    }
  }
}

provider "antsle" {
  api_key = var.apikey_auth
}
                      
                    

The "required_providers" block requires a provider named "antsle" to be used, which is found at the end of the file, and calls out part of the path you saw earlier. This is what is telling Terraform where to find your localhost-hosted provider binary when you run "terraform init". When you initialize your project, Terraform will find your provider binary and copy it to your project's .terraform directory. Specifically, it will be copied to the path "/path/to/your/project/.terraform/providers/localhost/antsle/antsle/2.2.0/linux_amd64/terraform-provider-antsle".

Also note the name of the argument used in the "provider" block. It is not "apikey_auth", as Antsle's documentation claims, but is now "api_key". I don't have my token string hard-coded into my file, but it retrieves the value from a variable. I just so happened to name that Terraform variable "apikey_auth", but it could have been named "my_cool_variable" instead. Don't misconstrue that variable name as something of significance; I just coincidentally named my variable to the incorrectly named provider argument to remind myself of the distinction between the provider argument and the optional Terraform variable containing my token.

The final gotcha is the actual string provided to this variable; it is the concatenation of the string "Token", a space character, and then your actual token. My provider.tf is grabbing this string from an CLI-provided input, so let's look at this variable at the end of the inputs.tf file.

                      
...
variable "apikey_auth" {
  # Example value = "Token ey..."
  type        = string
  description = "Get your Antsle token from the API, then put it in this variable. Remember to prefix 'Token ' to the actual token value."
}
                      
                    

The comment and description repeat what was just stated above, and is properly called out in Antsle's documentation. You can get your token from making the call to the login API, as the official video demonstrates. The video demo includes the hard-coded token value in the HCL, which was fine for a demo, but I wouldn't recommend in practice. You don't want to commit a credential, even a time-scoped token, to version control which is why it's better to source the token from a CLI input at run time.

All that remains now are the configs for your antlet resources, and Antsle's documentation and video has this right. The resource type is "antsle_antlets", and each antlet represented in the config can be uniquely named. If you were to look at my project's main.tf, you'd see that they are named with unique node names.

Antsle's Terraform Video

Antsle has provided a video walkthrough of this topic, and it is worth checking out. Just bear in mind the new path locations for assets we've just discussed as you do, and you should be okay. Hats off to a small company like Antsle providing a great capability like an API for the consumer to pickup and run with, and the OpenAPI Provider project for exposing that API to the great tool that is Terraform.

Conclusion

I hope you were able to get Terraform working with your Antsle! Drop a message in the Antsle forum if you're having trouble with this still. Below are some screenshots showing it in action.



No Antlets Created yet

no antlets

Terraform Init

terraform init

Terraform Apply

terraform apply

Accept The Plan

accept the plan

Terraform Apply Finished

terraform apply finished

Antlets Created

antlets created