Skip to content

Plugin Development

The chaos CLI is designed to be minimal and modular. Most functionality is provided through external plugins. This guide covers the basics of creating your own plugin.

A plugin is a standard Python package that uses entry points to register its functionality with chaos.

Project Structure

A basic plugin has the following structure:

my-chaos-plugin/
├── pyproject.toml
└── src/
    └── my_chaos_plugin/
        ├── __init__.py
        ├── roles.py
        └── explain.py

pyproject.toml

The pyproject.toml file is where you define your plugin's metadata and, most importantly, its entry points.

[project]
name = "my-chaos-plugin"
version = "0.1.0"
description = "A new plugin for Ch-aOS."
requires-python = ">=3.10"

[project.entry-points]
# Entry points are defined here
"chaos.roles" = { my-role = "my_chaos_plugin.roles:my_role_function" }
"chaos.explain" = { my-role = "my_chaos_plugin.explain:MyRoleExplain" }
"chaos.aliases" = { mr = "my-role" }
"chaos.keys" = { my-role = "my_chaos_plugin.roles:my_role_keys" }
"chaos.providers" = { myprovider = "my_chaos_plugin.providers:MyProviderClass" }

Entry Points

Ch-aOS uses several entry point groups to discover plugin functionality.

chaos.roles

This is the most important entry point. It registers a role that can be executed with chaos apply.

  • Key: The name of the role tag (e.g., my-role).
  • Value: A string pointing to a Python function in the format path.to.module:function_name.

This function will be called by chaos and should contain your pyinfra operations.

Example roles.py:

from pyinfra.operations import server

def my_role_function(state, host, chobolo_path, skip_confirm):
    """
    A simple role that ensures a directory exists.
    """
    # In a real role, you would load data from the chobolo_path
    # from omegaconf import OmegaConf
    # config = OmegaConf.load(chobolo_path)
    # my_dirs = config.get('my_role_dirs', [])

    server.dir(
        name="Ensure /tmp/my-role-dir exists",
        path="/tmp/my-role-dir",
        present=True,
        user="root",
        mode="755",
    )

chaos.explain

Registers a class that provides documentation for your role, accessible via chaos explain.

  • Key: The topic name, which should usually match your role's tag (e.g., my-role).

  • Value: A string pointing to a Python class in the format path.to.module:ClassName.

The class should contain methods named explain_<subtopic> that return a dictionary with the explanation content.

Example explain.py:

class MyRoleExplain:
    _order = ['usage'] # Controls the order in `explain my-role.list`

    def explain_my_role(self, detail_level='basic'):
        return {
            'concept': 'My Custom Role',
            'what': 'This role ensures a specific directory exists.',
            'why': 'To demonstrate how to create a Ch-aOS plugin.',
            'how': 'It uses the `server.dir` operation from pyinfra.',
        }

    def explain_usage(self, detail_level='basic'):
        return {
            'concept': 'Usage Example',
            'examples': [{
                'yaml': '# Run the role\nchaos apply my-role'
            }]
        }

chaos.aliases

Registers a shorter alias for a role tag.

  • Key: The alias (e.g., mr).

  • Value: The full role tag it points to (e.g., my-role).

Now you can run chaos apply mr instead of chaos apply my-role.

chaos.keys

Registers the configuration keys that your role uses. This allows chaos init chobolo to automatically include them in the generated template.

  • Key: The name of the role tag (e.g., my-role).

  • Value: A string pointing to a Python object (usually a list of dictionaries) in the format path.to.module:object_name.

Example roles.py:

# ... (imports and my_role_function)

# This is the object that will be exposed to `chaos init chobolo`
my_role_keys = [{
    'my_role_dirs': [
        '/tmp/dir1',
        '/tmp/dir2',
    ]
}]

chaos.providers

Registers a new secret provider. This is a more advanced topic that requires implementing a class that inherits from the base Provider class. See Plugin Providers for examples.

chaos.boats

Registers a new boat for use with chaos apply --fleet. This is an advanced topic for managing fleets of hosts. See Boat Plugins for more details.