Skip to content

Adding to Terry

Lee Baird edited this page Jun 19, 2023 · 15 revisions

Terry was intended to be built off of by modifying configurations and adding new templates. Before building onto Terry, please read the Home page to understand the design paradigms used to build infrastructure.

Adding a Provider (Base Implementation)

  1. Inside the Terraform mappings file template folder add the provider with the following format:
<provider_name>:
  provider:
    source: <terraform_provider_source>
    version: <terraform_provider_version>
    required_args:
      - <1_required_credentials_to_authenticate>
      - <2_required_credentials_to_authenticate>
      - ...
    is_registrar: true|false
  1. Find the provider documentation on the Terraform website and create the provider block needed for the specific provider.

Note: The required_args list inside the provider block MUST have the same names as the environment variables required by that provider. For example, an AWS Secret Key should be "AWS_SECRET_ACCESS_KEY" as that is defined as the required environment variable in the AWS Terraform docs.

And that is all you need to add a new provider! Since Terry will read from this file to check for implemented providers, it will now show up as an option for providers when using the CLI. However, if that provider can deploy a server resource (and you have a file at ./templates/terraform/<provider_name>/server.tf.j2), additional configuration is required. Keep reading.

Adding a Server Provider

Some providers can deploy servers and those servers are different for each provider in how they are named, what user is allowed to SSH in after it has been provisioned, and what property is mapped to the public IP address. Because of this, you will need to add some additional information into the provider config so Terry knows what data to map back to Ansible. That block looks like the following:

<provider_name>:
  provider:
    source: <terraform_provider_source>
    version: <terraform_provider_version>
    required_args:
      - <1_required_credentials_to_authenticate>
      - <2_required_credentials_to_authenticate>
      - ...
  is_registrar: true|false
  server: # This block is ONLY NEEDED IF THE PROVIDER CAN DEPLOY SERVERS
    resource_name: <resource_name_as_defined_in_terraform_docs> # REQUIRED! Name of the resource right after the word "resource" in the Terraform docs for a server
    remote_user: <ssh_user_of_provider> # REQUIRED! User that can SSH in after the server is provisioned
    ip_reference: <property_mapping_to_public_ip> # REQUIRED! IP reference property exported by the Terraform resource
    terry_defaults:
      server_size:
        global: '<global_size_reference_for_provider>' # REQUIRED! For example, AWS could be 't2.micro'
        teamserver: ... # Override global size
        lighthouse: ... # Override global size
        redirector: ... # Override global size
        categorize: ... # Override global size
        mailserver: ... # Override global size
        bare: ... # Override global size
      disk_size:
        global: <global_size_of_disk> # REQUIRED! For example, 32 for 32 GB of disk space 
        teamserver: ... # Override global size
        lighthouse: ... # Override global size
        redirector: ... # Override global size
        categorize: ... # Override global size
        mailserver: ... # Override global size
        bare: ... # Override global size

Adding a Resource

Following the design paradigms above from Home, to add a resource after adding the provider block follow these steps:

  1. If a folder for the provider does not exist inside templates/terraform/<provider_name>, create a folder for the provider using the same name as the <provider_name> as named in the Terraform mappings file. Use lowercase, no spaces, and no special characters.

  2. Inside that folder, create the resource type you want to add using the naming scheme <resource_type>.tf.j2 where the resource type is abstracted away from the provider naming scheme. For example, an AWS EC2 instance is just a server.

  3. Using the variables that will be passed from the click context, add the Jinja variables where needed.

And that is all, now you can use your new provider / resource with Terry!

Adding a Container

Adding a container that can be deployed through Terry is made to be easy. The container mappings file is a custom Docker Compose file that will be deployed by Terry at runtime. The customizations to the Docker compose are defined and explained below.

Deploying Containers

Each server deployed has the option to deploy an arbitrary number of containers to it. The containers that are available to be deployed are defined in the container mappings file. This file is a valid docker-compose.yml file with a few exceptions:

  • The presence of with the following properties: required_args, pre_run_commands, and post_run_commands
  • The use of "[[ ]]" inside of the file

I suggest reviewing Docker's documentation to learn more about Docker Compose.

Required Arguments

Property: required_args

These are arguments that must exist from either the configuration file, command line arguments, or environment variables. If they do not, Terry will ask you to input the value into standard input.

Pre and Post Run Commands

Property: pre_run_commands & post_run_commands

These are valid Ansible tasks that will run just before and just after spinning up a container. Some containers may require reading files from specific locations at runtime. Having these properties in the container mappings file allows the flexibility to run arbitrary Ansible tasks before and after starting a container.

Jinja Templating

Property: [[ <name> ]]

Because some of the containers require dynamic runtime arguments when started, there had to be a way to allow for Jinja templating inside of the Docker Compose file. However, if we use Jinja templates for variables that do not exist when the template is loaded, Ansible will throw an error. To alleviate that, every valid Jinja template has been replaced with square brackets and then will be replaced with valid Jinja templates and loaded once they are required.