Skip to main content

Migrate to an Infrastructure Plugin

In this section, you will find a guide on how to use legacy Terraform files to create Infrastructure Plugins.

How does it work?

The Plugin generator analyzes your existing Terraform structure and:

Extracts variables and local values from the Terraform file. It transforms these variables into inputs for the Infrastructure Plugin. These variables are required as they will be used in the Terraform configurations within the Plugin. The generator automates the creation of Plugins, allowing you to efficiently reuse your legacy code and integrate it with StackSpot.

Terraform Extracted Values

The extracted values ​​will be:

  • Terraform local values ​​(locals): values ​​only used in the scope of the file in which they were declared.

  • Variables (variable): variables valid for the entire scope of the Terraform execution.

The Terraform file is analyzed, and each variable is extracted as follows:

  • The type of the local variable or value will be the input type. Terraform's supported types are string, number, and bool and will correspond to StackSpot's text, int, and bool types.

  • The variable description will be the description of the input.

  • The default values for the variable will be specified in the default input field.

Local Values

Local values (locals) will only be extracted if they are literal types, such as string, number, or bool. Variables that are assigned the reference of another variable will not be extracted. Additionally, local values that are null will also not be extracted.

Example:

main.tf
locals{
var1 = "String text"
var2 = local.var1
var3 = null
}

The extracted local values will be converted into Jinja expressions in the Terraform file of your Plugin template, located in the templates-deploy folder, to correspond with the Plugin inputs. Any values that are not extracted will remain unchanged in your Terraform file.

Example:

main.tf
locals{
var1 = "String text"
var2 = 10
var3 = null
var4 = tolist(var.example_set)
}

After extracting the variables:

main.tf
locals{
var1 = {{main_local_var1}}
var2 = {{main_local_var2}}
var3 = null
var4 = tolist(var.example_set)
}

Variables

Variables (variable) - all variables will be extracted if they are not a Terraform composite type, for example, object, list, map, etc. Since StackSpot does not support these Terraform types.

The supported types are:

  • string
  • number (integer or decimal)
  • bool

The values in variable will not be modified in your template, except for any other values nested within variable. Instead, these values will be saved in the terraform.tfvars file generated by Terraform, which contains all the values for each variable.

When a variable is extracted with a default value of 'null', it will be treated as an input of type text. In this case, it will not have the property 'default', and the property 'required' will be marked as false.

The terraform.tfvars file is a mechanism in Terraform that automatically generates a file with the values of all variables. This process ensures that users do not have to re-enter the same inputs every time, particularly for variables without a defined default value.

When StackSpot creates the Infrastructure Plugin, it will use or create this file if it does not already exist and configure it using Jinja expressions.

For example, consider the file terraform.tfvars with the following variables filled in:

variables.tf file:

variable "var1"{
description = "Variable var1"
type = string
default = "var1 value"
}
variable "var2"{
description = "Variable var2"
type = string
default = "var2 value"
}
variable "var3"{
description = "Variable var3"
type = string
default = "var3 value"
}
variable "var4"{
description = "Variable var4"
type = number
default = 2.5
}
variable "var5"{
description = "Variable var5"
type = string
default = "null"
}
variable "var6"{
description = "Variable var6"
type = bool
default = true
}

File terraform.tfvars existing and populated:

terraform.tfvars
var1 = "string text"
var2 = "string text"
var3 = "string text"
var4 = 11.5
var5 = "null"
var6 = true

terraform.tfvars file transformed after extracting variables or generated during Plugin creation:

terraform.tfvars
var1 = {{variables_var_var1}}
var2 = {{variables_var_var2}}
var3 = {{variables_var_var3}}
var4 = {{variables_var_var4}}
var5 = {{variables_var_var5 or "null"}}
var6 = {{variables_var_var6}}
tip

With the terraform.In the tfvars file, you can see all the variable variables that were extracted (values ​​replaced by a Jinja expression) and those that were not. This file does not include the values ​​in the locals block.

When applying the Infrastructure Plugin in the terraform.tfvars file, the values ​​with the Jinja expressions will be replaced when the template is rendered.

Creating the Infrastructure Plugin

To create the Plugin, in addition to the Plugin name, use the following parameters when executing the stk create plugin command:

  • --type: Plugin type. The type must be "infra".
  • --source-type: Source file type. The accepted type is "terraform".
  • --source-path: Path to a folder with Terraform files.

Syntax:

stk create plugin name-plugin-infra --type infra --source-type terraform --source-path FOLDER/FILES/TERRAFORM

Example:

Terraform files in folder 'Documents/infra-iac'
stk create plugin plugin-infra-legacy --type infra --source-type terraform --source-path localUser/Documents/infra-iac

Your Infrastructure Plugin will be generated in the current folder where you run the command. Check all the files in the templates-deploy folder and the Plugin inputs in the plugin.yaml file. You must manually handle the values ​​not extracted into inputs for your Plugin. For all the 'stk create plugin' options, see the StackSpot commands page.

Best practices for creating Infrastructure Plugins

When creating Infrastructure Plugins in StackSpot, it’s important to adhere to best practices to avoid execution issues and ensure the consistency and security of your Application. See the following guidelines to consider:

1. Avoid using inputs or Jinja manipulations in resource or module names

Avoid using inputs or Jinja expressions directly in resource or module names. This can cause issues, especially if an input changes, leading to Terraform losing references and resulting in execution problems.

resource "aws_lambda_function" "{{ lambda_name }}" {
...
}

resource "aws_lambda_function" "stk_{{ lambda_name }}" {
...
}

module "ecr_{{ app_name }}" {
...
}
resource "aws_lambda_function" "stackspot_lambda" { // sem inputs
filename = "{{ lambda_zip }}"
function_name = "{{ lambda_name }}"
....
}

2. Avoid conditionals, loops, or interpolation in Jinja with Connection Interfaces

Avoid using conditionals, loops, or interpolation in Jinja when working with Connection Interfaces, as this can lead to inconsistencies and make the code more difficult to maintain.

3. Do not use Jinja with Connection Interfaces outside of Terraform (.tf) files

Connection interfaces generated by external applications are usually populated. However, when created within the same application (by other applied Plugins), their values are generated during execution and referenced as variables in Terraform.

Use Terraform to determine these values.

4. Do not use Connection Interfaces in tfvars

Avoid using Connection Interfaces directly in the tfvars file. Doing so can lead to significant inconsistencies and security vulnerabilities, including:

Exposure of sensitive data: Connection Interfaces often contain critical information such as ARNs, bucket names, and other resource identifiers. Storing this information directly in the tfvars file dramatically increases the risk of exposure.

Abstraction breakdown: This practice undermines the modularity and reusability of Plugins, making it far more challenging to integrate and reuse plugins or stacks with other components.

5. Caution when implementing unified deployment

The unified Deployment feature allows you to simultaneously apply all Terraform configurations from the Plugins associated with an Application or Infrastructure. While this process can streamline deployment, it may also require more resources and could lead to potential issues in some cases. Here are some important considerations:

  1. Complex Infrastructures: If your Application or Infrastructure uses multiple Infrastructure Plugins that require significant memory, caching, or file reading, it's advisable to utilize more powerful runners to prevent crashes.
  2. Provider version conflicts: Using Plugins with differing version constraints for the same provider can result in conflicts during Terraform execution.

Example:

In an Infrastructure with both an SQS Plugin and an SNS Plugin:

  • The SQS Plugin restricts the AWS provider version to ">= 1.2.0, < 2.0.0".
  • The SNS Plugin restricts the AWS provider version to ">= 4.0.0".
    • Terraform will result in an error during initialization because no version meets both conditions.
  • Make sure that all Plugin versions in a Stack are compatible. Additionally, check the compatibility of other Plugins in the Workspace.

By following these guidelines, you can achieve greater consistency and security in the development and execution of Infrastructure Plugins in StackSpot.