Executors

The executor field provides different execution methods for each step. These executors are responsible for executing the commands or scripts specified in the command or script field of the step. Below are the available executors and their use cases.

At Examples, you can find a collection of sample DAGs that demonstrate how to use executors.

Running Docker Containers

Note: It requires Docker daemon running on the host.

The docker executor allows us to run Docker containers instead of bare commands. This can be useful for running commands in isolated environments or for reproducibility purposes.

In the example below, it pulls and runs Deno’s docker image and prints ‘Hello World’.

steps:
  - name: deno_hello_world
    executor:
      type: docker
      config:
        image: "denoland/deno:1.10.3"
        autoRemove: true
    command: run https://examples.deno.land/hello-world.ts

Example Log output:

https://raw.githubusercontent.com/ErdemOzgen/blackdagger/main/examples/images/docker.png

Configuring Container Volumes, Environment Variables, and More

You can config the Docker container (e.g., volumes, env, etc) by passing more detailed options.

For example:

steps:
  - name: deno_hello_world
    executor:
      type: docker
      config:
        image: "denoland/deno:1.10.3"
        container:
          volumes:
            /app:/app:
          env:
            - FOO=BAR
        host:
          autoRemove: true
    command: run https://examples.deno.land/hello-world.ts

See the Docker’s API documentation for all available options.

Running Containers on the Host’s Docker Environment

If you are running blackdagger using a container, you need the setup below.

  1. Run a socat conainer with the command below.

docker run -v /var/run/docker.sock:/var/run/docker.sock -p 2376:2375 bobrik/socat TCP4-LISTEN:2375,fork,reuseaddr UNIX-CONNECT:/var/run/docker.sock
  1. Then you can set the DOCKER_HOST environment as follows.

env:
  - DOCKER_HOST : "tcp://host.docker.internal:2376"
steps:
  - name: deno_hello_world
    executor:
      type: docker
      config:
        image: "denoland/deno:1.10.3"
        autoRemove: true
    command: run https://examples.deno.land/hello-world.ts

For more details, see this page.

Making HTTP Requests

The http executor allows us to make an arbitrary HTTP request. This can be useful for interacting with web services or APIs.

Behavior notes:

  • URL is required. If URL cannot be resolved from the command/args, execution fails early with a clear validation error.

  • Environment variable expansion is applied to command-derived method values, URL args, config body values, and query values.

  • This makes lifecycle callback patterns (for example with handlerOn) more reliable when values come from environment variables.

steps:
  - name: send POST request
    command: POST https://foo.bar.com
    executor:
      type: http
      config:
        timeout: 10,
        headers:
          Authorization: "Bearer $TOKEN"
        silent: true # If silent is true, it outputs response body only.
        query:
          key: "value"
        body: "post body"

Sending Webhooks

The webhook executor triggers external systems by sending HTTP requests with configurable method, headers, body, timeout, and accepted success status codes.

steps:
  - name: trigger deployment
    executor:
      type: webhook
      config:
        url: "https://example.org/hooks/deploy"
        method: "POST"
        timeout: 10
        headers:
          Authorization: "Bearer ${WEBHOOK_TOKEN}"
          Content-Type: "application/json"
        query:
          env: "prod"
        body: '{"service":"api","version":"1.2.3"}'
        successStatusCodes: [200, 202]
        silent: true

Running Terraform Commands

The terraform executor runs Terraform CLI commands for infrastructure workflows.

steps:
  - name: terraform_apply
    executor:
      type: terraform
      config:
        binary: terraform
        workingDir: ./infra
        init: true
        initArgs:
          - -upgrade
        subcommand: apply
        varFiles:
          - env/prod.tfvars
        vars:
          image_tag: "1.2.3"
          region: "us-east-1"
        targets:
          - module.app
        autoApprove: true
        env:
          TF_IN_AUTOMATION: "true"

Executing Ansible Playbooks

The ansible executor runs ansible-playbook for configuration management and deployment tasks.

steps:
  - name: run_ansible_playbook
    executor:
      type: ansible
      config:
        binary: ansible-playbook
        playbook: deploy/site.yml
        inventory: inventory/prod.ini
        tags:
          - deploy
          - app
        extraVars:
          image_tag: "1.2.3"
          environment: "prod"
        become: true
        forks: 20
        diff: true
        check: false
        env:
          ANSIBLE_STDOUT_CALLBACK: yaml

Sending Email

The mail executor can be used to send email. This can be useful for sending notifications or alerts.

Example:

smtp:
  host: "smtp.foo.bar"
  port: "587"
  username: "<username>"
  password: "<password>"

params: RECIPIENT=XXX

steps:
  - name: step1
    executor:
      type: mail
      config:
        to: <to address>
        from: <from address>
        subject: "Exciting New Features Now Available"
        message: |
          Hello [RECIPIENT],

          We hope you're enjoying your experience with MyApp!
          We're thrilled to announce that [] v2.0 is now available,
          and we've added some fantastic new features based on your
          valuable feedback.

          Thank you for choosing MyApp and for your continued support.
          We look forward to hearing from you and providing you with
          an even better MyApp experience.

          Best regards,

Executing jq Command

The jq executor can be used to transform, query, and format JSON. This can be useful for working with JSON data in pipelines or for data processing.

Query Example

steps:
  - name: run query
    executor: jq
    command: '{(.id): .["10"].b}'
    script: |
      {"id": "sample", "10": {"b": 42}}

Output:

{
    "sample": 42
}

Formatting JSON

steps:
  - name: format json
    executor: jq
    script: |
      {"id": "sample", "10": {"b": 42}}

Output:

{
    "10": {
        "b": 42
    },
    "id": "sample"
}

Command Execution over SSH

The ssh executor allows us to execute commands on remote hosts over SSH. Instead of key, you can use password field and enter your password of your remote host.

steps:
  - name: step1
    executor:
      type: ssh
      config:
        user: blackdagger
        ip: XXX.XXX.XXX.XXX
        port: 22
        key: /Users/blackdagger/.ssh/private.pem
    command: /usr/sbin/ifconfig

To run multiple commands at the same time, use the example below:

steps:
  - name: step1
    executor:
      type: ssh
      config:
        user: blackdagger
        ip: XXX.XXX.XXX.XXX
        port: 22
        key: /Users/blackdagger/.ssh/private.pem
    script: |
      echo "Executing multiple commands:"
      cp /etc/resolv.conf /tmp/x
      cat /tmp/x

Command Execution over WinRM

The winrm executor allows us to execute commands on remote Windows hosts over the WinRM protocol.

steps:
  - name: step1
    executor:
      type: winrm
      config:
        user: blackdagger
        password: yourpassword
        ip: XXX.XXX.XXX.XXX
        port: 5985
    command: ipconfig

To run multiple commands at the same time, use the example below:

steps:
  - name: step1
    executor:
      type: winrm
      config:
        user: blackdagger
        password: yourpassword
        ip: XXX.XXX.XXX.XXX
        port: 5985
    script: |
        Write-Host "Executing multiple commands:"
        Get-ChildItem C:\Windows
        ipconfig