Drivers: add work_dir config to exec/raw_exec/java drivers (#24249)

---------

Co-authored-by: wurosh <uros.m.perisic@gmail.com>
Co-authored-by: Michael Schurter <mschurter@hashicorp.com>
Co-authored-by: Tim Gross <tgross@hashicorp.com>
This commit is contained in:
Michael Smithhisler
2024-11-01 11:04:40 -04:00
committed by GitHub
parent 58ea294f0b
commit 658c429d75
21 changed files with 408 additions and 125 deletions

3
.changelog/24249.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
drivers: Add work_dir config to exec/rawexec/java drivers for setting the working directory of processes in a task
```

View File

@@ -97,6 +97,7 @@ var (
"ipc_mode": hclspec.NewAttr("ipc_mode", "string", false),
"cap_add": hclspec.NewAttr("cap_add", "list(string)", false),
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
"work_dir": hclspec.NewAttr("work_dir", "string", false),
})
// driverCapabilities represents the RPC response for what features are
@@ -211,6 +212,9 @@ type TaskConfig struct {
// CapDrop is a set of linux capabilities to disable.
CapDrop []string `codec:"cap_drop"`
// WorkDir is the working directory inside the chroot
WorkDir string `codec:"work_dir"`
}
func (tc *TaskConfig) validate() error {
@@ -237,6 +241,10 @@ func (tc *TaskConfig) validate() error {
return fmt.Errorf("cap_drop configured with capabilities not supported by system: %s", badDrops)
}
if tc.WorkDir != "" && !filepath.IsAbs(tc.WorkDir) {
return fmt.Errorf("work_dir must be absolute but got relative path %q", tc.WorkDir)
}
return nil
}
@@ -517,6 +525,7 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
NoPivotRoot: d.config.NoPivotRoot,
Resources: cfg.Resources,
TaskDir: cfg.TaskDir().Dir,
WorkDir: driverConfig.WorkDir,
StdoutPath: cfg.StdoutPath,
StderrPath: cfg.StderrPath,
Mounts: cfg.Mounts,

View File

@@ -19,6 +19,7 @@ import (
"time"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/allocdir"
"github.com/hashicorp/nomad/client/lib/cgroupslib"
"github.com/hashicorp/nomad/client/lib/numalib"
ctestutils "github.com/hashicorp/nomad/client/testutil"
@@ -127,6 +128,50 @@ func TestExecDriver_Fingerprint(t *testing.T) {
}
}
func TestExecDriver_WorkDir(t *testing.T) {
ci.Parallel(t)
ctestutils.ExecCompatible(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := newExecDriverTest(t, ctx)
harness := dtestutil.NewDriverHarness(t, d)
allocID := uuid.Generate()
task := &drivers.TaskConfig{
AllocID: allocID,
ID: uuid.Generate(),
Name: "test",
Resources: testResources(allocID, "test"),
}
workDir := filepath.Join("/", allocdir.TaskLocal)
tc := &TaskConfig{
Command: "/bin/cat",
Args: []string{"foo.txt"},
WorkDir: workDir,
}
must.NoError(t, task.EncodeConcreteDriverConfig(&tc))
cleanup := harness.MkAllocDir(task, false)
defer cleanup()
must.NoError(t, os.WriteFile(filepath.Join(task.TaskDir().Dir, allocdir.TaskLocal, "foo.txt"), []byte("foo"), 660))
handle, _, err := harness.StartTask(task)
must.NoError(t, err)
ch, err := harness.WaitTask(context.Background(), handle.Config.ID)
must.NoError(t, err)
// Task will fail if cat cannot find the file, which would only happen
// if the task's WorkDir was setup incorrectly
result := <-ch
must.Zero(t, result.ExitCode)
must.NoError(t, harness.DestroyTask(task.ID, true))
}
func TestExecDriver_StartWait(t *testing.T) {
ci.Parallel(t)
ctestutils.ExecCompatible(t)
@@ -735,11 +780,13 @@ func TestConfig_ParseAllHCL(t *testing.T) {
config {
command = "/bin/bash"
args = ["-c", "echo hello"]
work_dir = "/root"
}`
expected := &TaskConfig{
Command: "/bin/bash",
Args: []string{"-c", "echo hello"},
WorkDir: "/root",
}
var tc *TaskConfig
@@ -1013,4 +1060,18 @@ func TestDriver_TaskConfig_validate(t *testing.T) {
}).validate())
}
})
t.Run("work_dir", func(t *testing.T) {
for _, tc := range []struct {
workDir string
exp error
}{
{workDir: "/foo", exp: nil},
{workDir: "foo", exp: errors.New(`work_dir must be absolute but got relative path "foo"`)},
} {
must.Eq(t, tc.exp, (&TaskConfig{
WorkDir: tc.workDir,
}).validate())
}
})
}

View File

@@ -98,6 +98,7 @@ var (
"ipc_mode": hclspec.NewAttr("ipc_mode", "string", false),
"cap_add": hclspec.NewAttr("cap_add", "list(string)", false),
"cap_drop": hclspec.NewAttr("cap_drop", "list(string)", false),
"work_dir": hclspec.NewAttr("work_dir", "string", false),
})
// driverCapabilities is returned by the Capabilities RPC and indicates what
@@ -189,6 +190,9 @@ type TaskConfig struct {
// CapDrop is a set of linux capabilities to disable.
CapDrop []string `codec:"cap_drop"`
// WorkDir is the working directory for the task
WorkDir string `coded:"work_dir"`
}
func (tc *TaskConfig) validate() error {
@@ -215,6 +219,9 @@ func (tc *TaskConfig) validate() error {
return fmt.Errorf("cap_drop configured with capabilities not supported by system: %s", badDrops)
}
if tc.WorkDir != "" && !filepath.IsAbs(tc.WorkDir) {
return fmt.Errorf("work_dir must be an absolute path: %s", tc.WorkDir)
}
return nil
}
@@ -496,6 +503,7 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
ResourceLimits: true,
Resources: cfg.Resources,
TaskDir: cfg.TaskDir().Dir,
WorkDir: driverConfig.WorkDir,
StdoutPath: cfg.StdoutPath,
StderrPath: cfg.StderrPath,
Mounts: cfg.Mounts,

View File

@@ -25,6 +25,7 @@ import (
"github.com/hashicorp/nomad/plugins/drivers"
dtestutil "github.com/hashicorp/nomad/plugins/drivers/testutils"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)
@@ -209,6 +210,49 @@ func TestJavaDriver_Class_Start_Wait(t *testing.T) {
require.NoError(t, harness.DestroyTask(task.ID, true))
}
func TestJavaDriver_WorkDir(t *testing.T) {
ci.Parallel(t)
javaCompatible(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
d := newJavaDriverTest(t, ctx)
harness := dtestutil.NewDriverHarness(t, d)
tc := &TaskConfig{
JarPath: "../demoapp.jar",
Args: []string{"1"},
JvmOpts: []string{"-Xmx64m", "-Xms32m"},
WorkDir: "/local",
}
task := basicTask(t, "demo-app", tc)
cleanup := harness.MkAllocDir(task, true)
defer cleanup()
copyFile("./test-resources/demoapp.jar", filepath.Join(task.TaskDir().Dir, "demoapp.jar"), t)
handle, _, err := harness.StartTask(task)
must.NoError(t, err)
ch, err := harness.WaitTask(context.Background(), handle.Config.ID)
must.NoError(t, err)
result := <-ch
must.Nil(t, result.Err)
must.Zero(t, result.ExitCode)
// Get the stdout of the process and assert that it's not empty
stdout, err := os.ReadFile(filepath.Join(task.TaskDir().LogDir, "demo-app.stdout.0"))
must.NoError(t, err)
must.Eq(t, string(stdout), "Hello, the current working directory is: /local\n")
must.NoError(t, harness.DestroyTask(task.ID, true))
}
func TestJavaCmdArgs(t *testing.T) {
ci.Parallel(t)
@@ -521,4 +565,18 @@ func TestDriver_TaskConfig_validate(t *testing.T) {
}).validate())
}
})
t.Run("work_dir", func(t *testing.T) {
for _, tc := range []struct {
workDir string
exp error
}{
{workDir: "/goodpath", exp: nil},
{workDir: "badpath", exp: errors.New("work_dir must be an absolute path: badpath")},
} {
require.Equal(t, tc.exp, (&TaskConfig{
WorkDir: tc.workDir,
}).validate())
}
})
}

View File

@@ -5,7 +5,7 @@
public class Hello {
public static void main(String[] args) {
System.out.println("Hello");
System.out.println("Hello, the current working directory is: " + System.getProperty("user.dir"));
int seconds = 5;
if (args.length != 0) {
seconds = Integer.parseInt(args[0]);

View File

@@ -94,6 +94,7 @@ var (
"cgroup_v2_override": hclspec.NewAttr("cgroup_v2_override", "string", false),
"cgroup_v1_override": hclspec.NewAttr("cgroup_v1_override", "list(map(string))", false),
"oom_score_adj": hclspec.NewAttr("oom_score_adj", "number", false),
"work_dir": hclspec.NewAttr("work_dir", "string", false),
})
// capabilities is returned by the Capabilities RPC and indicates what
@@ -172,6 +173,25 @@ type TaskConfig struct {
// OOMScoreAdj sets the oom_score_adj on Linux systems
OOMScoreAdj int `codec:"oom_score_adj"`
// WorkDir sets the working directory of the task
WorkDir string `codec:"work_dir"`
}
func (t *TaskConfig) validate() error {
// ensure only one of cgroups_v1_override and cgroups_v2_override have been
// configured; must check here because task config validation cannot happen
// on the server.
if len(t.OverrideCgroupV1) > 0 && t.OverrideCgroupV2 != "" {
return errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set")
}
if t.OOMScoreAdj < 0 {
return errors.New("oom_score_adj must not be negative")
}
if t.WorkDir != "" && !filepath.IsAbs(t.WorkDir) {
return errors.New("work_dir must be an absolute path")
}
return nil
}
// TaskState is the state which is encoded in the handle returned in
@@ -352,8 +372,10 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
return nil, nil, fmt.Errorf("failed to decode driver config: %v", err)
}
if driverConfig.OOMScoreAdj < 0 {
return nil, nil, fmt.Errorf("oom_score_adj must not be negative")
driverConfig.OverrideCgroupV2 = cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2)
if err := driverConfig.validate(); err != nil {
return nil, nil, fmt.Errorf("failed driver config validation: %v", err)
}
if err := d.Validate(*cfg); err != nil {
@@ -383,22 +405,16 @@ func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drive
Env: cfg.EnvList(),
User: cfg.User,
TaskDir: cfg.TaskDir().Dir,
WorkDir: driverConfig.WorkDir,
StdoutPath: cfg.StdoutPath,
StderrPath: cfg.StderrPath,
NetworkIsolation: cfg.NetworkIsolation,
Resources: cfg.Resources.Copy(),
OverrideCgroupV2: cgroupslib.CustomPathCG2(driverConfig.OverrideCgroupV2),
OverrideCgroupV2: driverConfig.OverrideCgroupV2,
OverrideCgroupV1: driverConfig.OverrideCgroupV1,
OOMScoreAdj: int32(driverConfig.OOMScoreAdj),
}
// ensure only one of cgroups_v1_override and cgroups_v2_override have been
// configured; must check here because task config validation cannot happen
// on the server.
if len(execCmd.OverrideCgroupV1) > 0 && execCmd.OverrideCgroupV2 != "" {
return nil, nil, errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set")
}
ps, err := exec.Launch(execCmd)
if err != nil {
pluginClient.Kill()

View File

@@ -462,7 +462,6 @@ func TestRawExecDriver_ParentCgroup(t *testing.T) {
func TestRawExecDriver_Exec(t *testing.T) {
ci.Parallel(t)
ctestutil.ExecCompatible(t)
require := require.New(t)
@@ -506,7 +505,7 @@ func TestRawExecDriver_Exec(t *testing.T) {
res, err = harness.ExecTask(task.ID, []string{"cmd.exe", "/c", "stat", "notarealfile123abc"}, 1*time.Second)
require.NoError(err)
require.False(res.ExitResult.Successful())
require.Contains(string(res.Stdout), "not recognized")
require.Contains(string(res.Stdout), "No such file or directory")
} else {
// Exec a command that should work
res, err := harness.ExecTask(task.ID, []string{"/usr/bin/stat", "/tmp"}, 1*time.Second)
@@ -524,6 +523,59 @@ func TestRawExecDriver_Exec(t *testing.T) {
require.NoError(harness.DestroyTask(task.ID, true))
}
func TestRawExecDriver_WorkDir(t *testing.T) {
ci.Parallel(t)
d := newEnabledRawExecDriver(t)
harness := dtestutil.NewDriverHarness(t, d)
defer harness.Kill()
allocID := uuid.Generate()
taskName := "test"
task := &drivers.TaskConfig{
AllocID: allocID,
ID: uuid.Generate(),
Name: taskName,
Env: defaultEnv(),
Resources: testResources(allocID, taskName),
}
workDir := t.TempDir()
tc := &TaskConfig{
WorkDir: workDir,
}
if runtime.GOOS == "windows" {
tc.Command = "cmd.exe"
tc.Args = []string{"/c", "stat", "foo.txt"}
} else {
tc.Command = "/usr/bin/stat"
tc.Args = []string{"foo.txt"}
}
must.NoError(t, task.EncodeConcreteDriverConfig(&tc))
testtask.SetTaskConfigEnv(task)
cleanup := harness.MkAllocDir(task, false)
defer cleanup()
harness.MakeTaskCgroup(allocID, taskName)
must.NoError(t, os.WriteFile(filepath.Join(workDir, "foo.txt"), []byte("foo"), 770))
handle, _, err := harness.StartTask(task)
must.NoError(t, err)
ch, err := harness.WaitTask(context.Background(), handle.Config.ID)
must.NoError(t, err)
// Task will fail if cat cannot find the file, which would only happen
// if the task's WorkDir was setup incorrectly
result := <-ch
must.Zero(t, result.ExitCode)
must.NoError(t, harness.DestroyTask(task.ID, true))
}
func TestConfig_ParseAllHCL(t *testing.T) {
ci.Parallel(t)
@@ -568,3 +620,45 @@ func TestRawExecDriver_Disabled(t *testing.T) {
require.Contains(err.Error(), errDisabledDriver.Error())
require.Nil(handle)
}
func TestRawExecDriver_validate(t *testing.T) {
ci.Parallel(t)
testCases := []struct {
name string
config *TaskConfig
exp error
}{
{
name: "validates CGroup overrides",
config: &TaskConfig{
OverrideCgroupV2: "custom.slice/app.scope",
OverrideCgroupV1: map[string]string{
"pids": "custom/path",
},
},
exp: errors.New("only one of cgroups_v1_override and cgroups_v2_override may be set"),
},
{
name: "validates OOM score adj",
config: &TaskConfig{
OOMScoreAdj: -1,
},
exp: errors.New("oom_score_adj must not be negative"),
},
{
name: "validates work_dir is abolute path",
config: &TaskConfig{
WorkDir: "bad/path",
},
exp: errors.New("work_dir must be an absolute path"),
},
}
for _, i := range testCases {
t.Run(i.name, func(t *testing.T) {
err := i.config.validate()
must.Eq(t, i.exp, err)
})
}
}

View File

@@ -30,7 +30,6 @@ import (
"github.com/hashicorp/nomad/plugins/drivers"
dtestutil "github.com/hashicorp/nomad/plugins/drivers/testutils"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
)
@@ -65,38 +64,6 @@ func TestRawExecDriver_User(t *testing.T) {
require.Contains(err.Error(), msg)
}
func TestRawExecDriver_ValidateCgroupOverrides(t *testing.T) {
ci.Parallel(t)
clienttestutil.RequireLinux(t)
d := newEnabledRawExecDriver(t)
harness := dtestutil.NewDriverHarness(t, d)
task := &drivers.TaskConfig{
ID: uuid.Generate(),
Name: "sleep",
User: "nobody",
}
cleanup := harness.MkAllocDir(task, false)
defer cleanup()
tc := &TaskConfig{
Command: "sleep",
Args: []string{"infinity"},
OverrideCgroupV2: "custom.slice/app.scope",
OverrideCgroupV1: map[string]string{
"pids": "custom/path",
},
}
must.NoError(t, task.EncodeConcreteDriverConfig(&tc))
testtask.SetTaskConfigEnv(task)
_, _, err := harness.StartTask(task)
must.ErrorContains(t, err, "only one of cgroups_v1_override and cgroups_v2_override may be set")
}
func TestRawExecDriver_Signal(t *testing.T) {
ci.Parallel(t)
clienttestutil.RequireLinux(t)

View File

@@ -125,6 +125,10 @@ type ExecCommand struct {
// TaskDir is the directory path on the host where for the task
TaskDir string
// WorkDir is the working directory of the task inside of a chroot
// which defaults to the chroot directory (TaskDir) itself
WorkDir string
// ResourceLimits determines whether resource limits are enforced by the
// executor.
ResourceLimits bool
@@ -363,7 +367,11 @@ func (e *UniversalExecutor) Launch(command *ExecCommand) (*ProcessState, error)
}
// set the task dir as the working directory for the command
e.childCmd.Dir = e.command.TaskDir
if e.command.WorkDir != "" {
e.childCmd.Dir = e.command.WorkDir
} else {
e.childCmd.Dir = e.command.TaskDir
}
// start command in separate process group
if err := e.setNewProcessGroup(); err != nil {
@@ -482,7 +490,7 @@ func (e *UniversalExecutor) ExecStreaming(ctx context.Context, command []string,
cmd := exec.CommandContext(ctx, command[0], command[1:]...)
cmd.Dir = "/"
cmd.Dir = e.childCmd.Dir
cmd.Env = e.childCmd.Env
execHelper := &execHelper{

View File

@@ -214,6 +214,7 @@ func (l *LibcontainerExecutor) Launch(command *ExecCommand) (*ProcessState, erro
process := &libcontainer.Process{
Args: combined,
Env: command.Env,
Cwd: command.WorkDir,
Stdout: stdout,
Stderr: stderr,
Init: true,
@@ -497,6 +498,7 @@ func (l *LibcontainerExecutor) Exec(deadline time.Time, cmd string, args []strin
process := &libcontainer.Process{
Args: combined,
Env: l.command.Env,
Cwd: l.command.WorkDir,
Stdout: buf,
Stderr: buf,
}
@@ -552,7 +554,7 @@ func (l *LibcontainerExecutor) ExecStreaming(ctx context.Context, cmd []string,
Env: l.userProc.Env,
User: l.userProc.User,
Init: false,
Cwd: "/",
Cwd: l.command.WorkDir,
}
execHelper := &execHelper{

View File

@@ -62,6 +62,7 @@ func testExecutorCommandWithChroot(t *testing.T) *testExecCmd {
"/lib64": "/lib64",
"/usr/lib": "/usr/lib",
"/bin/ls": "/bin/ls",
"/bin/pwd": "/bin/pwd",
"/bin/cat": "/bin/cat",
"/bin/echo": "/bin/echo",
"/bin/bash": "/bin/bash",
@@ -798,6 +799,34 @@ func TestExecutor_cmdMounts(t *testing.T) {
require.EqualValues(t, expected, cmdMounts(input))
}
func TestExecutor_WorkDir(t *testing.T) {
t.Parallel()
testutil.ExecCompatible(t)
testExecCmd := testExecutorCommandWithChroot(t)
execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir
defer allocDir.Destroy()
execCmd.ResourceLimits = true
workDir := "/etc"
execCmd.WorkDir = workDir
execCmd.Cmd = "/bin/pwd"
executor := NewExecutorWithIsolation(testlog.HCLogger(t), compute)
defer executor.Shutdown("SIGKILL", 0)
ps, err := executor.Launch(execCmd)
must.NoError(t, err)
must.NonZero(t, ps.Pid)
state, err := executor.Wait(context.Background())
must.NoError(t, err)
must.Zero(t, state.ExitCode)
output := strings.TrimSpace(testExecCmd.stdout.String())
must.Eq(t, output, workDir)
}
func TestExecCommand_getCgroupOr_off(t *testing.T) {
ci.Parallel(t)

View File

@@ -55,6 +55,7 @@ func (c *grpcExecutorClient) Launch(cmd *ExecCommand) (*ProcessState, error) {
CgroupV2Override: cmd.OverrideCgroupV2,
CgroupV1Override: cmd.OverrideCgroupV1,
OomScoreAdj: cmd.OOMScoreAdj,
WorkDir: cmd.WorkDir,
}
resp, err := c.client.Launch(ctx, req)
if err != nil {

View File

@@ -44,6 +44,7 @@ func (s *grpcExecutorServer) Launch(ctx context.Context, req *proto.LaunchReques
OverrideCgroupV2: req.CgroupV2Override,
OverrideCgroupV1: req.CgroupV1Override,
OOMScoreAdj: req.OomScoreAdj,
WorkDir: req.WorkDir,
})
if err != nil {

View File

@@ -49,6 +49,7 @@ type LaunchRequest struct {
CgroupV2Override string `protobuf:"bytes,20,opt,name=cgroup_v2_override,json=cgroupV2Override,proto3" json:"cgroup_v2_override,omitempty"`
CgroupV1Override map[string]string `protobuf:"bytes,21,rep,name=cgroup_v1_override,json=cgroupV1Override,proto3" json:"cgroup_v1_override,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
OomScoreAdj int32 `protobuf:"varint,22,opt,name=oom_score_adj,json=oomScoreAdj,proto3" json:"oom_score_adj,omitempty"`
WorkDir string `protobuf:"bytes,23,opt,name=work_dir,json=workDir,proto3" json:"work_dir,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -234,6 +235,13 @@ func (m *LaunchRequest) GetOomScoreAdj() int32 {
return 0
}
func (m *LaunchRequest) GetWorkDir() string {
if m != nil {
return m.WorkDir
}
return ""
}
type LaunchResponse struct {
Process *ProcessState `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -908,82 +916,83 @@ func init() {
}
var fileDescriptor_66b85426380683f3 = []byte{
// 1187 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x7d, 0x6f, 0xdb, 0x44,
0x1c, 0x9e, 0x9b, 0xa6, 0x49, 0x7e, 0x49, 0xda, 0xec, 0xd8, 0x8a, 0x17, 0x84, 0x56, 0x8c, 0xc4,
0x22, 0x18, 0xee, 0xd6, 0xbd, 0x0a, 0x24, 0x06, 0xeb, 0x06, 0x9a, 0xf6, 0x42, 0xe5, 0x8e, 0x4d,
0xe2, 0x0f, 0xcc, 0xcd, 0xbe, 0x25, 0xb7, 0x38, 0x3e, 0x73, 0x77, 0xce, 0x5a, 0x09, 0x89, 0x2f,
0x01, 0x12, 0x1f, 0x80, 0x4f, 0xc4, 0x27, 0x42, 0xf7, 0xe6, 0x26, 0xdd, 0x98, 0xdc, 0x22, 0xfe,
0xca, 0xdd, 0xe3, 0xe7, 0xf7, 0x7e, 0xf7, 0x5c, 0xe0, 0x72, 0xca, 0xe9, 0x9c, 0x70, 0xb1, 0x2d,
0x26, 0x98, 0x93, 0x74, 0x9b, 0x1c, 0x90, 0xa4, 0x94, 0x8c, 0x6f, 0x17, 0x9c, 0x49, 0x56, 0x6d,
0x43, 0xbd, 0x45, 0x9f, 0x4c, 0xb0, 0x98, 0xd0, 0x84, 0xf1, 0x22, 0xcc, 0xd9, 0x0c, 0xa7, 0x61,
0x91, 0x95, 0x63, 0x9a, 0x8b, 0x70, 0x99, 0x37, 0xbc, 0x38, 0x66, 0x6c, 0x9c, 0x11, 0xe3, 0xe4,
0x45, 0xf9, 0x72, 0x5b, 0xd2, 0x19, 0x11, 0x12, 0xcf, 0x0a, 0x4b, 0x08, 0xac, 0xe1, 0xb6, 0x0b,
0x6f, 0xc2, 0x99, 0x9d, 0xe1, 0x04, 0x7f, 0xb7, 0xa1, 0xff, 0x08, 0x97, 0x79, 0x32, 0x89, 0xc8,
0x2f, 0x25, 0x11, 0x12, 0x0d, 0xa0, 0x91, 0xcc, 0x52, 0xdf, 0xdb, 0xf2, 0x46, 0x9d, 0x48, 0x2d,
0x11, 0x82, 0x55, 0xcc, 0xc7, 0xc2, 0x5f, 0xd9, 0x6a, 0x8c, 0x3a, 0x91, 0x5e, 0xa3, 0x27, 0xd0,
0xe1, 0x44, 0xb0, 0x92, 0x27, 0x44, 0xf8, 0x8d, 0x2d, 0x6f, 0xd4, 0xdd, 0xb9, 0x12, 0xfe, 0x5b,
0xe2, 0x36, 0xbe, 0x09, 0x19, 0x46, 0xce, 0x2e, 0x3a, 0x72, 0x81, 0x2e, 0x42, 0x57, 0xc8, 0x94,
0x95, 0x32, 0x2e, 0xb0, 0x9c, 0xf8, 0xab, 0x3a, 0x3a, 0x18, 0x68, 0x0f, 0xcb, 0x89, 0x25, 0x10,
0xce, 0x0d, 0xa1, 0x59, 0x11, 0x08, 0xe7, 0x9a, 0x30, 0x80, 0x06, 0xc9, 0xe7, 0xfe, 0x9a, 0x4e,
0x52, 0x2d, 0x55, 0xde, 0xa5, 0x20, 0xdc, 0x6f, 0x69, 0xae, 0x5e, 0xa3, 0x0b, 0xd0, 0x96, 0x58,
0x4c, 0xe3, 0x94, 0x72, 0xbf, 0xad, 0xf1, 0x96, 0xda, 0xdf, 0xa3, 0x1c, 0x5d, 0x82, 0x0d, 0x97,
0x4f, 0x9c, 0xd1, 0x19, 0x95, 0xc2, 0xef, 0x6c, 0x79, 0xa3, 0x76, 0xb4, 0xee, 0xe0, 0x47, 0x1a,
0x45, 0xd7, 0xe1, 0xdc, 0x0b, 0x2c, 0x68, 0x12, 0x17, 0x9c, 0x25, 0x44, 0x88, 0x38, 0x19, 0x73,
0x56, 0x16, 0x3e, 0x28, 0xf6, 0xdd, 0x15, 0xdf, 0x8b, 0x90, 0xfe, 0xbe, 0x67, 0x3e, 0xef, 0xea,
0xaf, 0xe8, 0x1e, 0xac, 0xcd, 0x58, 0x99, 0x4b, 0xe1, 0x77, 0xb7, 0x1a, 0xa3, 0xee, 0xce, 0xe5,
0x9a, 0xed, 0x7a, 0xac, 0x8c, 0x22, 0x6b, 0x8b, 0xbe, 0x83, 0x56, 0x4a, 0xe6, 0x54, 0x75, 0xbd,
0xa7, 0xdd, 0x7c, 0x5e, 0xd3, 0xcd, 0x3d, 0x6d, 0x15, 0x39, 0x6b, 0x34, 0x81, 0xb3, 0x39, 0x91,
0xaf, 0x19, 0x9f, 0xc6, 0x54, 0xb0, 0x0c, 0x4b, 0xca, 0x72, 0xbf, 0xaf, 0x07, 0xf9, 0x65, 0x4d,
0x97, 0x4f, 0x8c, 0xfd, 0x03, 0x67, 0xbe, 0x5f, 0x90, 0x24, 0x1a, 0xe4, 0xc7, 0x50, 0x14, 0x40,
0x3f, 0x67, 0x71, 0x41, 0xe7, 0x4c, 0xc6, 0x9c, 0x31, 0xe9, 0xaf, 0xeb, 0xae, 0x76, 0x73, 0xb6,
0xa7, 0xb0, 0x88, 0x31, 0x89, 0x46, 0x30, 0x48, 0xc9, 0x4b, 0x5c, 0x66, 0x32, 0x2e, 0x68, 0x1a,
0xcf, 0x58, 0x4a, 0xfc, 0x0d, 0x3d, 0x9e, 0x75, 0x8b, 0xef, 0xd1, 0xf4, 0x31, 0x4b, 0xc9, 0x22,
0x93, 0x16, 0x89, 0x61, 0x0e, 0x96, 0x98, 0x0f, 0x8a, 0x44, 0x33, 0x3f, 0x86, 0x7e, 0x52, 0x94,
0x82, 0x48, 0x37, 0x9f, 0xb3, 0x9a, 0xd6, 0x33, 0xa0, 0x9d, 0xca, 0x87, 0x00, 0x38, 0xcb, 0xd8,
0xeb, 0x38, 0xc1, 0x85, 0xf0, 0x91, 0x3e, 0x3c, 0x1d, 0x8d, 0xec, 0xe2, 0x42, 0xa0, 0x00, 0x7a,
0x09, 0x2e, 0xf0, 0x0b, 0x9a, 0x51, 0x49, 0x89, 0xf0, 0xdf, 0xd3, 0x84, 0x25, 0x0c, 0x5d, 0x06,
0x64, 0x02, 0xc4, 0xf3, 0x9d, 0x98, 0xcd, 0x09, 0xe7, 0x34, 0x25, 0xfe, 0x39, 0x1d, 0x6c, 0x60,
0xbe, 0x3c, 0xdb, 0xf9, 0xde, 0xe2, 0xe8, 0xf0, 0x88, 0x7d, 0xf5, 0x88, 0x7d, 0x5e, 0xcf, 0xf2,
0x61, 0x58, 0xef, 0xea, 0x87, 0x4b, 0x37, 0x36, 0x34, 0xa5, 0x3c, 0xbb, 0xea, 0x62, 0xdc, 0xcf,
0x25, 0x3f, 0xac, 0x42, 0x57, 0xb0, 0x1a, 0x04, 0x63, 0xb3, 0x58, 0x24, 0x8c, 0x93, 0x18, 0xa7,
0xaf, 0xfc, 0xcd, 0x2d, 0x6f, 0xd4, 0x8c, 0xba, 0x8c, 0xcd, 0xf6, 0x15, 0xf6, 0x4d, 0xfa, 0x6a,
0xb8, 0x0b, 0xe7, 0xdf, 0xea, 0x4e, 0x5d, 0xaf, 0x29, 0x39, 0x74, 0xb2, 0x30, 0x25, 0x87, 0xe8,
0x1c, 0x34, 0xe7, 0x38, 0x2b, 0x89, 0xbf, 0xa2, 0x31, 0xb3, 0xf9, 0x62, 0xe5, 0xb6, 0x17, 0xfc,
0x0c, 0xeb, 0x2e, 0x43, 0x51, 0xb0, 0x5c, 0x10, 0xf4, 0x04, 0x5a, 0xf6, 0xb2, 0x68, 0x0f, 0xdd,
0x9d, 0xeb, 0x75, 0x4b, 0xb5, 0x97, 0x68, 0x5f, 0x62, 0x49, 0x22, 0xe7, 0x24, 0xe8, 0x43, 0xf7,
0x39, 0xa6, 0xd2, 0x76, 0x20, 0xf8, 0x09, 0x7a, 0x66, 0xfb, 0x3f, 0x85, 0x7b, 0x04, 0x1b, 0xfb,
0x93, 0x52, 0xa6, 0xec, 0x75, 0xee, 0x64, 0x72, 0x13, 0xd6, 0x04, 0x1d, 0xe7, 0x38, 0xb3, 0x2d,
0xb1, 0x3b, 0xf4, 0x11, 0xf4, 0xc6, 0x1c, 0x27, 0x24, 0x2e, 0x08, 0xa7, 0x2c, 0xd5, 0xcd, 0x69,
0x44, 0x5d, 0x8d, 0xed, 0x69, 0x28, 0x40, 0x30, 0x38, 0xf2, 0x66, 0x32, 0x0e, 0x26, 0xb0, 0xf9,
0x43, 0x91, 0xaa, 0xa0, 0x95, 0x3a, 0xda, 0x40, 0x4b, 0x4a, 0xeb, 0xfd, 0x67, 0xa5, 0x0d, 0x2e,
0xc0, 0xfb, 0x6f, 0x44, 0xb2, 0x49, 0x0c, 0x60, 0xfd, 0x19, 0xe1, 0x82, 0x32, 0x57, 0x65, 0xf0,
0x19, 0x6c, 0x54, 0x88, 0xed, 0xad, 0x0f, 0xad, 0xb9, 0x81, 0x6c, 0xe5, 0x6e, 0x1b, 0x7c, 0x0a,
0x3d, 0xd5, 0xb7, 0x2a, 0xf3, 0x21, 0xb4, 0x69, 0x2e, 0x09, 0x9f, 0xdb, 0x26, 0x35, 0xa2, 0x6a,
0x1f, 0x3c, 0x87, 0xbe, 0xe5, 0x5a, 0xb7, 0xdf, 0x42, 0x53, 0x28, 0xe0, 0x84, 0x25, 0x3e, 0xc5,
0x62, 0x6a, 0x1c, 0x19, 0xf3, 0xe0, 0x12, 0xf4, 0xf7, 0xf5, 0x24, 0xde, 0x3e, 0xa8, 0xa6, 0x1b,
0x94, 0x2a, 0xd6, 0x11, 0x6d, 0xf9, 0x53, 0xe8, 0xde, 0x3f, 0x20, 0x89, 0x33, 0xbc, 0x09, 0xed,
0x94, 0xe0, 0x34, 0xa3, 0x39, 0xb1, 0x49, 0x0d, 0x43, 0xf3, 0xe4, 0x86, 0xee, 0xc9, 0x0d, 0x9f,
0xba, 0x27, 0x37, 0xaa, 0xb8, 0xee, 0x01, 0x5d, 0x79, 0xf3, 0x01, 0x6d, 0x1c, 0x3d, 0xa0, 0xc1,
0x2e, 0xf4, 0x4c, 0x30, 0x5b, 0xff, 0x26, 0xac, 0xb1, 0x52, 0x16, 0xa5, 0xd4, 0xb1, 0x7a, 0x91,
0xdd, 0xa1, 0x0f, 0xa0, 0x43, 0x0e, 0xa8, 0x8c, 0x13, 0x25, 0x74, 0x2b, 0xba, 0x82, 0xb6, 0x02,
0x76, 0x59, 0x4a, 0x82, 0xbf, 0x3c, 0xe8, 0x2d, 0x9e, 0x58, 0x15, 0xbb, 0xa0, 0xa9, 0xad, 0x54,
0x2d, 0xdf, 0x69, 0xbf, 0xd0, 0x9b, 0xc6, 0x62, 0x6f, 0x50, 0x08, 0xab, 0xea, 0xcf, 0x84, 0x7e,
0x86, 0xdf, 0x5d, 0xb6, 0xe6, 0x29, 0x15, 0x55, 0xca, 0x32, 0xa5, 0x59, 0x46, 0x52, 0xfd, 0x36,
0xb7, 0xa3, 0x0e, 0x63, 0xb3, 0x87, 0x1a, 0xd8, 0xf9, 0xa3, 0x03, 0xed, 0xfb, 0xf6, 0x9e, 0xa1,
0x43, 0x58, 0x33, 0xe2, 0x80, 0x6e, 0x9c, 0x4a, 0xee, 0x86, 0x37, 0x4f, 0x6a, 0x66, 0xc7, 0x7b,
0x06, 0x09, 0x58, 0x55, 0x32, 0x81, 0xae, 0xd5, 0xf5, 0xb0, 0xa0, 0x31, 0xc3, 0xeb, 0x27, 0x33,
0xaa, 0x82, 0xfe, 0x06, 0x6d, 0x77, 0xdb, 0xd1, 0xad, 0xba, 0x3e, 0x8e, 0xa9, 0xcd, 0xf0, 0xf6,
0xc9, 0x0d, 0xab, 0x04, 0x7e, 0xf7, 0x60, 0xe3, 0xd8, 0x8d, 0x47, 0x5f, 0xd5, 0xf5, 0xf7, 0x76,
0x51, 0x1a, 0xde, 0x39, 0xb5, 0x7d, 0x95, 0xd6, 0xaf, 0xd0, 0xb2, 0xd2, 0x82, 0x6a, 0x4f, 0x74,
0x59, 0x9d, 0x86, 0xb7, 0x4e, 0x6c, 0x57, 0x45, 0x3f, 0x80, 0xa6, 0x96, 0x0d, 0x54, 0x7b, 0xac,
0x8b, 0xd2, 0x36, 0xbc, 0x71, 0x42, 0x2b, 0x17, 0xf7, 0x8a, 0xa7, 0xce, 0xbf, 0xd1, 0x9d, 0xfa,
0xe7, 0x7f, 0x49, 0xd0, 0xea, 0x9f, 0xff, 0x63, 0xf2, 0xa6, 0xcf, 0xbf, 0xba, 0x86, 0xf5, 0xcf,
0xff, 0x82, 0x1c, 0xd6, 0x3f, 0xff, 0x8b, 0xb2, 0x16, 0x9c, 0x41, 0x7f, 0x7a, 0xd0, 0x57, 0xd0,
0xbe, 0xe4, 0x04, 0xcf, 0x68, 0x3e, 0x46, 0x77, 0x6a, 0x6a, 0xbb, 0xb2, 0x32, 0xfa, 0x6e, 0x2d,
0x5d, 0x2a, 0x5f, 0x9f, 0xde, 0x81, 0x4b, 0x6b, 0xe4, 0x5d, 0xf1, 0xee, 0xb6, 0x7e, 0x6c, 0x1a,
0x49, 0x5b, 0xd3, 0x3f, 0xd7, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x85, 0x8d, 0xe6, 0xa9,
0x0d, 0x00, 0x00,
// 1205 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xfb, 0x6e, 0x1b, 0xc5,
0x17, 0xee, 0xc6, 0x71, 0x6c, 0x1f, 0xdb, 0x89, 0x3b, 0xbf, 0x36, 0xdd, 0xfa, 0x27, 0xd4, 0xb0,
0x48, 0xd4, 0x82, 0xb2, 0x69, 0xd3, 0xab, 0x40, 0xa2, 0xd0, 0xa4, 0xa0, 0xaa, 0x17, 0xa2, 0x4d,
0x69, 0x25, 0xfe, 0x60, 0x99, 0xee, 0x4e, 0xed, 0xa9, 0xd7, 0x3b, 0xcb, 0xcc, 0xac, 0x9b, 0x48,
0x48, 0xbc, 0x04, 0x48, 0x3c, 0x00, 0xaf, 0xc7, 0x3b, 0xa0, 0xb9, 0x6d, 0xec, 0xb4, 0x54, 0x9b,
0x22, 0xfe, 0xca, 0x9e, 0xcf, 0xdf, 0xb9, 0xcc, 0x39, 0x73, 0xbe, 0x09, 0x5c, 0x49, 0x39, 0x9d,
0x13, 0x2e, 0xb6, 0xc5, 0x04, 0x73, 0x92, 0x6e, 0x93, 0x43, 0x92, 0x94, 0x92, 0xf1, 0xed, 0x82,
0x33, 0xc9, 0x2a, 0x33, 0xd4, 0x26, 0xfa, 0x78, 0x82, 0xc5, 0x84, 0x26, 0x8c, 0x17, 0x61, 0xce,
0x66, 0x38, 0x0d, 0x8b, 0xac, 0x1c, 0xd3, 0x5c, 0x84, 0xcb, 0xbc, 0xe1, 0xa5, 0x31, 0x63, 0xe3,
0x8c, 0x98, 0x20, 0x2f, 0xca, 0x97, 0xdb, 0x92, 0xce, 0x88, 0x90, 0x78, 0x56, 0x58, 0x42, 0x60,
0x1d, 0xb7, 0x5d, 0x7a, 0x93, 0xce, 0x58, 0x86, 0x13, 0xfc, 0xd5, 0x86, 0xfe, 0x23, 0x5c, 0xe6,
0xc9, 0x24, 0x22, 0x3f, 0x97, 0x44, 0x48, 0x34, 0x80, 0x46, 0x32, 0x4b, 0x7d, 0x6f, 0xcb, 0x1b,
0x75, 0x22, 0xf5, 0x89, 0x10, 0xac, 0x62, 0x3e, 0x16, 0xfe, 0xca, 0x56, 0x63, 0xd4, 0x89, 0xf4,
0x37, 0x7a, 0x02, 0x1d, 0x4e, 0x04, 0x2b, 0x79, 0x42, 0x84, 0xdf, 0xd8, 0xf2, 0x46, 0xdd, 0x9d,
0xab, 0xe1, 0x3f, 0x15, 0x6e, 0xf3, 0x9b, 0x94, 0x61, 0xe4, 0xfc, 0xa2, 0xe3, 0x10, 0xe8, 0x12,
0x74, 0x85, 0x4c, 0x59, 0x29, 0xe3, 0x02, 0xcb, 0x89, 0xbf, 0xaa, 0xb3, 0x83, 0x81, 0xf6, 0xb1,
0x9c, 0x58, 0x02, 0xe1, 0xdc, 0x10, 0x9a, 0x15, 0x81, 0x70, 0xae, 0x09, 0x03, 0x68, 0x90, 0x7c,
0xee, 0xaf, 0xe9, 0x22, 0xd5, 0xa7, 0xaa, 0xbb, 0x14, 0x84, 0xfb, 0x2d, 0xcd, 0xd5, 0xdf, 0xe8,
0x22, 0xb4, 0x25, 0x16, 0xd3, 0x38, 0xa5, 0xdc, 0x6f, 0x6b, 0xbc, 0xa5, 0xec, 0x3d, 0xca, 0xd1,
0x65, 0xd8, 0x70, 0xf5, 0xc4, 0x19, 0x9d, 0x51, 0x29, 0xfc, 0xce, 0x96, 0x37, 0x6a, 0x47, 0xeb,
0x0e, 0x7e, 0xa4, 0x51, 0x74, 0x03, 0xce, 0xbd, 0xc0, 0x82, 0x26, 0x71, 0xc1, 0x59, 0x42, 0x84,
0x88, 0x93, 0x31, 0x67, 0x65, 0xe1, 0x83, 0x62, 0xdf, 0x5b, 0xf1, 0xbd, 0x08, 0xe9, 0xdf, 0xf7,
0xcd, 0xcf, 0xbb, 0xfa, 0x57, 0xb4, 0x07, 0x6b, 0x33, 0x56, 0xe6, 0x52, 0xf8, 0xdd, 0xad, 0xc6,
0xa8, 0xbb, 0x73, 0xa5, 0x66, 0xbb, 0x1e, 0x2b, 0xa7, 0xc8, 0xfa, 0xa2, 0x6f, 0xa1, 0x95, 0x92,
0x39, 0x55, 0x5d, 0xef, 0xe9, 0x30, 0x9f, 0xd5, 0x0c, 0xb3, 0xa7, 0xbd, 0x22, 0xe7, 0x8d, 0x26,
0x70, 0x36, 0x27, 0xf2, 0x35, 0xe3, 0xd3, 0x98, 0x0a, 0x96, 0x61, 0x49, 0x59, 0xee, 0xf7, 0xf5,
0x20, 0xbf, 0xa8, 0x19, 0xf2, 0x89, 0xf1, 0x7f, 0xe0, 0xdc, 0x0f, 0x0a, 0x92, 0x44, 0x83, 0xfc,
0x04, 0x8a, 0x02, 0xe8, 0xe7, 0x2c, 0x2e, 0xe8, 0x9c, 0xc9, 0x98, 0x33, 0x26, 0xfd, 0x75, 0xdd,
0xd5, 0x6e, 0xce, 0xf6, 0x15, 0x16, 0x31, 0x26, 0xd1, 0x08, 0x06, 0x29, 0x79, 0x89, 0xcb, 0x4c,
0xc6, 0x05, 0x4d, 0xe3, 0x19, 0x4b, 0x89, 0xbf, 0xa1, 0xc7, 0xb3, 0x6e, 0xf1, 0x7d, 0x9a, 0x3e,
0x66, 0x29, 0x59, 0x64, 0xd2, 0x22, 0x31, 0xcc, 0xc1, 0x12, 0xf3, 0x41, 0x91, 0x68, 0xe6, 0x47,
0xd0, 0x4f, 0x8a, 0x52, 0x10, 0xe9, 0xe6, 0x73, 0x56, 0xd3, 0x7a, 0x06, 0xb4, 0x53, 0xf9, 0x00,
0x00, 0x67, 0x19, 0x7b, 0x1d, 0x27, 0xb8, 0x10, 0x3e, 0xd2, 0x97, 0xa7, 0xa3, 0x91, 0x5d, 0x5c,
0x08, 0x14, 0x40, 0x2f, 0xc1, 0x05, 0x7e, 0x41, 0x33, 0x2a, 0x29, 0x11, 0xfe, 0xff, 0x34, 0x61,
0x09, 0x43, 0x57, 0x00, 0x99, 0x04, 0xf1, 0x7c, 0x27, 0x66, 0x73, 0xc2, 0x39, 0x4d, 0x89, 0x7f,
0x4e, 0x27, 0x1b, 0x98, 0x5f, 0x9e, 0xed, 0x7c, 0x67, 0x71, 0x74, 0x74, 0xcc, 0xbe, 0x76, 0xcc,
0x3e, 0xaf, 0x67, 0xf9, 0x30, 0xac, 0xb7, 0xfa, 0xe1, 0xd2, 0xc6, 0x86, 0xe6, 0x28, 0xcf, 0xae,
0xb9, 0x1c, 0xf7, 0x73, 0xc9, 0x8f, 0xaa, 0xd4, 0x15, 0xac, 0x06, 0xc1, 0xd8, 0x2c, 0x16, 0x09,
0xe3, 0x24, 0xc6, 0xe9, 0x2b, 0x7f, 0x73, 0xcb, 0x1b, 0x35, 0xa3, 0x2e, 0x63, 0xb3, 0x03, 0x85,
0x7d, 0x9d, 0xbe, 0x52, 0xfb, 0xa1, 0xef, 0x84, 0xda, 0x8f, 0x0b, 0x66, 0x3f, 0x94, 0xbd, 0x47,
0xf9, 0x70, 0x17, 0xce, 0xbf, 0x35, 0x93, 0xda, 0xbc, 0x29, 0x39, 0x72, 0x8a, 0x31, 0x25, 0x47,
0xe8, 0x1c, 0x34, 0xe7, 0x38, 0x2b, 0x89, 0xbf, 0xa2, 0x31, 0x63, 0x7c, 0xbe, 0x72, 0xc7, 0x0b,
0x7e, 0x82, 0x75, 0x57, 0xbc, 0x28, 0x58, 0x2e, 0x08, 0x7a, 0x02, 0x2d, 0xbb, 0x47, 0x3a, 0x42,
0x77, 0xe7, 0x46, 0xdd, 0x2e, 0xd8, 0xfd, 0x3a, 0x90, 0x58, 0x92, 0xc8, 0x05, 0x09, 0xfa, 0xd0,
0x7d, 0x8e, 0xa9, 0xb4, 0xcd, 0x09, 0x7e, 0x84, 0x9e, 0x31, 0xff, 0xa3, 0x74, 0x8f, 0x60, 0xe3,
0x60, 0x52, 0xca, 0x94, 0xbd, 0xce, 0x9d, 0x82, 0x6e, 0xc2, 0x9a, 0xa0, 0xe3, 0x1c, 0x67, 0xb6,
0x25, 0xd6, 0x42, 0x1f, 0x42, 0x6f, 0xcc, 0x71, 0x42, 0xe2, 0x82, 0x70, 0xca, 0x52, 0xdd, 0x9c,
0x46, 0xd4, 0xd5, 0xd8, 0xbe, 0x86, 0x02, 0x04, 0x83, 0xe3, 0x68, 0xa6, 0xe2, 0x60, 0x02, 0x9b,
0xdf, 0x17, 0xa9, 0x4a, 0x5a, 0x09, 0xa7, 0x4d, 0xb4, 0x24, 0xc2, 0xde, 0xbf, 0x16, 0xe1, 0xe0,
0x22, 0x5c, 0x78, 0x23, 0x93, 0x2d, 0x62, 0x00, 0xeb, 0xcf, 0x08, 0x17, 0x94, 0xb9, 0x53, 0x06,
0x9f, 0xc2, 0x46, 0x85, 0xd8, 0xde, 0xfa, 0xd0, 0x9a, 0x1b, 0xc8, 0x9e, 0xdc, 0x99, 0xc1, 0x27,
0xd0, 0x53, 0x7d, 0xab, 0x2a, 0x1f, 0x42, 0x9b, 0xe6, 0x92, 0xf0, 0xb9, 0x6d, 0x52, 0x23, 0xaa,
0xec, 0xe0, 0x39, 0xf4, 0x2d, 0xd7, 0x86, 0xfd, 0x06, 0x9a, 0x42, 0x01, 0xa7, 0x3c, 0xe2, 0x53,
0x2c, 0xa6, 0x26, 0x90, 0x71, 0x0f, 0x2e, 0x43, 0xff, 0x40, 0x4f, 0xe2, 0xed, 0x83, 0x6a, 0xba,
0x41, 0xa9, 0xc3, 0x3a, 0xa2, 0x3d, 0xfe, 0x14, 0xba, 0xf7, 0x0f, 0x49, 0xe2, 0x1c, 0x6f, 0x41,
0x3b, 0x25, 0x38, 0xcd, 0x68, 0x4e, 0x6c, 0x51, 0xc3, 0xd0, 0xbc, 0xc6, 0xa1, 0x7b, 0x8d, 0xc3,
0xa7, 0xee, 0x35, 0x8e, 0x2a, 0xae, 0x7b, 0x5b, 0x57, 0xde, 0x7c, 0x5b, 0x1b, 0xc7, 0x6f, 0x6b,
0xb0, 0x0b, 0x3d, 0x93, 0xcc, 0x9e, 0x7f, 0x13, 0xd6, 0x58, 0x29, 0x8b, 0x52, 0xea, 0x5c, 0xbd,
0xc8, 0x5a, 0xe8, 0xff, 0xd0, 0x21, 0x87, 0x54, 0xc6, 0x89, 0xd2, 0xc0, 0x15, 0x7d, 0x82, 0xb6,
0x02, 0x76, 0x59, 0x4a, 0x82, 0x3f, 0x3d, 0xe8, 0x2d, 0xde, 0x58, 0x95, 0xbb, 0xa0, 0xa9, 0x3d,
0xa9, 0xfa, 0x7c, 0xa7, 0xff, 0x42, 0x6f, 0x1a, 0x8b, 0xbd, 0x41, 0x21, 0xac, 0xaa, 0xff, 0x33,
0xf4, 0x0b, 0xfd, 0xee, 0x63, 0x6b, 0x9e, 0x12, 0x58, 0x25, 0x3a, 0x53, 0x9a, 0x65, 0x24, 0xd5,
0xcf, 0x76, 0x3b, 0xea, 0x30, 0x36, 0x7b, 0xa8, 0x81, 0x9d, 0xdf, 0x3b, 0xd0, 0xbe, 0x6f, 0xf7,
0x0c, 0x1d, 0xc1, 0x9a, 0x11, 0x07, 0x74, 0xf3, 0xbd, 0x94, 0x70, 0x78, 0xeb, 0xb4, 0x6e, 0x76,
0xbc, 0x67, 0x90, 0x80, 0x55, 0x25, 0x13, 0xe8, 0x7a, 0xdd, 0x08, 0x0b, 0x1a, 0x33, 0xbc, 0x71,
0x3a, 0xa7, 0x2a, 0xe9, 0xaf, 0xd0, 0x76, 0xdb, 0x8e, 0x6e, 0xd7, 0x8d, 0x71, 0x42, 0x6d, 0x86,
0x77, 0x4e, 0xef, 0x58, 0x15, 0xf0, 0x9b, 0x07, 0x1b, 0x27, 0x36, 0x1e, 0x7d, 0x59, 0x37, 0xde,
0xdb, 0x45, 0x69, 0x78, 0xf7, 0xbd, 0xfd, 0xab, 0xb2, 0x7e, 0x81, 0x96, 0x95, 0x16, 0x54, 0x7b,
0xa2, 0xcb, 0xea, 0x34, 0xbc, 0x7d, 0x6a, 0xbf, 0x2a, 0xfb, 0x21, 0x34, 0xb5, 0x6c, 0xa0, 0xda,
0x63, 0x5d, 0x94, 0xb6, 0xe1, 0xcd, 0x53, 0x7a, 0xb9, 0xbc, 0x57, 0x3d, 0x75, 0xff, 0x8d, 0xee,
0xd4, 0xbf, 0xff, 0x4b, 0x82, 0x56, 0xff, 0xfe, 0x9f, 0x90, 0x37, 0x7d, 0xff, 0xd5, 0x1a, 0xd6,
0xbf, 0xff, 0x0b, 0x72, 0x58, 0xff, 0xfe, 0x2f, 0xca, 0x5a, 0x70, 0x06, 0xfd, 0xe1, 0x41, 0x5f,
0x41, 0x07, 0x92, 0x13, 0x3c, 0xa3, 0xf9, 0x18, 0xdd, 0xad, 0xa9, 0xed, 0xca, 0xcb, 0xe8, 0xbb,
0xf5, 0x74, 0xa5, 0x7c, 0xf5, 0xfe, 0x01, 0x5c, 0x59, 0x23, 0xef, 0xaa, 0x77, 0xaf, 0xf5, 0x43,
0xd3, 0x48, 0xda, 0x9a, 0xfe, 0x73, 0xfd, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xc0, 0xa1,
0x7e, 0xc4, 0x0d, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -53,6 +53,7 @@ message LaunchRequest {
string cgroup_v2_override = 20;
map<string,string> cgroup_v1_override = 21;
int32 oom_score_adj = 22;
string work_dir = 23;
}
message LaunchResponse {

View File

@@ -87,6 +87,11 @@ config {
}
```
- `work_dir` - (Optional) Sets a custom working directory for the task. This path must be
absolute and within the task's [chroot](#chroot) or in a [host volume][] mounted
with a [`volume_mount`][volume_mount] block. This will also change the working
directory when using `nomad alloc exec`.
## Examples
To run a binary present on the Node:

View File

@@ -85,6 +85,11 @@ config {
}
```
- `work_dir` - (Optional) Sets a custom working directory for the task. This path must be
absolute and within the task's [chroot](#chroot) or in a [host volume][] mounted
with a [`volume_mount`][volume_mount] block. This will also change the working
directory when using `nomad alloc exec`.
## Examples
A simple config block to run a Java Jar:
@@ -260,3 +265,5 @@ This list is configurable through the agent client
[allow_caps]: /nomad/docs/drivers/java#allow_caps
[docker_caps]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
[cgroup controller requirements]: /nomad/docs/install/production/requirements#hardening-nomad
[volume_mount]: /nomad/docs/job-specification/volume_mount
[host volume]: /nomad/docs/configuration/client#host_volume-block

View File

@@ -53,6 +53,10 @@ the Nomad client has been hardened according to the [production][hardening] guid
- `oom_score_adj` - (Optional) A positive integer to indicate the likelihood of
the task being OOM killed (valid only for Linux). Defaults to 0.
- `work_dir` - (Optional) Sets a custom working directory for the task. This must be an
absolute path. This will also change the working directory when using `nomad alloc exec`.
## Examples
To run a binary present on the Node: