mirror of
https://github.com/kemko/nomad.git
synced 2026-01-09 03:45:41 +03:00
Fixes an issue where if a task was restarted after restating the client, the task dir environment variables would not be populated. This PR fixes this for both upgrades from 0.8.X and for normal 0.9 restarts.
100 lines
3.2 KiB
Go
100 lines
3.2 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 {
|
|
if v, ok := req.HookData[TaskDirHookIsDoneDataKey]; ok && v == "true" {
|
|
fsi := h.runner.driverCapabilities.FSIsolation
|
|
setEnvvars(h.runner.envBuilder, fsi, h.runner.taskDir, h.runner.clientConfig)
|
|
resp.HookData = 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
|
|
fsi := h.runner.driverCapabilities.FSIsolation
|
|
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.HookData = 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)
|
|
}
|
|
}
|