Skip to content

Module best practices

Terrareg has been extensively tested with Terraform modules of all shapes and sizes, meaning that it should be able to provide valuable information without any modification to modules before indexing.

However, to get the most out of Terrareg, there are some practices/guides that will help.

Markdown

Markdown files can be indexed and shown as tabs.

The README.md in a root module, sub-modules and examples are indexed by default.

Additional markdown files can be indexed and shown as tabs using ADDITIONAL_MODULE_TABS

Code blocks are shown with syntax highlighting, with the following supported languages:

  • hcl
  • css
  • bash
  • batch
  • docker
  • hcl
  • plsql
  • powershell
  • python
  • sql

Auto-detection of languages is used, but it's safest to write with language-helper markup, e.g.:

```hcl
terraform {
  required_version = "0.1.2
}
```

```bash
#!/bin/bash

echo Some bash script
```

Terrareg metadata file

A metadata file can be provided each an uploaded module's archive to provide additional metadata to terrareg.

This should be called terrareg.json or .terrareg.json and be placed in the root of the module.

For an example, please see: ../example-terrareg-module-metadata.json

The following attributes are available at the root of the JSON object:

Key Description
owner Name of the owner of the module
description Description of the module.
variable_template Structure holding required input variables for module, used for 'Usage Builder'. See table below
repo_clone_url Url to clone the repository. Optional placeholders {namespace}, {module} and {provider} can be used. E.g. ssh://gitlab.corporate.com/scm/{namespace}/{module}.git
repo_base_url Formatted base URL for project's repo. E.g. https://gitlab.corporate.com/{namespace}/{module}
repo_browse_url Formatted URL for user-viewable source code. Must contain {tag} and {path} placeholders. E.g. https://github.com/{namespace}/{module}-{provider}/blob/{tag}/{path}

For information on the repo URLs, see Git Providers

Each of these attributes can be enforced in modules uploaded to the registry by setting REQUIRED_MODULE_METADATA_ATTRIBUTES.

Description

If a metadata file is not present or a description is not provided, Terrareg will attempt to automatically generate a description of the module, using the README.md from the module.

This functionality can be disabled by setting AUTOGENERATE_MODULE_PROVIDER_DESCRIPTION.

Usage builder configuration

The usage builder requires an array of objects, which define the name, type and description of the variable.

In the following the 'config input' refers to the HTML inputs that provide the user with the ability to select/enter values. The 'terraform input' refers to the value used for the variable in the outputted terraform example.

There are common attributes that can be added to each of variable objects, which include:

Attribute Description Default
name The name of the 'config input'. This is also used as the module variable in the 'terraform input'. Required
type The type of the input variable, see table below. Required
required Boolean flag to determine whether the variable is Required. true
quote_value Boolean flag to determine whether the value generated is quoted for the 'terraform input'. false
additional_help A description that is provided, along with the terraform variable description in the usage builder ""
default_value The default value if required is false null
Variable type Description Type specific attributes
text A plain input text box for users to provide a value that it directly used as the 'terraform input'
boolean Provides a checkbox that results in a true/false value as the 'terraform input'
static This does not appear in the 'Usage Builder' 'config input' table, but provides a static value in the 'terraform input'
select Provides a dropdown for the user to select from a list of choices "choices" must be added to the object, which may either be a list of strings, or a list of objects. If using a list of objects, a "name" and "value" must be provided. Optionally an "additional_content" attribute can be added to the choice, which provides additional terraform to be added to the top of the terraform example. The main variable object may also contain a "allow_custom" boolean attribute, which allows the user to enter a custom text input.

Terrareg will automatically generated usage builder inputs based on discovered variables in the module. This functionality can be disabled by setting AUTOGENERATE_USAGE_BUILDER_VARIABLES

Submodules

By default, sub-modules are located in individual sub-directories of the modules directory of the module, e.g.:

 <Root of Module>
 |
 | -> modules
 |    |
 |    | -> s3
 |    |    |
 |    |     -> main.tf
 |    |
 |    | -> route53
 |    |    |
 |    |     -> main.tf

This directory can be changed on a global level with MODULES_DIRECTORY

Examples

By default, examples are located in individual sub-directories of the examples directory of the module, e.g.:

 <Root of Module>
 |
 | -> examples
 |    |
 |    | -> basic
 |    |    |
 |    |     -> main.tf
 |    |
 |    | -> complete
 |    |    |
 |    |     -> main.tf

This directory can be changed on a global level with EXAMPLES_DIRECTORY

Variable defaults

During indexing, cost analysis checks are performed against each example.

To perform this accurately, it is best to ensure examples do not have any required variables - either with no variables present in the example or ensuring all variables have a 'default' value.

Usage of main.tf

Each of the Terraform files in the example is shown in the UI in alphabetical order, exception for main.tf, which is displayed first.

It is recommended to put the 'main' functionality of the example (e.g. the call to the root module and other crucial code to demonstrate) in the main.tf, putting any 'supporting' terraform (state configuration etc.) into seperate files.

Relative module calls

We recommend using relative paths in the source of the "module blocks" in the examples (that call the local module's root/submodules).

The Terrareg automatically converts this before displaying to users in the web interface, replacing the relative source path with a URL to the module's path within the registry and adds a version constraint.

E.g., for an example with the code:

/examples/basic_vpc/main.tf:

module "network" {
  source = "../../"

  vpc = module.vpc.vpc_id
}

module "vpc" {
  source = "../../modules/vpc"

  cidr = "10.0.0.0/24"
}

will be rewritten in the UI to:

/examples/basic_vpc/main.tf:

module "network" {
  source  = "my-registry.example.com/mynamespace/mymodule/myprovider"
  version = ">= 1.5.0, < 2.0.0"

  vpc = module.vpc.vpc_id
}

module "vpc" {
  source  = "my-registry.example.com/mynamespace/mymodule/myprovider//modules/vpc"
  version = ">= 1.5.0, < 2.0.0"

  cidr = "10.0.0.0/24"
}

Note: We also recommend using a single line break before any variables being passing into the module call, as this results in a more consistent styling of the rewritten code.

The version constraint template can be modified by setting TERRAFORM_EXAMPLE_VERSION_TEMPLATE.