You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: controller.go
    path of file: ./repos/docker-ce/components/engine/vendor/github.com/docker/swarmkit/agent/exec
    
    the code of the file until where you have to start completion: package exec

import (
	"context"
	"fmt"
	"time"

	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/api/equality"
	"github.com/docker/swarmkit/log"
	"github.com/docker/swarmkit/protobuf/ptypes"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// Controller controls execution of a task.
type Controller interface {
	// Update the task definition seen by the controller. Will return
	// ErrTaskUpdateFailed if the provided task definition changes fields that
	// cannot be changed.
	//
	// Will be ignored if the task has exited.
	Update(ctx context.Context, t *api.Task) error

	// Prepare the task for execution. This should ensure that all resources
	// are created such that a call to start should execute immediately.
	Prepare(ctx context.Context) error

	// Start the target and return when it has started successfully.
	Start(ctx context.Context) error

	// Wait blocks until the target has exited.
	Wait(ctx context.Context) error

	// Shutdown requests to exit the target gracefully.
	Shutdown(ctx context.Cont
    
func Resolve(ctx context.Context, task *api.Task, executor Executor) (Controller, *api.TaskStatus, error) {
	status := task.Status.Copy()

	defer func() {
		logStateChange(ctx, task.DesiredState, task.Status.State, status.State)
	}()

	ctlr, err := executor.Controller(task)

	// depending on the tasks state, a failed controller resolution has varying
	// impact. The following expresses that impact.
	if err != nil {
		status.Message = "resolving controller failed"
		status.Err = err.Error()
		// before the task has been started, we consider it a rejection.
		// if task is running, consider the task has failed
		// otherwise keep the existing state
		if task.Status.State < api.TaskStateStarting {
			status.State = api.TaskStateRejected
		} else if task.Status.State <= api.TaskStateRunning {
			status.State = api.TaskStateFailed
		}
	} else if task.Status.State < api.TaskStateAccepted {
		// we always want to proceed to accepted when we resolve the controller
		status.Message = "accepted"
		status.State = api.TaskStateAccepted
		status.Err = ""
	}

	return ctlr, status, err
}