jobspec: Add Volume and VolumeMount declarations
This commit is contained in:
parent
1871c1edbc
commit
b45bd36230
|
@ -53,6 +53,7 @@ func parseGroups(result *api.Job, list *ast.ObjectList) error {
|
||||||
"spread",
|
"spread",
|
||||||
"network",
|
"network",
|
||||||
"service",
|
"service",
|
||||||
|
"volume",
|
||||||
}
|
}
|
||||||
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
||||||
return multierror.Prefix(err, fmt.Sprintf("'%s' ->", n))
|
return multierror.Prefix(err, fmt.Sprintf("'%s' ->", n))
|
||||||
|
@ -74,6 +75,7 @@ func parseGroups(result *api.Job, list *ast.ObjectList) error {
|
||||||
delete(m, "spread")
|
delete(m, "spread")
|
||||||
delete(m, "network")
|
delete(m, "network")
|
||||||
delete(m, "service")
|
delete(m, "service")
|
||||||
|
delete(m, "volume")
|
||||||
|
|
||||||
// Build the group with the basic decode
|
// Build the group with the basic decode
|
||||||
var g api.TaskGroup
|
var g api.TaskGroup
|
||||||
|
@ -161,6 +163,13 @@ func parseGroups(result *api.Job, list *ast.ObjectList) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse any volume declarations
|
||||||
|
if o := listVal.Filter("volume"); len(o.Items) > 0 {
|
||||||
|
if err := parseVolumes(&g.Volumes, o); err != nil {
|
||||||
|
return multierror.Prefix(err, "volume ->")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse tasks
|
// Parse tasks
|
||||||
if o := listVal.Filter("task"); len(o.Items) > 0 {
|
if o := listVal.Filter("task"); len(o.Items) > 0 {
|
||||||
if err := parseTasks(&g.Tasks, o); err != nil {
|
if err := parseTasks(&g.Tasks, o); err != nil {
|
||||||
|
@ -274,3 +283,61 @@ func parseRestartPolicy(final **api.RestartPolicy, list *ast.ObjectList) error {
|
||||||
*final = &result
|
*final = &result
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseVolumes(out *map[string]*api.Volume, list *ast.ObjectList) error {
|
||||||
|
volumes := make(map[string]*api.Volume, len(list.Items))
|
||||||
|
|
||||||
|
for _, item := range list.Items {
|
||||||
|
n := item.Keys[0].Token.Value().(string)
|
||||||
|
valid := []string{
|
||||||
|
"type",
|
||||||
|
"read_only",
|
||||||
|
"hidden",
|
||||||
|
"config",
|
||||||
|
}
|
||||||
|
if err := helper.CheckHCLKeys(item.Val, valid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(dani): FIXME: this is gross but we don't have ObjectList.Filter here
|
||||||
|
var cfg map[string]interface{}
|
||||||
|
if cfgI, ok := m["config"]; ok {
|
||||||
|
cfgL, ok := cfgI.([]map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Incorrect `config` type, expected map")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfgL) != 1 {
|
||||||
|
return fmt.Errorf("Expected single `config`, found %d", len(cfgL))
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg = cfgL[0]
|
||||||
|
}
|
||||||
|
delete(m, "config")
|
||||||
|
|
||||||
|
var result api.Volume
|
||||||
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
WeaklyTypedInput: true,
|
||||||
|
Result: &result,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := dec.Decode(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Name = n
|
||||||
|
result.Config = cfg
|
||||||
|
|
||||||
|
volumes[n] = &result
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = volumes
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ func parseTask(item *ast.ObjectItem) (*api.Task, error) {
|
||||||
"vault",
|
"vault",
|
||||||
"kill_signal",
|
"kill_signal",
|
||||||
"kind",
|
"kind",
|
||||||
|
"volume_mount",
|
||||||
}
|
}
|
||||||
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -93,6 +94,7 @@ func parseTask(item *ast.ObjectItem) (*api.Task, error) {
|
||||||
delete(m, "service")
|
delete(m, "service")
|
||||||
delete(m, "template")
|
delete(m, "template")
|
||||||
delete(m, "vault")
|
delete(m, "vault")
|
||||||
|
delete(m, "volume_mount")
|
||||||
|
|
||||||
// Build the task
|
// Build the task
|
||||||
var t api.Task
|
var t api.Task
|
||||||
|
@ -173,6 +175,14 @@ func parseTask(item *ast.ObjectItem) (*api.Task, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse volume mounts
|
||||||
|
if o := listVal.Filter("volume_mount"); len(o.Items) > 0 {
|
||||||
|
if err := parseVolumeMounts(&t.VolumeMounts, o); err != nil {
|
||||||
|
return multierror.Prefix(err, fmt.Sprintf(
|
||||||
|
"'%s', volume_mount ->", n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we have resources, then parse that
|
// If we have resources, then parse that
|
||||||
if o := listVal.Filter("resources"); len(o.Items) > 0 {
|
if o := listVal.Filter("resources"); len(o.Items) > 0 {
|
||||||
var r api.Resources
|
var r api.Resources
|
||||||
|
@ -504,3 +514,40 @@ func parseResources(result *api.Resources, list *ast.ObjectList) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseVolumeMounts(out *[]*api.VolumeMount, list *ast.ObjectList) error {
|
||||||
|
mounts := make([]*api.VolumeMount, len(list.Items))
|
||||||
|
|
||||||
|
for i, item := range list.Items {
|
||||||
|
valid := []string{
|
||||||
|
"volume",
|
||||||
|
"read_only",
|
||||||
|
"destination",
|
||||||
|
}
|
||||||
|
if err := helper.CheckHCLKeys(item.Val, valid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var m map[string]interface{}
|
||||||
|
if err := hcl.DecodeObject(&m, item.Val); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result api.VolumeMount
|
||||||
|
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
WeaklyTypedInput: true,
|
||||||
|
Result: &result,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := dec.Decode(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts[i] = &result
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = mounts
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ func TestParse(t *testing.T) {
|
||||||
TaskGroups: []*api.TaskGroup{
|
TaskGroups: []*api.TaskGroup{
|
||||||
{
|
{
|
||||||
Name: helper.StringToPtr("outside"),
|
Name: helper.StringToPtr("outside"),
|
||||||
|
|
||||||
Tasks: []*api.Task{
|
Tasks: []*api.Task{
|
||||||
{
|
{
|
||||||
Name: "outside",
|
Name: "outside",
|
||||||
|
@ -110,6 +111,13 @@ func TestParse(t *testing.T) {
|
||||||
Operand: "=",
|
Operand: "=",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Volumes: map[string]*api.Volume{
|
||||||
|
"foo": {
|
||||||
|
Name: "foo",
|
||||||
|
Type: "host",
|
||||||
|
},
|
||||||
|
},
|
||||||
Affinities: []*api.Affinity{
|
Affinities: []*api.Affinity{
|
||||||
{
|
{
|
||||||
LTarget: "${node.datacenter}",
|
LTarget: "${node.datacenter}",
|
||||||
|
@ -187,6 +195,12 @@ func TestParse(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
VolumeMounts: []*api.VolumeMount{
|
||||||
|
{
|
||||||
|
Volume: "foo",
|
||||||
|
Destination: "/mnt/foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
Affinities: []*api.Affinity{
|
Affinities: []*api.Affinity{
|
||||||
{
|
{
|
||||||
LTarget: "${meta.foo}",
|
LTarget: "${meta.foo}",
|
||||||
|
|
|
@ -63,6 +63,10 @@ job "binstore-storagelocker" {
|
||||||
group "binsl" {
|
group "binsl" {
|
||||||
count = 5
|
count = 5
|
||||||
|
|
||||||
|
volume "foo" {
|
||||||
|
type = "host"
|
||||||
|
}
|
||||||
|
|
||||||
restart {
|
restart {
|
||||||
attempts = 5
|
attempts = 5
|
||||||
interval = "10m"
|
interval = "10m"
|
||||||
|
@ -143,6 +147,11 @@ job "binstore-storagelocker" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
volume = "foo"
|
||||||
|
destination = "/mnt/foo"
|
||||||
|
}
|
||||||
|
|
||||||
logs {
|
logs {
|
||||||
max_files = 14
|
max_files = 14
|
||||||
max_file_size = 101
|
max_file_size = 101
|
||||||
|
|
Loading…
Reference in New Issue