Merge pull request #5297 from hashicorp/b-docker-logging
Docker: Fix logging config parsing
This commit is contained in:
commit
3b84e08fa4
|
@ -11,7 +11,6 @@ import (
|
||||||
metrics "github.com/armon/go-metrics"
|
metrics "github.com/armon/go-metrics"
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/hcl2/hcl"
|
|
||||||
"github.com/hashicorp/hcl2/hcldec"
|
"github.com/hashicorp/hcl2/hcldec"
|
||||||
"github.com/hashicorp/nomad/client/allocdir"
|
"github.com/hashicorp/nomad/client/allocdir"
|
||||||
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
|
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
|
||||||
|
@ -620,12 +619,7 @@ func (tr *TaskRunner) runDriver() error {
|
||||||
tr.logger.Warn("some environment variables not available for rendering", "keys", strings.Join(keys, ", "))
|
tr.logger.Warn("some environment variables not available for rendering", "keys", strings.Join(keys, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
evalCtx := &hcl.EvalContext{
|
val, diag := hclutils.ParseHclInterface(tr.task.Config, tr.taskSchema, vars)
|
||||||
Variables: vars,
|
|
||||||
Functions: hclutils.GetStdlibFuncs(),
|
|
||||||
}
|
|
||||||
|
|
||||||
val, diag := hclutils.ParseHclInterface(tr.task.Config, tr.taskSchema, evalCtx)
|
|
||||||
if diag.HasErrors() {
|
if diag.HasErrors() {
|
||||||
return multierror.Append(errors.New("failed to parse config"), diag.Errs()...)
|
return multierror.Append(errors.New("failed to parse config"), diag.Errs()...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1935,6 +1935,8 @@ func (c *Client) runAllocs(update *allocUpdates) {
|
||||||
c.logger.Debug("allocation updates", "added", len(diff.added), "removed", len(diff.removed),
|
c.logger.Debug("allocation updates", "added", len(diff.added), "removed", len(diff.removed),
|
||||||
"updated", len(diff.updated), "ignored", len(diff.ignore))
|
"updated", len(diff.updated), "ignored", len(diff.ignore))
|
||||||
|
|
||||||
|
errs := 0
|
||||||
|
|
||||||
// Remove the old allocations
|
// Remove the old allocations
|
||||||
for _, remove := range diff.removed {
|
for _, remove := range diff.removed {
|
||||||
c.removeAlloc(remove)
|
c.removeAlloc(remove)
|
||||||
|
@ -1949,6 +1951,7 @@ func (c *Client) runAllocs(update *allocUpdates) {
|
||||||
// Make room for new allocations before running
|
// Make room for new allocations before running
|
||||||
if err := c.garbageCollector.MakeRoomFor(diff.added); err != nil {
|
if err := c.garbageCollector.MakeRoomFor(diff.added); err != nil {
|
||||||
c.logger.Error("error making room for new allocations", "error", err)
|
c.logger.Error("error making room for new allocations", "error", err)
|
||||||
|
errs++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the new allocations
|
// Start the new allocations
|
||||||
|
@ -1956,6 +1959,7 @@ func (c *Client) runAllocs(update *allocUpdates) {
|
||||||
migrateToken := update.migrateTokens[add.ID]
|
migrateToken := update.migrateTokens[add.ID]
|
||||||
if err := c.addAlloc(add, migrateToken); err != nil {
|
if err := c.addAlloc(add, migrateToken); err != nil {
|
||||||
c.logger.Error("error adding alloc", "error", err, "alloc_id", add.ID)
|
c.logger.Error("error adding alloc", "error", err, "alloc_id", add.ID)
|
||||||
|
errs++
|
||||||
// We mark the alloc as failed and send an update to the server
|
// We mark the alloc as failed and send an update to the server
|
||||||
// We track the fact that creating an allocrunner failed so that we don't send updates again
|
// We track the fact that creating an allocrunner failed so that we don't send updates again
|
||||||
if add.ClientStatus != structs.AllocClientStatusFailed {
|
if add.ClientStatus != structs.AllocClientStatusFailed {
|
||||||
|
@ -1967,6 +1971,8 @@ func (c *Client) runAllocs(update *allocUpdates) {
|
||||||
// Trigger the GC once more now that new allocs are started that could
|
// Trigger the GC once more now that new allocs are started that could
|
||||||
// have caused thresholds to be exceeded
|
// have caused thresholds to be exceeded
|
||||||
c.garbageCollector.Trigger()
|
c.garbageCollector.Trigger()
|
||||||
|
c.logger.Debug("allocation updates applied", "added", len(diff.added), "removed", len(diff.removed),
|
||||||
|
"updated", len(diff.updated), "ignored", len(diff.ignore), "errors", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeFailedAlloc creates a stripped down version of the allocation passed in
|
// makeFailedAlloc creates a stripped down version of the allocation passed in
|
||||||
|
|
|
@ -533,8 +533,11 @@ func (c *ServiceClient) sync() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Debug("sync complete", "registered_services", sreg, "deregistered_services", sdereg,
|
// Only log if something was actually synced
|
||||||
"registered_checks", creg, "deregistered_checks", cdereg)
|
if sreg > 0 || sdereg > 0 || creg > 0 || cdereg > 0 {
|
||||||
|
c.logger.Debug("sync complete", "registered_services", sreg, "deregistered_services", sdereg,
|
||||||
|
"registered_checks", creg, "deregistered_checks", cdereg)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ var (
|
||||||
"ipv6_address": hclspec.NewAttr("ipv6_address", "string", false),
|
"ipv6_address": hclspec.NewAttr("ipv6_address", "string", false),
|
||||||
"labels": hclspec.NewBlockAttrs("labels", "string", false),
|
"labels": hclspec.NewBlockAttrs("labels", "string", false),
|
||||||
"load": hclspec.NewAttr("load", "string", false),
|
"load": hclspec.NewAttr("load", "string", false),
|
||||||
"logging": hclspec.NewBlockSet("logging", hclspec.NewObject(map[string]*hclspec.Spec{
|
"logging": hclspec.NewBlock("logging", false, hclspec.NewObject(map[string]*hclspec.Spec{
|
||||||
"type": hclspec.NewAttr("type", "string", false),
|
"type": hclspec.NewAttr("type", "string", false),
|
||||||
"config": hclspec.NewBlockAttrs("config", "string", false),
|
"config": hclspec.NewBlockAttrs("config", "string", false),
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -15,8 +15,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseHclInterface is used to convert an interface value representing a hcl2
|
// ParseHclInterface is used to convert an interface value representing a hcl2
|
||||||
// body and return the interpolated value.
|
// body and return the interpolated value. Vars may be nil if there are no
|
||||||
func ParseHclInterface(val interface{}, spec hcldec.Spec, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
// variables to interpolate.
|
||||||
|
func ParseHclInterface(val interface{}, spec hcldec.Spec, vars map[string]cty.Value) (cty.Value, hcl.Diagnostics) {
|
||||||
|
evalCtx := &hcl.EvalContext{
|
||||||
|
Variables: vars,
|
||||||
|
Functions: GetStdlibFuncs(),
|
||||||
|
}
|
||||||
|
|
||||||
// Encode to json
|
// Encode to json
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := codec.NewEncoder(&buf, structs.JsonHandle)
|
enc := codec.NewEncoder(&buf, structs.JsonHandle)
|
||||||
|
@ -37,7 +43,7 @@ func ParseHclInterface(val interface{}, spec hcldec.Spec, ctx *hcl.EvalContext)
|
||||||
return cty.NilVal, diag
|
return cty.NilVal, diag
|
||||||
}
|
}
|
||||||
|
|
||||||
value, decDiag := hcldec.Decode(hclFile.Body, spec, ctx)
|
value, decDiag := hcldec.Decode(hclFile.Body, spec, evalCtx)
|
||||||
diag = diag.Extend(decDiag)
|
diag = diag.Extend(decDiag)
|
||||||
if diag.HasErrors() {
|
if diag.HasErrors() {
|
||||||
return cty.NilVal, diag
|
return cty.NilVal, diag
|
||||||
|
|
|
@ -1,82 +1,23 @@
|
||||||
package hclutils
|
package hclutils_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
"github.com/hashicorp/hcl/hcl/ast"
|
||||||
hcl2 "github.com/hashicorp/hcl2/hcl"
|
|
||||||
"github.com/hashicorp/hcl2/hcldec"
|
"github.com/hashicorp/hcl2/hcldec"
|
||||||
"github.com/hashicorp/nomad/helper"
|
"github.com/hashicorp/nomad/drivers/docker"
|
||||||
|
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
|
||||||
|
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
|
||||||
"github.com/hashicorp/nomad/nomad/structs"
|
"github.com/hashicorp/nomad/nomad/structs"
|
||||||
|
"github.com/hashicorp/nomad/plugins/drivers"
|
||||||
"github.com/kr/pretty"
|
"github.com/kr/pretty"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/ugorji/go/codec"
|
"github.com/ugorji/go/codec"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
"github.com/zclconf/go-cty/cty/gocty"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
dockerSpec hcldec.Spec = hcldec.ObjectSpec(map[string]hcldec.Spec{
|
|
||||||
"image": &hcldec.AttrSpec{
|
|
||||||
Name: "image",
|
|
||||||
Type: cty.String,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"args": &hcldec.AttrSpec{
|
|
||||||
Name: "args",
|
|
||||||
Type: cty.List(cty.String),
|
|
||||||
},
|
|
||||||
"pids_limit": &hcldec.AttrSpec{
|
|
||||||
Name: "pids_limit",
|
|
||||||
Type: cty.Number,
|
|
||||||
},
|
|
||||||
"port_map": &hcldec.BlockAttrsSpec{
|
|
||||||
TypeName: "port_map",
|
|
||||||
ElementType: cty.String,
|
|
||||||
},
|
|
||||||
|
|
||||||
"devices": &hcldec.BlockListSpec{
|
|
||||||
TypeName: "devices",
|
|
||||||
Nested: hcldec.ObjectSpec(map[string]hcldec.Spec{
|
|
||||||
"host_path": &hcldec.AttrSpec{
|
|
||||||
Name: "host_path",
|
|
||||||
Type: cty.String,
|
|
||||||
},
|
|
||||||
"container_path": &hcldec.AttrSpec{
|
|
||||||
Name: "container_path",
|
|
||||||
Type: cty.String,
|
|
||||||
},
|
|
||||||
"cgroup_permissions": &hcldec.DefaultSpec{
|
|
||||||
Primary: &hcldec.AttrSpec{
|
|
||||||
Name: "cgroup_permissions",
|
|
||||||
Type: cty.String,
|
|
||||||
},
|
|
||||||
Default: &hcldec.LiteralSpec{
|
|
||||||
Value: cty.StringVal(""),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
type dockerConfig struct {
|
|
||||||
Image string `cty:"image"`
|
|
||||||
Args []string `cty:"args"`
|
|
||||||
PidsLimit *int64 `cty:"pids_limit"`
|
|
||||||
PortMap map[string]string `cty:"port_map"`
|
|
||||||
Devices []DockerDevice `cty:"devices"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DockerDevice struct {
|
|
||||||
HostPath string `cty:"host_path"`
|
|
||||||
ContainerPath string `cty:"container_path"`
|
|
||||||
CgroupPermissions string `cty:"cgroup_permissions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func hclConfigToInterface(t *testing.T, config string) interface{} {
|
func hclConfigToInterface(t *testing.T, config string) interface{} {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
@ -121,30 +62,22 @@ func jsonConfigToInterface(t *testing.T, config string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseHclInterface_Hcl(t *testing.T) {
|
func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
defaultCtx := &hcl2.EvalContext{
|
dockerDriver := new(docker.Driver)
|
||||||
Functions: GetStdlibFuncs(),
|
dockerSpec, err := dockerDriver.TaskConfigSchema()
|
||||||
}
|
require.NoError(t, err)
|
||||||
variableCtx := &hcl2.EvalContext{
|
dockerDecSpec, diags := hclspecutils.Convert(dockerSpec)
|
||||||
Functions: GetStdlibFuncs(),
|
require.False(t, diags.HasErrors())
|
||||||
Variables: map[string]cty.Value{
|
|
||||||
"NOMAD_ALLOC_INDEX": cty.NumberIntVal(2),
|
|
||||||
"NOMAD_META_hello": cty.StringVal("world"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX Useful for determining what cty thinks the type is
|
vars := map[string]cty.Value{
|
||||||
//implied, err := gocty.ImpliedType(&dockerConfig{})
|
"NOMAD_ALLOC_INDEX": cty.NumberIntVal(2),
|
||||||
//if err != nil {
|
"NOMAD_META_hello": cty.StringVal("world"),
|
||||||
//t.Fatalf("implied type failed: %v", err)
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
//t.Logf("Implied type: %v", implied.GoString())
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
config interface{}
|
config interface{}
|
||||||
spec hcldec.Spec
|
spec hcldec.Spec
|
||||||
ctx *hcl2.EvalContext
|
vars map[string]cty.Value
|
||||||
expected interface{}
|
expected interface{}
|
||||||
expectedType interface{}
|
expectedType interface{}
|
||||||
}{
|
}{
|
||||||
|
@ -154,13 +87,13 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
config {
|
config {
|
||||||
image = "redis:3.2"
|
image = "redis:3.2"
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single string attr json",
|
name: "single string attr json",
|
||||||
|
@ -170,13 +103,13 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"image": "redis:3.2"
|
"image": "redis:3.2"
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "number attr",
|
name: "number attr",
|
||||||
|
@ -185,14 +118,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
image = "redis:3.2"
|
image = "redis:3.2"
|
||||||
pids_limit = 2
|
pids_limit = 2
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PidsLimit: helper.Int64ToPtr(2),
|
PidsLimit: 2,
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "number attr json",
|
name: "number attr json",
|
||||||
|
@ -203,14 +136,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"pids_limit": "2"
|
"pids_limit": "2"
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PidsLimit: helper.Int64ToPtr(2),
|
PidsLimit: 2,
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "number attr interpolated",
|
name: "number attr interpolated",
|
||||||
|
@ -219,14 +152,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
image = "redis:3.2"
|
image = "redis:3.2"
|
||||||
pids_limit = "${2 + 2}"
|
pids_limit = "${2 + 2}"
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PidsLimit: helper.Int64ToPtr(4),
|
PidsLimit: 4,
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "number attr interploated json",
|
name: "number attr interploated json",
|
||||||
|
@ -237,14 +170,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"pids_limit": "${2 + 2}"
|
"pids_limit": "${2 + 2}"
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PidsLimit: helper.Int64ToPtr(4),
|
PidsLimit: 4,
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multi attr",
|
name: "multi attr",
|
||||||
|
@ -253,14 +186,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
image = "redis:3.2"
|
image = "redis:3.2"
|
||||||
args = ["foo", "bar"]
|
args = ["foo", "bar"]
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Args: []string{"foo", "bar"},
|
Args: []string{"foo", "bar"},
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multi attr json",
|
name: "multi attr json",
|
||||||
|
@ -271,14 +204,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"args": ["foo", "bar"]
|
"args": ["foo", "bar"]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Args: []string{"foo", "bar"},
|
Args: []string{"foo", "bar"},
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multi attr variables",
|
name: "multi attr variables",
|
||||||
|
@ -288,15 +221,16 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
args = ["${NOMAD_META_hello}", "${NOMAD_ALLOC_INDEX}"]
|
args = ["${NOMAD_META_hello}", "${NOMAD_ALLOC_INDEX}"]
|
||||||
pids_limit = "${NOMAD_ALLOC_INDEX + 2}"
|
pids_limit = "${NOMAD_ALLOC_INDEX + 2}"
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: variableCtx,
|
vars: vars,
|
||||||
expected: &dockerConfig{
|
expected: &docker.TaskConfig{
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Args: []string{"world", "2"},
|
Args: []string{"world", "2"},
|
||||||
PidsLimit: helper.Int64ToPtr(4),
|
PidsLimit: 4,
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "multi attr variables json",
|
name: "multi attr variables json",
|
||||||
|
@ -307,14 +241,14 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"args": ["foo", "bar"]
|
"args": ["foo", "bar"]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Args: []string{"foo", "bar"},
|
Args: []string{"foo", "bar"},
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "port_map",
|
name: "port_map",
|
||||||
|
@ -322,21 +256,21 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
config {
|
config {
|
||||||
image = "redis:3.2"
|
image = "redis:3.2"
|
||||||
port_map {
|
port_map {
|
||||||
foo = "db"
|
foo = 1234
|
||||||
bar = "db2"
|
bar = 5678
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PortMap: map[string]string{
|
PortMap: map[string]int{
|
||||||
"foo": "db",
|
"foo": 1234,
|
||||||
"bar": "db2",
|
"bar": 5678,
|
||||||
},
|
},
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "port_map json",
|
name: "port_map json",
|
||||||
|
@ -345,22 +279,22 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
"Config": {
|
"Config": {
|
||||||
"image": "redis:3.2",
|
"image": "redis:3.2",
|
||||||
"port_map": [{
|
"port_map": [{
|
||||||
"foo": "db",
|
"foo": 1234,
|
||||||
"bar": "db2"
|
"bar": 5678
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
PortMap: map[string]string{
|
PortMap: map[string]int{
|
||||||
"foo": "db",
|
"foo": 1234,
|
||||||
"bar": "db2",
|
"bar": 5678,
|
||||||
},
|
},
|
||||||
Devices: []DockerDevice{},
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "devices",
|
name: "devices",
|
||||||
|
@ -379,11 +313,10 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Devices: []DockerDevice{
|
Devices: []docker.DockerDevice{
|
||||||
{
|
{
|
||||||
HostPath: "/dev/sda1",
|
HostPath: "/dev/sda1",
|
||||||
ContainerPath: "/dev/xvdc",
|
ContainerPath: "/dev/xvdc",
|
||||||
|
@ -394,33 +327,63 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
ContainerPath: "/dev/xvdd",
|
ContainerPath: "/dev/xvdd",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "devices json",
|
name: "docker_logging",
|
||||||
|
config: hclConfigToInterface(t, `
|
||||||
|
config {
|
||||||
|
image = "redis:3.2"
|
||||||
|
network_mode = "host"
|
||||||
|
dns_servers = ["169.254.1.1"]
|
||||||
|
logging {
|
||||||
|
type = "syslog"
|
||||||
|
config {
|
||||||
|
tag = "driver-test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`),
|
||||||
|
spec: dockerDecSpec,
|
||||||
|
expected: &docker.TaskConfig{
|
||||||
|
Image: "redis:3.2",
|
||||||
|
NetworkMode: "host",
|
||||||
|
DNSServers: []string{"169.254.1.1"},
|
||||||
|
Logging: docker.DockerLogging{
|
||||||
|
Type: "syslog",
|
||||||
|
Config: map[string]string{
|
||||||
|
"tag": "driver-test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Devices: []docker.DockerDevice{},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
|
},
|
||||||
|
expectedType: &docker.TaskConfig{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "docker_json",
|
||||||
config: jsonConfigToInterface(t, `
|
config: jsonConfigToInterface(t, `
|
||||||
{
|
{
|
||||||
"Config": {
|
"Config": {
|
||||||
"image": "redis:3.2",
|
"image": "redis:3.2",
|
||||||
"devices": [
|
"devices": [
|
||||||
{
|
{
|
||||||
"host_path": "/dev/sda1",
|
"host_path": "/dev/sda1",
|
||||||
"container_path": "/dev/xvdc",
|
"container_path": "/dev/xvdc",
|
||||||
"cgroup_permissions": "r"
|
"cgroup_permissions": "r"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"host_path": "/dev/sda2",
|
"host_path": "/dev/sda2",
|
||||||
"container_path": "/dev/xvdd"
|
"container_path": "/dev/xvdd"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`),
|
}`),
|
||||||
spec: dockerSpec,
|
spec: dockerDecSpec,
|
||||||
ctx: defaultCtx,
|
expected: &docker.TaskConfig{
|
||||||
expected: &dockerConfig{
|
|
||||||
Image: "redis:3.2",
|
Image: "redis:3.2",
|
||||||
Devices: []DockerDevice{
|
Devices: []docker.DockerDevice{
|
||||||
{
|
{
|
||||||
HostPath: "/dev/sda1",
|
HostPath: "/dev/sda1",
|
||||||
ContainerPath: "/dev/xvdc",
|
ContainerPath: "/dev/xvdc",
|
||||||
|
@ -431,16 +394,18 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
ContainerPath: "/dev/xvdd",
|
ContainerPath: "/dev/xvdd",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Mounts: []docker.DockerMount{},
|
||||||
},
|
},
|
||||||
expectedType: &dockerConfig{},
|
expectedType: &docker.TaskConfig{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
|
c := c
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
t.Logf("Val: % #v", pretty.Formatter(c.config))
|
t.Logf("Val: % #v", pretty.Formatter(c.config))
|
||||||
// Parse the interface
|
// Parse the interface
|
||||||
ctyValue, diag := ParseHclInterface(c.config, c.spec, c.ctx)
|
ctyValue, diag := hclutils.ParseHclInterface(c.config, c.spec, c.vars)
|
||||||
if diag.HasErrors() {
|
if diag.HasErrors() {
|
||||||
for _, err := range diag.Errs() {
|
for _, err := range diag.Errs() {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -448,8 +413,12 @@ func TestParseHclInterface_Hcl(t *testing.T) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert cty-value to go structs
|
// Test encoding
|
||||||
require.NoError(t, gocty.FromCtyValue(ctyValue, c.expectedType))
|
taskConfig := &drivers.TaskConfig{}
|
||||||
|
require.NoError(t, taskConfig.EncodeDriverConfig(ctyValue))
|
||||||
|
|
||||||
|
// Test decoding
|
||||||
|
require.NoError(t, taskConfig.DecodeDriverConfig(c.expectedType))
|
||||||
|
|
||||||
require.EqualValues(t, c.expected, c.expectedType)
|
require.EqualValues(t, c.expected, c.expectedType)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
version "github.com/hashicorp/go-version"
|
version "github.com/hashicorp/go-version"
|
||||||
hcl2 "github.com/hashicorp/hcl2/hcl"
|
|
||||||
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
|
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
|
||||||
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
|
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
|
||||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||||
|
@ -18,14 +17,6 @@ import (
|
||||||
"github.com/zclconf/go-cty/cty/msgpack"
|
"github.com/zclconf/go-cty/cty/msgpack"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// configParseCtx is the context used to parse a plugin's configuration
|
|
||||||
// stanza
|
|
||||||
configParseCtx = &hcl2.EvalContext{
|
|
||||||
Functions: hclutils.GetStdlibFuncs(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// validateConfig returns whether or not the configuration is valid
|
// validateConfig returns whether or not the configuration is valid
|
||||||
func validateConfig(config *PluginLoaderConfig) error {
|
func validateConfig(config *PluginLoaderConfig) error {
|
||||||
var mErr multierror.Error
|
var mErr multierror.Error
|
||||||
|
@ -466,7 +457,7 @@ func (l *PluginLoader) validatePluginConfig(id PluginID, info *pluginInfo) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the config using the spec
|
// Parse the config using the spec
|
||||||
val, diag := hclutils.ParseHclInterface(info.config, spec, configParseCtx)
|
val, diag := hclutils.ParseHclInterface(info.config, spec, nil)
|
||||||
if diag.HasErrors() {
|
if diag.HasErrors() {
|
||||||
multierror.Append(&mErr, diag.Errs()...)
|
multierror.Append(&mErr, diag.Errs()...)
|
||||||
return multierror.Prefix(&mErr, "failed parsing config:")
|
return multierror.Prefix(&mErr, "failed parsing config:")
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
"github.com/hashicorp/hcl/hcl/ast"
|
||||||
hcl2 "github.com/hashicorp/hcl2/hcl"
|
|
||||||
"github.com/hashicorp/hcl2/hcldec"
|
"github.com/hashicorp/hcl2/hcldec"
|
||||||
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
|
"github.com/hashicorp/nomad/helper/pluginutils/hclspecutils"
|
||||||
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
|
"github.com/hashicorp/nomad/helper/pluginutils/hclutils"
|
||||||
|
@ -197,11 +196,7 @@ func (c *Device) setConfig(spec hcldec.Spec, apiVersion string, config []byte, n
|
||||||
|
|
||||||
c.logger.Trace("raw hcl config", "config", hclog.Fmt("% #v", pretty.Formatter(configVal)))
|
c.logger.Trace("raw hcl config", "config", hclog.Fmt("% #v", pretty.Formatter(configVal)))
|
||||||
|
|
||||||
ctx := &hcl2.EvalContext{
|
val, diag := hclutils.ParseHclInterface(configVal, spec, nil)
|
||||||
Functions: hclutils.GetStdlibFuncs(),
|
|
||||||
}
|
|
||||||
|
|
||||||
val, diag := hclutils.ParseHclInterface(configVal, spec, ctx)
|
|
||||||
if diag.HasErrors() {
|
if diag.HasErrors() {
|
||||||
errStr := "failed to parse config"
|
errStr := "failed to parse config"
|
||||||
for _, err := range diag.Errs() {
|
for _, err := range diag.Errs() {
|
||||||
|
|
Loading…
Reference in New Issue