Implement configuration validation for all task drivers

This commit is contained in:
Ivo Verberk 2016-04-10 00:38:42 +02:00
parent 542603dec6
commit 13a2d62bfa
18 changed files with 806 additions and 494 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/hashicorp/nomad/client/driver/executor"
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
@ -126,60 +127,62 @@ func NewDockerDriver(ctx *DriverContext) Driver {
return &DockerDriver{DriverContext: *ctx}
}
// Validate is used to validate the driver configuration
func (d *DockerDriver) Validate(config map[string]interface{}) error {
fd := &FieldData{
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*FieldSchema{
"image": &FieldSchema{
Type: TypeString,
Schema: map[string]*fields.FieldSchema{
"image": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"load": &FieldSchema{
Type: TypeArray,
"load": &fields.FieldSchema{
Type: fields.TypeArray,
},
"command": &FieldSchema{
Type: TypeString,
"command": &fields.FieldSchema{
Type: fields.TypeString,
},
"args": &FieldSchema{
Type: TypeArray,
"args": &fields.FieldSchema{
Type: fields.TypeArray,
},
"ipc_mode": &FieldSchema{
Type: TypeString,
"ipc_mode": &fields.FieldSchema{
Type: fields.TypeString,
},
"network_mode": &FieldSchema{
Type: TypeString,
"network_mode": &fields.FieldSchema{
Type: fields.TypeString,
},
"pid_mode": &FieldSchema{
Type: TypeString,
"pid_mode": &fields.FieldSchema{
Type: fields.TypeString,
},
"uts_mode": &FieldSchema{
Type: TypeString,
"uts_mode": &fields.FieldSchema{
Type: fields.TypeString,
},
"port_map": &FieldSchema{
Type: TypeArray,
"port_map": &fields.FieldSchema{
Type: fields.TypeArray,
},
"privileged": &FieldSchema{
Type: TypeBool,
"privileged": &fields.FieldSchema{
Type: fields.TypeBool,
},
"dns_servers": &FieldSchema{
Type: TypeArray,
"dns_servers": &fields.FieldSchema{
Type: fields.TypeArray,
},
"dns_search_domains": &FieldSchema{
Type: TypeArray,
"dns_search_domains": &fields.FieldSchema{
Type: fields.TypeArray,
},
"hostname": &FieldSchema{
Type: TypeString,
"hostname": &fields.FieldSchema{
Type: fields.TypeString,
},
"labels": &FieldSchema{
Type: TypeMap,
"labels": &fields.FieldSchema{
Type: fields.TypeMap,
},
"auth": &FieldSchema{
Type: TypeArray,
"auth": &fields.FieldSchema{
Type: fields.TypeArray,
},
"ssl": &FieldSchema{
Type: TypeBool,
"ssl": &fields.FieldSchema{
Type: fields.TypeBool,
},
"tty": &FieldSchema{
Type: TypeBool,
"tty": &fields.FieldSchema{
Type: fields.TypeBool,
},
},
}
@ -188,11 +191,6 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error {
return err
}
result, ok := fd.GetOk("image")
if !ok || result == "" {
return fmt.Errorf("image is required")
}
return nil
}

View File

@ -71,6 +71,18 @@ type DriverContext struct {
taskEnv *env.TaskEnvironment
}
// NewEmptyDriverContext returns a DriverContext with all fields set to their
// zero value.
func NewEmptyDriverContext() *DriverContext {
return &DriverContext{
taskName: "",
config: nil,
node: nil,
logger: nil,
taskEnv: nil,
}
}
// NewDriverContext initializes a new DriverContext with the specified fields.
// This enables other packages to create DriverContexts but keeps the fields
// private to the driver. If we want to change this later we can gorename all of

View File

@ -17,6 +17,7 @@ import (
"github.com/hashicorp/nomad/client/driver/executor"
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
@ -59,6 +60,23 @@ func NewExecDriver(ctx *DriverContext) Driver {
}
func (d *ExecDriver) Validate(config map[string]interface{}) error {
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*fields.FieldSchema{
"command": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"args": &fields.FieldSchema{
Type: fields.TypeArray,
},
},
}
if err := fd.Validate(); err != nil {
return err
}
return nil
}

View File

@ -22,6 +22,7 @@ import (
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
)
@ -66,7 +67,28 @@ func NewJavaDriver(ctx *DriverContext) Driver {
return &JavaDriver{DriverContext: *ctx}
}
// Validate is used to validate the driver configuration
func (d *JavaDriver) Validate(config map[string]interface{}) error {
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*fields.FieldSchema{
"jar_path": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"jvm_options": &fields.FieldSchema{
Type: fields.TypeArray,
},
"args": &fields.FieldSchema{
Type: fields.TypeArray,
},
},
}
if err := fd.Validate(); err != nil {
return err
}
return nil
}

View File

@ -18,6 +18,7 @@ import (
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
@ -66,6 +67,26 @@ func NewQemuDriver(ctx *DriverContext) Driver {
}
func (d *QemuDriver) Validate(config map[string]interface{}) error {
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*fields.FieldSchema{
"image_path": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"accelerator": &fields.FieldSchema{
Type: fields.TypeString,
},
"port_map": &fields.FieldSchema{
Type: fields.TypeArray,
},
},
}
if err := fd.Validate(); err != nil {
return err
}
return nil
}

View File

@ -16,6 +16,7 @@ import (
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
@ -57,6 +58,23 @@ func NewRawExecDriver(ctx *DriverContext) Driver {
}
func (d *RawExecDriver) Validate(config map[string]interface{}) error {
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*fields.FieldSchema{
"command": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"args": &fields.FieldSchema{
Type: fields.TypeArray,
},
},
}
if err := fd.Validate(); err != nil {
return err
}
return nil
}

View File

@ -22,6 +22,7 @@ import (
cstructs "github.com/hashicorp/nomad/client/driver/structs"
"github.com/hashicorp/nomad/client/fingerprint"
"github.com/hashicorp/nomad/helper/discover"
"github.com/hashicorp/nomad/helper/fields"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/mapstructure"
)
@ -89,6 +90,29 @@ func NewRktDriver(ctx *DriverContext) Driver {
}
func (d *RktDriver) Validate(config map[string]interface{}) error {
fd := &fields.FieldData{
Raw: config,
Schema: map[string]*fields.FieldSchema{
"image": &fields.FieldSchema{
Type: fields.TypeString,
Required: true,
},
"args": &fields.FieldSchema{
Type: fields.TypeArray,
},
"dns_servers": &fields.FieldSchema{
Type: fields.TypeArray,
},
"dns_search_domains": &fields.FieldSchema{
Type: fields.TypeArray,
},
},
}
if err := fd.Validate(); err != nil {
return err
}
return nil
}

View File

@ -539,10 +539,10 @@ func parseTasks(jobName string, taskGroupName string, result *[]*structs.Task, l
}
}
// Instantiate a dummy driver to validate to configuration
// Instantiate a driver to validate the configuration
d, err := driver.NewDriver(
t.Driver,
driver.NewDriverContext("", nil, nil, nil, nil),
driver.NewEmptyDriverContext(),
)
if err != nil {

View File

@ -53,7 +53,7 @@ func TestParse(t *testing.T) {
Name: "outside",
Driver: "java",
Config: map[string]interface{}{
"jar": "s3://my-cool-store/foo.jar",
"jar_path": "s3://my-cool-store/foo.jar",
},
Meta: map[string]string{
"my-cool-key": "foobar",
@ -148,7 +148,7 @@ func TestParse(t *testing.T) {
},
&structs.Task{
Name: "storagelocker",
Driver: "java",
Driver: "docker",
User: "",
Config: map[string]interface{}{
"image": "hashicorp/storagelocker",
@ -302,6 +302,7 @@ func TestParse(t *testing.T) {
Name: "bar",
Driver: "docker",
Config: map[string]interface{}{
"image": "hashicorp/image",
"port_map": []map[string]interface{}{
map[string]interface{}{
"db": 1234,
@ -319,6 +320,7 @@ func TestParse(t *testing.T) {
},
false,
},
{
"bad-artifact.hcl",
nil,
@ -399,10 +401,65 @@ func TestParse(t *testing.T) {
}
}
func TestBadConfigEmpty(t *testing.T) {
path, err := filepath.Abs(filepath.Join("./test-fixtures", "bad-config-empty.hcl"))
if err != nil {
t.Fatalf("Can't get absolute path for file: %s", err)
}
_, err = ParseFile(path)
if !strings.Contains(err.Error(), "field \"image\" is required, but no value was found") {
t.Fatalf("\nExpected error\n %s\ngot\n %v",
"field \"image\" is required, but no value was found",
err,
)
}
}
func TestBadConfigMissing(t *testing.T) {
path, err := filepath.Abs(filepath.Join("./test-fixtures", "bad-config-missing.hcl"))
if err != nil {
t.Fatalf("Can't get absolute path for file: %s", err)
}
_, err = ParseFile(path)
if !strings.Contains(err.Error(), "field \"image\" is required") {
t.Fatalf("\nExpected error\n %s\ngot\n %v",
"field \"image\" is required",
err,
)
}
}
func TestBadConfig(t *testing.T) {
path, err := filepath.Abs(filepath.Join("./test-fixtures", "bad-config.hcl"))
if err != nil {
t.Fatalf("Can't get absolute path for file: %s", err)
}
_, err = ParseFile(path)
if !strings.Contains(err.Error(), "seem to be of type boolean") {
t.Fatalf("\nExpected error\n %s\ngot\n %v",
"seem to be of type boolean",
err,
)
}
if !strings.Contains(err.Error(), "\"foo\" is an invalid field") {
t.Fatalf("\nExpected error\n %s\ngot\n %v",
"\"foo\" is an invalid field",
err,
)
}
}
func TestBadPorts(t *testing.T) {
path, err := filepath.Abs(filepath.Join("./test-fixtures", "bad-ports.hcl"))
if err != nil {
t.Fatalf("Can't get absoluate path for file: %s", err)
t.Fatalf("Can't get absolute path for file: %s", err)
}
_, err = ParseFile(path)

View File

@ -0,0 +1,16 @@
job "binstore-storagelocker" {
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = ""
}
resources {
}
}
}
}

View File

@ -0,0 +1,15 @@
job "binstore-storagelocker" {
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
}
resources {
}
}
}
}

View File

@ -0,0 +1,18 @@
job "binstore-storagelocker" {
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = "hashicorp/image"
privileged = "false"
foo = "bar"
}
resources {
}
}
}
}

View File

@ -1,86 +1,101 @@
job "binstore-storagelocker" {
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
meta {
foo = "bar"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar_path = "s3://my-cool-store/foo.jar"
}
meta {
foo = "bar"
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "this_is_aport" {
}
port "" {
}
}
}
}
task "storagelocker" {
driver = "docker"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "windows"
attribute = "kernel.os"
value = "linux"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar = "s3://my-cool-store/foo.jar"
}
meta {
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "this_is_aport" {}
port ""{}
}
}
}
task "storagelocker" {
driver = "java"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "linux"
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
}
}

View File

@ -1,129 +1,153 @@
job "binstore-storagelocker" {
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
meta {
foo = "bar"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar_path = "s3://my-cool-store/foo.jar"
}
meta {
foo = "bar"
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
mode = "delay"
}
task "binstore" {
driver = "docker"
user = "bob"
config {
image = "hashicorp/binstore"
}
logs {
max_files = 10
max_file_size = 100
}
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "tcp"
interval = "10s"
timeout = "2s"
}
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "http" {
}
port "https" {
}
port "admin" {
}
}
}
kill_timeout = "22s"
artifact {
source = "http://foo.com/artifact"
options {
checksum = "md5:b8a4f3f72ecab0510a6a31e997461c5f"
}
}
artifact {
source = "http://bar.com/artifact"
options {
checksum = "md5:ff1cc0d3432dad54d607c1505fb7245c"
}
}
}
task "storagelocker" {
driver = "docker"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
iops = 30
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "windows"
attribute = "kernel.os"
value = "linux"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar = "s3://my-cool-store/foo.jar"
}
meta {
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
mode = "delay"
}
task "binstore" {
driver = "docker"
user = "bob"
config {
image = "hashicorp/binstore"
}
logs {
max_files = 10
max_file_size = 100
}
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "tcp"
interval = "10s"
timeout = "2s"
}
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "http" {}
port "https" {}
port "admin" {}
}
}
kill_timeout = "22s"
artifact {
source = "http://foo.com/artifact"
options {
checksum = "md5:b8a4f3f72ecab0510a6a31e997461c5f"
}
}
artifact {
source = "http://bar.com/artifact"
options {
checksum = "md5:ff1cc0d3432dad54d607c1505fb7245c"
}
}
}
task "storagelocker" {
driver = "java"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
iops = 30
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "linux"
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
}
}

View File

@ -1,114 +1,136 @@
job "binstore-storagelocker" {
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
meta {
foo = "bar"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar_path = "s3://my-cool-store/foo.jar"
}
meta {
foo = "bar"
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
mode = "delay"
}
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
logs {
max_files = 10
max_file_size = 100
}
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "tcp"
nterval = "10s"
timeout = "2s"
}
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "http" {
}
port "https" {
}
port "admin" {
}
}
}
kill_timeout = "22s"
}
task "storagelocker" {
driver = "docker"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
iops = 30
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "windows"
attribute = "kernel.os"
value = "linux"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar = "s3://my-cool-store/foo.jar"
}
meta {
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
mode = "delay"
}
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
logs {
max_files = 10
max_file_size = 100
}
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "tcp"
nterval = "10s"
timeout = "2s"
}
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "http" {}
port "https" {}
port "admin" {}
}
}
kill_timeout = "22s"
}
task "storagelocker" {
driver = "java"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
iops = 30
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "linux"
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
}
}

View File

@ -1,78 +1,92 @@
job "binstore-storagelocker" {
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
meta {
foo = "bar"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar_path = "s3://my-cool-store/foo.jar"
}
meta {
foo = "bar"
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
task "binstore" {
driver = "docker"
update {
stagger = "60s"
max_parallel = 2
}
config {
image = "hashicorp/binstore"
}
task "outside" {
driver = "java"
config {
jar = "s3://my-cool-store/foo.jar"
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "http"
interval = "10s"
timeout = "2s"
}
meta {
my-cool-key = "foobar"
}
}
}
group "binsl" {
count = 5
restart {
attempts = 5
interval = "10m"
delay = "15s"
}
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
env {
HELLO = "world"
LOREM = "ipsum"
}
service {
tags = ["foo", "bar"]
port = "http"
check {
name = "check-name"
type = "http"
interval = "10s"
timeout = "2s"
}
}
service {
port = "one"
}
resources {
cpu = 500
memory = 128
service {
port = "one"
}
network {
mbits = "100"
port "one" {
static = 1
}
port "three" {
static = 3
}
port "http" {}
}
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "three" {
static = 3
}
port "http" {
}
}
}
}
}
}

View File

@ -1,87 +1,102 @@
job "binstore-storagelocker" {
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
region = "global"
type = "service"
priority = 50
all_at_once = true
datacenters = ["us2", "eu1"]
meta {
foo = "bar"
}
constraint {
attribute = "kernel.os"
value = "windows"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar_path = "s3://my-cool-store/foo.jar"
}
meta {
foo = "bar"
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "Http"{
}
port "http"{
}
port "HTTP"{
}
}
}
}
task "storagelocker" {
driver = "docker"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "windows"
attribute = "kernel.os"
value = "linux"
}
update {
stagger = "60s"
max_parallel = 2
}
task "outside" {
driver = "java"
config {
jar = "s3://my-cool-store/foo.jar"
}
meta {
my-cool-key = "foobar"
}
}
group "binsl" {
count = 5
task "binstore" {
driver = "docker"
config {
image = "hashicorp/binstore"
}
resources {
cpu = 500
memory = 128
network {
mbits = "100"
port "one" {
static = 1
}
port "two" {
static = 2
}
port "three" {
static = 3
}
port "Http" {}
port "http" {}
port "HTTP" {}
}
}
}
task "storagelocker" {
driver = "java"
config {
image = "hashicorp/storagelocker"
}
resources {
cpu = 500
memory = 128
}
constraint {
attribute = "kernel.arch"
value = "amd64"
}
}
constraint {
attribute = "kernel.os"
value = "linux"
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
meta {
elb_mode = "tcp"
elb_interval = 10
elb_checks = 3
}
}
}

View File

@ -1,10 +1,13 @@
job "foo" {
task "bar" {
driver = "docker"
config {
port_map {
db = 1234
}
}
task "bar" {
driver = "docker"
config {
image = "hashicorp/image"
port_map {
db = 1234
}
}
}
}