ef8d284352
This commit is a significant change. TR.Run is now always executed, even for terminal allocations. This was changed to allow TR.Run to cleanup (run stop hooks) if a handle was recovered. This is intended to handle the case of Nomad receiving a DesiredStatus=Stop allocation update, persisting it, but crashing before stopping AR/TR. The commit also renames task runner hook data as it was very easy to accidently set state on Requests instead of Responses using the old field names.
99 lines
3.1 KiB
Go
99 lines
3.1 KiB
Go
package taskrunner
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
log "github.com/hashicorp/go-hclog"
|
|
"github.com/hashicorp/nomad/client/allocdir"
|
|
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
|
|
cconfig "github.com/hashicorp/nomad/client/config"
|
|
"github.com/hashicorp/nomad/client/taskenv"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
"github.com/hashicorp/nomad/plugins/drivers"
|
|
)
|
|
|
|
const (
|
|
// TaskDirHookIsDoneDataKey is used to mark whether the hook is done. We
|
|
// do not use the Done response value because we still need to set the
|
|
// environment variables every time a task starts.
|
|
// TODO(0.9.1): Use the resp.Env map and switch to resp.Done. We need to
|
|
// remove usage of the envBuilder
|
|
TaskDirHookIsDoneDataKey = "is_done"
|
|
)
|
|
|
|
type taskDirHook struct {
|
|
runner *TaskRunner
|
|
logger log.Logger
|
|
}
|
|
|
|
func newTaskDirHook(runner *TaskRunner, logger log.Logger) *taskDirHook {
|
|
td := &taskDirHook{
|
|
runner: runner,
|
|
}
|
|
td.logger = logger.Named(td.Name())
|
|
return td
|
|
}
|
|
|
|
func (h *taskDirHook) Name() string {
|
|
// Copied in client/state when upgrading from <0.9 schemas, so if you
|
|
// change it here you also must change it there.
|
|
return "task_dir"
|
|
}
|
|
|
|
func (h *taskDirHook) Prestart(ctx context.Context, req *interfaces.TaskPrestartRequest, resp *interfaces.TaskPrestartResponse) error {
|
|
fsi := h.runner.driverCapabilities.FSIsolation
|
|
if v, ok := req.PreviousState[TaskDirHookIsDoneDataKey]; ok && v == "true" {
|
|
setEnvvars(h.runner.envBuilder, fsi, h.runner.taskDir, h.runner.clientConfig)
|
|
resp.State = map[string]string{
|
|
TaskDirHookIsDoneDataKey: "true",
|
|
}
|
|
return nil
|
|
}
|
|
|
|
cc := h.runner.clientConfig
|
|
chroot := cconfig.DefaultChrootEnv
|
|
if len(cc.ChrootEnv) > 0 {
|
|
chroot = cc.ChrootEnv
|
|
}
|
|
|
|
// Emit the event that we are going to be building the task directory
|
|
h.runner.EmitEvent(structs.NewTaskEvent(structs.TaskSetup).SetMessage(structs.TaskBuildingTaskDir))
|
|
|
|
// Build the task directory structure
|
|
err := h.runner.taskDir.Build(fsi == drivers.FSIsolationChroot, chroot)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update the environment variables based on the built task directory
|
|
setEnvvars(h.runner.envBuilder, fsi, h.runner.taskDir, h.runner.clientConfig)
|
|
resp.State = map[string]string{
|
|
TaskDirHookIsDoneDataKey: "true",
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// setEnvvars sets path and host env vars depending on the FS isolation used.
|
|
func setEnvvars(envBuilder *taskenv.Builder, fsi drivers.FSIsolation, taskDir *allocdir.TaskDir, conf *cconfig.Config) {
|
|
// Set driver-specific environment variables
|
|
switch fsi {
|
|
case drivers.FSIsolationNone:
|
|
// Use host paths
|
|
envBuilder.SetAllocDir(taskDir.SharedAllocDir)
|
|
envBuilder.SetTaskLocalDir(taskDir.LocalDir)
|
|
envBuilder.SetSecretsDir(taskDir.SecretsDir)
|
|
default:
|
|
// filesystem isolation; use container paths
|
|
envBuilder.SetAllocDir(allocdir.SharedAllocContainerPath)
|
|
envBuilder.SetTaskLocalDir(allocdir.TaskLocalContainerPath)
|
|
envBuilder.SetSecretsDir(allocdir.TaskSecretsContainerPath)
|
|
}
|
|
|
|
// Set the host environment variables for non-image based drivers
|
|
if fsi != drivers.FSIsolationImage {
|
|
filter := strings.Split(conf.ReadDefault("env.blacklist", cconfig.DefaultEnvBlacklist), ",")
|
|
envBuilder.SetHostEnvvars(filter)
|
|
}
|
|
}
|