Merge pull request #5297 from hashicorp/b-docker-logging

Docker: Fix logging config parsing
This commit is contained in:
Michael Schurter 2019-02-11 06:57:52 -08:00 committed by GitHub
commit 3b84e08fa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 180 additions and 216 deletions

View File

@ -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()...)
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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),
})), })),

View File

@ -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

View File

@ -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)

View File

@ -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:")

View File

@ -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() {