Does ExecTask Work?

I’ve been implementing a custom task driver to run VMs on macOS and I wanted to make sure that you could click the ‘exec’ button from within the Nomad UI and run a quick command line invocation on that target VM.

I’ve found the docs Task Driver Plugins | Nomad | HashiCorp Developer that simply state that you should be able to implement that interface, and set your capabilities correctly, and it just works.

However, I can’t seem to get it to work at all…

My driver implementation returns the “Exec” capability, and has this implementation for the ExecTask function

// ExecTask returns the result of executing the given command inside a task.
func (d *Driver) ExecTask(taskID string, cmd []string, timeout time.Duration) (*drivers.ExecTaskResult, error) {
	d.logger.Info("executing command inside task", "task_id", taskID, "cmd", cmd)
	handle, ok := d.tasks.Get(taskID)
	if !ok {
		return nil, drivers.ErrTaskNotFound
	}

	var taskConfig TaskConfig
	if err := handle.taskConfig.DecodeDriverConfig(&taskConfig); err != nil {
		return nil, fmt.Errorf("failed to decode driver config: %v", err)
	}

	allocVMName := d.generateVMName(handle.taskConfig.AllocID)
	output, stderr, err := d.virtualizer.SSH(d.ctx, allocVMName, taskConfig.SSHUser, taskConfig.SSHPassword, strings.Join(cmd, " "))
	if err != nil {
		return nil, fmt.Errorf("failed to execute SSH command on VM %s: %v (stderr: %s)",
			allocVMName, err, stderr)
	}

	return &drivers.ExecTaskResult{
		Stdout: []byte(output),
		Stderr: []byte(stderr),
		ExitResult: &drivers.ExitResult{
			ExitCode: 0,
		},
	}, nil
}

Whenever I run something like nomad alloc exec 13867d0b-07c4-3bfc-0781-3f0f46be9cea /bin/echo "test" I always get failed to exec into task: rpc error: code = Unknown desc = driver does not support exec. The server logs seem to indicate that my ExecTask function is never called:

   2025-06-07T23:29:15.029-0400 [DEBUG] http: request complete: method=GET path=/v1/allocations?prefix=13867d0b-07c4-3bfc-0781-3f0f46be9cea duration="154.208µs"
    2025-06-07T23:29:15.030-0400 [DEBUG] http: request complete: method=GET path=/v1/allocation/13867d0b-07c4-3bfc-0781-3f0f46be9cea?namespace=default duration="144.584µs"
    2025-06-07T23:29:15.031-0400 [DEBUG] http: request complete: method=GET path=/v1/node/25c3fdd0-9ba7-2fef-ab52-cd83a761ac82 duration="109.542µs"
    2025-06-07T23:29:15.032-0400 [INFO]  client: task exec session starting: exec_id=0dee9712-73b8-4f76-08ed-2e120c04bec4 alloc_id=13867d0b-07c4-3bfc-0781-3f0f46be9cea task=vm command=["/bin/echo", "test"] tty=true action=""
    2025-06-07T23:29:15.033-0400 [INFO]  client.driver_mgr.nomad-driver-tart: CAPABILITIES DEBUG: driver=tart @module=tart exec=true send_signals=false timestamp=2025-06-07T23:29:15.033-0400
    2025-06-07T23:29:15.033-0400 [INFO]  client: task exec session ended with an error: error="rpc error: code = Unknown desc = driver does not support exec" code=0x14000559da8
    2025-06-07T23:29:15.033-0400 [ERROR] http: request failed: method=GET path="/v1/client/allocation/13867d0b-07c4-3bfc-0781-3f0f46be9cea/exec?command=%5B%22%2Fbin%2Fecho%22%2C%22test%22%5D&region=global&task=vm&tty=true" error="rpc error: code = Unknown desc = driver does not support exec" code=500
    2025-06-07T23:29:15.033-0400 [DEBUG] http: request complete: method=GET path="/v1/client/allocation/13867d0b-07c4-3bfc-0781-3f0f46be9cea/exec?command=%5B%22%2Fbin%2Fecho%22%2C%22test%22%5D&region=global&task=vm&tty=true" duration="655.208µs"

At this point I’m just scratching my head as to what I have to implement to get this working in a very minimal way. I’d love advice!

I ended up finding this issue nomad-driver-containerd: Issue with ExecTask API · Issue #8022 · hashicorp/nomad · GitHub which I’m going to try to implement myself. If this is the case I’ll file an issue to make the docs much clearer.