Skip to content

Creating a provider plugin

In this guide you’ll learn how to build a provider plugin.

Introduction

In this guide, you will learn about the basic components needed to create and use a packaged provider plugin. To focus this guide on the components needed to package the plugin, the functionality of the plugin’s code is minimal. The plugin provides a function that prints “Hello World” in the logs or “Hello {who-to-greet}” if you provide a custom name.

This guide uses the OpenTestFactory Orchestrator Toolkit module to speed up development. For more information, see the opentestfactory/python-toolkit repository.

Once you complete this project, you should understand how to build your own provider plugin and test it in a workflow.

To ensure your plugins are compatible with all OpenTestFactory Orchestrator deployments (linux, windows, …), the packaged code you write should be pure and not rely on other non-portable binaries.

Prerequisites

You may find it helpful to have a basic understanding of the OpenTestFactory Orchestrator environment variables:

Before you begin, you’ll need to create a repository.

  1. Create a new repository on GitHub/Gitlab/BitBucket/.... You can choose any repository name or use “hello-world-provider-plugin” like this example.
  2. Clone your repository to your computer.
  3. From your terminal, change directories into your new repository.
cd hello-world-provider-plugin

Create a web service

Provider plugins are simple web services. They subscribe to specific events on startup, and publish events in response.

The opentf-toolkit module streamlines the process if you want to write your plugin in Python. For more information on doing things in a less assisted way, see “Writing plugins the hard way.”

In your new hello-world-provider-plugin directory, create a new main.py file.

main.py

# main.py
from opentf.toolkit import make_plugin, run_plugin

from .implementation import handler

plugin = make_plugin(
    name='helloworld',
    description='A helloworld provider.',
    provider=handler
)

if __name__ == '__main__':
    run_plugin(plugin)

Create a plugin metadata file

Create a new plugin.yaml file in the hello-world-provider-plugin directory you created above. For more information, see “Metadata syntax for OpenTestFactory Orchestrator plugins.”

This files describes the functions your plugin implements.

plugin.yaml

# plugin.yaml
apiVersion: 'opentestfactory.org/v1alpha1'
kind: 'ProviderPlugin'
metadata:
  name: 'HelloWorld'
  description: 'Greet someone'
cmd: 'python3 -m main'
events:
- categoryPrefix: helloworld
  category: greet
  categoryVersion: v1
inputs:
  who-to-greet:
    description: 'Who to greet'
    required: false
    default: 'World'
outputs:
  random-number:
    description: 'Random number'
    value: ${{ steps.random-number-generator.outputs.random-id }}

Writing the plugin code

Provider plugin functions must return a possibly empty list of steps. Each step has a definition. For more information about the steps syntax, see “Workflow syntax for OpenTestFactory Orchestrator.”

The following Python script example uses the who-to-greet input variable to print “Hello {who-to-greet}” in the log file and maps the random generated number to the random-number output variable.

implementation.py

# implementation.py

def handler(inputs):
  steps = [
    {
      'run': 'echo Hello ' + inputs['who-to-greet'] + '.',
      'shell': 'bash'
    },
    {
      'id': 'random-number-generator',
      'run': 'echo "::set-output name=random-id::$(echo $RANDOM)"',
      'shell': 'bash'
    }
  ]
  return steps

Create a README

To let people know how to use your plugin, you can create a README file. A README is most helpful when you plan to share your plugin publicly, but is also a great way to remind you or your team how to use the plugin’s functions.

In your hello-world-provider-plugin directory, create a README.md file that specifies the following information:

  • A detailed description of what the plugin’s function does.
  • Required input and output arguments.
  • Optional input and output arguments.
  • Environment variables the function uses.
  • An example of how to use your function in a workflow.

README.md

# Hello world function

This function prints "Hello World" or "Hello" + the name of a person to greet to
the log.

## Inputs

### `who-to-greets`

**Required** The name of the person to greet.  Default `"World"`.

## Outputs

###  `random-id`

A random number.

## Example usage

uses: helloworld/greet@v1
with:
  who-to-greets: 'Mona the Octocat'

Commit, tag, push, and deploy your plugin

From your terminal, commit your plugin.yaml, implementation.py, helloworld.py, and README.md files.

It is best practice to also add a version tag for releases of your plugin. For more information on versioning your plugin, see “About plugins.”

git add plugin.yaml implementation.py helloworld.py README.md
git commit -m "My first plugin is ready"
git tag -a -m "My first plugin release" v1
git push --follow-tags

Deploy your plugin

TODO (Deploy)

Testing out your plugin’s function in a workflow

Now you are ready to test your function out in a workflow.

Example

jobs:
  hello_world_job:
    runs-on: linux
    name: A job to say hello
    steps:
    - uses: helloworld/greet@v1
      with:
        who-to-greets: "Mona the Octocat"