Using Drivers

Drivers in Essh are template system to construct shell scripts in tasks execution. In this tutorial, You have already used default built-in driver that is included in Essh binary. You can use a custom driver to modify behavior of tasks.

To understand what drivers do, see the following short example:

task "example" {
    script = {
        "echo aaa",
        "echo bbb",
    }
}

Try to run this task with --debug option to display the actual script.

$ essh example --debug
...
[essh debug] run task: example
[essh debug] driver: default 
[essh debug] real local command: [bash -c 
export ESSH_TASK_NAME='example'
export ESSH_SSH_CONFIG=/var/folders/bt/xwh9qmcj00dctz53_rxclgtr0000gn/T/essh.ssh_config.767200705
export ESSH_DEBUG="1"

echo aaa
echo bbb
]

According to the debug messages, the task ran the following bash script:

export ESSH_TASK_NAME='example'
export ESSH_SSH_CONFIG=/var/folders/bt/xwh9qmcj00dctz53_rxclgtr0000gn/T/essh.ssh_config.767200705
export ESSH_DEBUG="1"

echo aaa
echo bbb

This contents was generated by the built-in driver. The built-in driver is the following text template that is included in Essh binary:

{{template "environment" .}}
{{range $i, $script := .Scripts}}{{$script.code}}
{{end}}

{{template "environment" .}} generates environment variables section. In the above example, this section becomes the following code:

export ESSH_TASK_NAME='example'
export ESSH_SSH_CONFIG=/var/folders/bt/xwh9qmcj00dctz53_rxclgtr0000gn/T/essh.ssh_config.767200705
export ESSH_DEBUG="1"

And after that, Essh concatenates script texts with new line code.

{{range $i, $script := .Scripts}}{{$script.code}}
{{end}}

The above code becomes the following:

echo aaa
echo bbb

Then, Try to define your first custom driver using driver function.

driver "my_driver" {
    engine = [=[
        {{template "environment" .}}
        
        set -e
        indent() {
            local n="${1:-4}"
            local p=""
            for i in `seq 1 $n`; do
                p="$p "
            done;

            local c="s/^/$p/"
            case $(uname) in
              Darwin) sed -l "$c";;
              *)      sed -u "$c";;
            esac
        }
        
        {{range $i, $script := .Scripts -}}
        echo '==> step {{$i}}:{{if $script.description}} {{$script.description}}{{end}}'
        { 
            {{$script.code}} 
        } | indent; __essh_exit_status=${PIPESTATUS[0]}
        if [ $__essh_exit_status -ne 0 ]; then
            exit $__essh_exit_status
        fi
        {{end}}
    ]=],
}

task "example" {
    driver = "my_driver",
    script = {
        "echo aaa",
        "echo bbb",
    }
}

driver function needs the required parameter engine. This is the template text. To use your custom driver, you need to set task’s driver property.

In this example, the driver outputs a step number and description, and indented script’s stdout. If you run the above task, you will get the following outputs.

==> step 0:
    aaa
==> step 1:
    bbb

The description hasn’t be displayed yet. You can set description property to each script’s code.

task "example" {
    driver = "my_driver",
    script = {
        {
            description = "output aaa",
            code = "echo aaa",
        },
        {
            description = "output bbb",
            code = "echo bbb",
        },
    }
}

This code outputs the result like the following.

==> step 0: output aaa
    aaa
==> step 1: output bbb
    bbb

For more information on drivers, see the Drivers section.

Next Steps

In the Introduction guide, I have explained the basic features of Essh. If you want to get in-depth information about Essh, read the documentation.

Enjoy!