Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Writing a custom provider definition

Create an empty directory and make it your working directory:

mkdir rtf-custom-provider
cd rtf-custom-provider

Create an empty YAML file for the custom provider definition:

touch my-provider.yaml

We will now step through creating a simple custom provider definition.

Adding required fields

A custom provider definition has three required fields: name, description, and command. The sections below add each of these required fields and explain them in more detail.

name

Add the name field to the my-provider.yaml file:

name: env-generator

name is used to give each custom provider an identifiable title. It can be any valid string. The value used for the name field has no impact on the execution of the custom provider. This makes it easier to work with the custom provider programmatically.

description

Add the description field to the my-provider.yaml file:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)

description is used to give more information about the custom provider for future users. It can be any valid string. The value used for the description field has no impact on the execution of the custom provider itself. This is a useful place to document what files the provider generates and how they should be used.

command

The command is used to define what will be executed when the custom provider runs. The command is responsible for generating output files in the $RTF_OUTPUT directory.

Add the command field to the my-provider.yaml file:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)

command:
  name: generate.sh
  kind: relative_path
  path: scripts/generate.sh

This references a script file that we will create in the custom provider commands section. Before we can run the custom provider, we need to create this script.

Custom provider commands

Before we can run the custom provider, we need to create the script referenced in the command section. Create a scripts directory and the generate.sh file:

mkdir scripts
touch scripts/generate.sh

Add the following content to scripts/generate.sh:

#!/usr/bin/env bash
set -e

mkdir -p "$RTF_OUTPUT"

cat > "$RTF_OUTPUT/ENV_VARS.txt" << EOF
# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="default-project"
export LOG_LEVEL="info"
EOF

echo "Generated environment config in $RTF_OUTPUT"

This script does the following:

  • Creates the output directory using the $RTF_OUTPUT environment variable, which is automatically set by rtf to the directory where output files should be written. All custom provider command scripts must write to this location.
  • Writes an ENV_VARS.txt file with environment variable exports that can be sourced by downstream scripts. This is not a required pattern for a custom provider but can be useful in many use cases which is why it is included in this guide.
  • Prints a message confirming the generation was successful.

The key difference between a command in a custom provider and one in a config file is that the command in a custom provider MUST write one or more files to RTF_OUTPUT. Commands in config files perform an action, for example, setting up an environment, whereas commands in a custom provider write files for config files to make use of.

Make the script executable:

chmod +x scripts/generate.sh

Your directory structure should now look like this:

ls -R
my-provider.yaml scripts

./scripts:
generate.sh

Checking the custom provider

Now, let’s check that the custom provider has been defined correctly:

rtf custom-provider template my-provider.yaml

This should result in the fully templated custom provider being printed to the terminal:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)
variable_definitions: []
command:
  name: generate.sh
  kind: relative_path
  path: scripts/generate.sh
  args: []
env_vars: {}
file_providers: []

This highlights the optional fields for custom providers that have not yet been used: variable_definitions, env_vars, and file_providers. These are discussed in the following sections.

Running the custom provider

Before looking at the optional fields, let’s run the custom provider:

rtf custom-provider run my-provider.yaml

You should see output similar to this:

Generated environment config in /path/to/rtf-custom-provider/output/RTF_OUTPUT

The output directory contains the generated files. Let’s examine what was created:

cat output/RTF_OUTPUT/ENV_VARS.txt

Output:

# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="default-project"
export LOG_LEVEL="info"

Remove the output directory before continuing:

rm -rf output/

Note rtf is deliberately configured to not overwrite an existing output directory. This is so you cannot accidentally overwrite output you intend to keep. The --output flag can be used with rtf custom-provider run to set a different output directory if you want to keep the existing output and run a new test.

Defining variables

The variable_definitions field is used to define parameters that the custom provider accepts. When the custom provider is used in a test plan, these variables are passed as arguments. The using a custom provider guide covers how to pass arguments to a custom provider in detail.

For now, let’s add a variable to make the project name configurable. We are also going to update the script to use this variable. The env_vars field is used to pass variable values to the command as environment variables.

Update my-provider.yaml:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)

# --- Add variable definitions ---
variable_definitions:
  - name: project_name
    description: "The name of the project"
# --------------------------------

command:
  name: generate.sh
  kind: relative_path
  path: scripts/generate.sh

# --- Add env_vars to pass variables to the command ---
env_vars:
  PROJECT_NAME: "{{ project_name }}"
# -----------------------------------------------------

Update scripts/generate.sh to use the environment variable:

#!/usr/bin/env bash
set -e

mkdir -p "$RTF_OUTPUT"

cat > "$RTF_OUTPUT/ENV_VARS.txt" << EOF
# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="$PROJECT_NAME"
EOF

echo "Generated environment config in $RTF_OUTPUT"

Now run the custom provider with the --var flag to set the variable:

rtf custom-provider run my-provider.yaml --var project_name=my-app

Output:

Generated environment config in /path/to/rtf-custom-provider/output/RTF_OUTPUT
cat output/RTF_OUTPUT/ENV_VARS.txt

Output:

# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="my-app"

The project_name variable is now configurable. Remove the output directory before continuing:

rm -rf output/

Adding a default value

Variables can have default values, like in config files. Let’s add a log_level variable with a default value of "info".

Update my-provider.yaml:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)

variable_definitions:
  - name: project_name
    description: "The name of the project"

# --- Add a variable with a default ---
  - name: log_level
    description: "Logging verbosity level"
    default: "info"
# -------------------------------------

command:
  name: generate.sh
  kind: relative_path
  path: scripts/generate.sh

env_vars:
  PROJECT_NAME: "{{ project_name }}"
# --- Add LOG_LEVEL ---
  LOG_LEVEL: "{{ log_level }}"
# ---------------------

Update scripts/generate.sh:

#!/usr/bin/env bash
set -e

mkdir -p "$RTF_OUTPUT"

cat > "$RTF_OUTPUT/ENV_VARS.txt" << EOF
# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="$PROJECT_NAME"
export LOG_LEVEL="$LOG_LEVEL"
EOF

echo "Generated environment config in $RTF_OUTPUT"

Now run the custom provider without specifying log_level:

rtf custom-provider run my-provider.yaml --var project_name=my-app

Output:

Generated environment config in /path/to/rtf-custom-provider/output/RTF_OUTPUT
cat output/RTF_OUTPUT/ENV_VARS.txt

Output:

# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="my-app"
export LOG_LEVEL="info"

The default value "info" is used. You can override it by passing --var log_level=debug.

Remove the output directory before continuing:

rm -rf output/

Using file providers

The file_providers field is used to make files available to the command script. Each file provider creates a file and sets an environment variable containing the path to that file. This allows the command script to read input files or copy template files to the output directory.

Let’s add a base configuration file that the command will copy to the output. Update my-provider.yaml:

name: env-generator
description: |
  Generates an ENV_VARS.txt file with configuration for downstream scripts.

  Output directory contains:
  - ENV_VARS.txt (environment variables for setup scripts)
  - base-config.txt (a base configuration file)

variable_definitions:
  - name: project_name
    description: "The name of the project"

  - name: log_level
    description: "Logging verbosity level"
    default: "info"

command:
  name: generate.sh
  kind: relative_path
  path: scripts/generate.sh

# --- Add file providers ---
file_providers:
  - name: base-config.txt
    env_var: BASE_CONFIG
    kind: inline
    content: |
      # Base configuration
      # Project-specific values set via ENV_VARS.txt
# -------------------------

env_vars:
  PROJECT_NAME: "{{ project_name }}"
  LOG_LEVEL: "{{ log_level }}"

The file provider defines:

  • name: The filename used when the file is written to the providers directory.
  • env_var: The environment variable that will contain the path to the file.
  • kind: The type of file provider. Here we use inline to define the content directly.
  • content: The file content (for inline providers).

Update scripts/generate.sh to copy the base config to the output:

#!/usr/bin/env bash
set -e

mkdir -p "$RTF_OUTPUT"

cat > "$RTF_OUTPUT/ENV_VARS.txt" << EOF
# Environment variables for project setup
# Generated by env-generator provider

export PROJECT_NAME="$PROJECT_NAME"
export LOG_LEVEL="$LOG_LEVEL"
export BASE_CONFIG="$RTF_OUTPUT/base-config.txt"
EOF

# Copy the base config to output
cp "$BASE_CONFIG" "$RTF_OUTPUT/base-config.txt"

echo "Generated environment config in $RTF_OUTPUT"

Now run the custom provider:

rtf custom-provider run my-provider.yaml --var project_name=my-app

Output:

Generated environment config in /path/to/rtf-custom-provider/output/RTF_OUTPUT
cat output/RTF_OUTPUT/base-config.txt

Output:

# Base configuration
# Project-specific values set via ENV_VARS.txt

The base configuration file is now included in the output. Remove the output directory before continuing:

rm -rf output/

This completes the custom provider definition.


In this guide we have covered writing a simple custom provider definition. Next, we will guide you through how to use it in a test plan.

Next: Using a custom provider