diff --git a/client/agent_endpoint.go b/client/agent_endpoint.go index 856b2787d..5840217ee 100644 --- a/client/agent_endpoint.go +++ b/client/agent_endpoint.go @@ -8,14 +8,17 @@ import ( "time" "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/nomad/command/agent/host" "github.com/hashicorp/nomad/command/agent/monitor" "github.com/hashicorp/nomad/command/agent/pprof" "github.com/hashicorp/nomad/helper" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" metrics "github.com/armon/go-metrics" log "github.com/hashicorp/go-hclog" + sframer "github.com/hashicorp/nomad/client/lib/streamframer" cstructs "github.com/hashicorp/nomad/client/structs" ) @@ -121,7 +124,7 @@ func (a *Agent) monitor(conn io.ReadWriteCloser) { frames := make(chan *sframer.StreamFrame, streamFramesBuffer) errCh := make(chan error) var buf bytes.Buffer - frameCodec := codec.NewEncoder(&buf, structs.JsonHandle) + frameCodec := codec.NewEncoder(&buf, handlers.JsonHandle) framer := sframer.NewStreamFramer(frames, 1*time.Second, 200*time.Millisecond, 1024) framer.Run() diff --git a/client/alloc_endpoint.go b/client/alloc_endpoint.go index 9d7d8c7a5..d9944fb2e 100644 --- a/client/alloc_endpoint.go +++ b/client/alloc_endpoint.go @@ -10,10 +10,12 @@ import ( metrics "github.com/armon/go-metrics" "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/nomad/acl" cstructs "github.com/hashicorp/nomad/client/structs" "github.com/hashicorp/nomad/helper" "github.com/hashicorp/nomad/helper/uuid" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" nstructs "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/plugins/drivers" @@ -279,7 +281,7 @@ func newExecStream(decoder *codec.Decoder, encoder *codec.Encoder) drivers.ExecT buf: buf, encoder: encoder, - frameCodec: codec.NewEncoder(buf, structs.JsonHandle), + frameCodec: codec.NewEncoder(buf, handlers.JsonHandle), } } diff --git a/client/fs_endpoint.go b/client/fs_endpoint.go index d16b05bd0..1ceae2480 100644 --- a/client/fs_endpoint.go +++ b/client/fs_endpoint.go @@ -17,13 +17,15 @@ import ( metrics "github.com/armon/go-metrics" "github.com/hashicorp/go-msgpack/codec" + "github.com/hpcloud/tail/watch" + "github.com/hashicorp/nomad/acl" "github.com/hashicorp/nomad/client/allocdir" sframer "github.com/hashicorp/nomad/client/lib/streamframer" cstructs "github.com/hashicorp/nomad/client/structs" "github.com/hashicorp/nomad/helper" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" - "github.com/hpcloud/tail/watch" ) var ( @@ -237,7 +239,7 @@ func (f *FileSystem) stream(conn io.ReadWriteCloser) { frames := make(chan *sframer.StreamFrame, streamFramesBuffer) errCh := make(chan error) var buf bytes.Buffer - frameCodec := codec.NewEncoder(&buf, structs.JsonHandle) + frameCodec := codec.NewEncoder(&buf, handlers.JsonHandle) // Create the framer framer := sframer.NewStreamFramer(frames, streamHeartbeatRate, streamBatchWindow, streamFrameSize) @@ -468,7 +470,7 @@ func (f *FileSystem) logs(conn io.ReadWriteCloser) { var streamErr error buf := new(bytes.Buffer) - frameCodec := codec.NewEncoder(buf, structs.JsonHandle) + frameCodec := codec.NewEncoder(buf, handlers.JsonHandle) OUTER: for { select { diff --git a/command/agent/http.go b/command/agent/http.go index 320a4518a..d937dd2f3 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/nomad/helper/noxssrw" "github.com/hashicorp/nomad/helper/tlsutil" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" ) @@ -495,13 +496,13 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque if obj != nil { var buf bytes.Buffer if prettyPrint { - enc := codec.NewEncoder(&buf, structs.JsonHandlePretty) + enc := codec.NewEncoder(&buf, handlers.JsonHandlePretty) err = enc.Encode(obj) if err == nil { buf.Write([]byte("\n")) } } else { - enc := codec.NewEncoder(&buf, structs.JsonHandleWithExtensions) + enc := codec.NewEncoder(&buf, handlers.JsonHandleWithExtensions) err = enc.Encode(obj) } if err != nil { diff --git a/helper/pluginutils/hclutils/testing.go b/helper/pluginutils/hclutils/testing.go index 469cec7d5..50f2ca0e2 100644 --- a/helper/pluginutils/hclutils/testing.go +++ b/helper/pluginutils/hclutils/testing.go @@ -6,13 +6,14 @@ import ( "github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/hcl" "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/nomad/helper/pluginutils/hclspecutils" - "github.com/hashicorp/nomad/nomad/structs" - "github.com/hashicorp/nomad/plugins/drivers" - "github.com/hashicorp/nomad/plugins/shared/hclspec" "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/require" "github.com/zclconf/go-cty/cty" + + "github.com/hashicorp/nomad/helper/pluginutils/hclspecutils" + "github.com/hashicorp/nomad/nomad/json/handlers" + "github.com/hashicorp/nomad/plugins/drivers" + "github.com/hashicorp/nomad/plugins/shared/hclspec" ) type HCLParser struct { @@ -121,7 +122,7 @@ func JsonConfigToInterface(t *testing.T, config string) interface{} { t.Helper() // Decode from json - dec := codec.NewDecoderBytes([]byte(config), structs.JsonHandle) + dec := codec.NewDecoderBytes([]byte(config), handlers.JsonHandle) var m map[string]interface{} err := dec.Decode(&m) diff --git a/helper/pluginutils/hclutils/util.go b/helper/pluginutils/hclutils/util.go index 6042e7b0f..460ab875b 100644 --- a/helper/pluginutils/hclutils/util.go +++ b/helper/pluginutils/hclutils/util.go @@ -9,7 +9,9 @@ import ( hcl "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hcldec" hjson "github.com/hashicorp/hcl/v2/json" - "github.com/hashicorp/nomad/nomad/structs" + + "github.com/hashicorp/nomad/nomad/json/handlers" + "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/function" "github.com/zclconf/go-cty/cty/function/stdlib" @@ -26,7 +28,7 @@ func ParseHclInterface(val interface{}, spec hcldec.Spec, vars map[string]cty.Va // Encode to json var buf bytes.Buffer - enc := codec.NewEncoder(&buf, structs.JsonHandle) + enc := codec.NewEncoder(&buf, handlers.JsonHandle) err := enc.Encode(val) if err != nil { // Convert to a hcl diagnostics message diff --git a/nomad/client_agent_endpoint.go b/nomad/client_agent_endpoint.go index 488478034..7e381f0d1 100644 --- a/nomad/client_agent_endpoint.go +++ b/nomad/client_agent_endpoint.go @@ -10,12 +10,14 @@ import ( "time" log "github.com/hashicorp/go-hclog" + sframer "github.com/hashicorp/nomad/client/lib/streamframer" cstructs "github.com/hashicorp/nomad/client/structs" "github.com/hashicorp/nomad/command/agent/host" "github.com/hashicorp/nomad/command/agent/monitor" "github.com/hashicorp/nomad/command/agent/pprof" "github.com/hashicorp/nomad/helper" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/go-msgpack/codec" @@ -185,7 +187,7 @@ func (a *Agent) monitor(conn io.ReadWriteCloser) { frames := make(chan *sframer.StreamFrame, 32) errCh := make(chan error) var buf bytes.Buffer - frameCodec := codec.NewEncoder(&buf, structs.JsonHandle) + frameCodec := codec.NewEncoder(&buf, handlers.JsonHandle) framer := sframer.NewStreamFramer(frames, 1*time.Second, 200*time.Millisecond, 1024) framer.Run() diff --git a/nomad/structs/json_encoding.go b/nomad/json/encoding.go similarity index 65% rename from nomad/structs/json_encoding.go rename to nomad/json/encoding.go index 2a2ccaa66..e5ff82d91 100644 --- a/nomad/structs/json_encoding.go +++ b/nomad/json/encoding.go @@ -1,4 +1,4 @@ -package structs +package json import ( "reflect" @@ -6,27 +6,6 @@ import ( "github.com/hashicorp/go-msgpack/codec" ) -func init() { - registerExtension(reflect.TypeOf(Node{}), nodeExt) -} - -func nodeExt(v interface{}) interface{} { - node := v.(*Node) - if node == nil { - return nil - } - type NodeAlias Node - return &struct { - *NodeAlias - Drain bool - }{ - NodeAlias: (*NodeAlias)(node), - Drain: node.DrainStrategy != nil, - } -} - -// BOILERPLATE GOES HERE - type extendFunc func(interface{}) interface{} var ( @@ -44,7 +23,8 @@ func (n nomadJsonEncodingExtensions) ConvertExt(v interface{}) interface{} { if fn, ok := extendedTypes[reflect.TypeOf(v)]; ok { return fn(v) } else { - return nil + // shouldn't get here + return v } } @@ -52,7 +32,7 @@ func (n nomadJsonEncodingExtensions) ConvertExt(v interface{}) interface{} { func (n nomadJsonEncodingExtensions) UpdateExt(_ interface{}, _ interface{}) {} func NomadJsonEncodingExtensions(h *codec.JsonHandle) *codec.JsonHandle { - for tpe, _ := range extendedTypes { + for tpe := range extendedTypes { h.SetInterfaceExt(tpe, 1, nomadJsonEncodingExtensions{}) } return h diff --git a/nomad/json/extensions.go b/nomad/json/extensions.go new file mode 100644 index 000000000..2246c1c01 --- /dev/null +++ b/nomad/json/extensions.go @@ -0,0 +1,28 @@ +package json + +import ( + "reflect" + + "github.com/hashicorp/nomad/nomad/structs" +) + +func init() { + // TODO: this could be simplified by looking up the base type in the case of a pointer type + registerExtension(reflect.TypeOf(structs.Node{}), nodeExt) + registerExtension(reflect.TypeOf(&structs.Node{}), nodeExt) +} + +func nodeExt(v interface{}) interface{} { + node := v.(*structs.Node) + if node == nil { + return nil + } + type NodeAlias structs.Node + return &struct { + *NodeAlias + Drain bool + }{ + NodeAlias: (*NodeAlias)(node), + Drain: node.DrainStrategy != nil, + } +} diff --git a/nomad/json/handlers/handlers.go b/nomad/json/handlers/handlers.go new file mode 100644 index 000000000..5ec676eb7 --- /dev/null +++ b/nomad/json/handlers/handlers.go @@ -0,0 +1,24 @@ +package handlers + +import ( + "github.com/hashicorp/go-msgpack/codec" + + "github.com/hashicorp/nomad/nomad/json" +) + +var ( + // JsonHandle and JsonHandlePretty are the codec handles to JSON encode + // structs. The pretty handle will add indents for easier human consumption. + // JsonHandleWithExtensions and JsonHandlePretty include extensions for + // encoding structs objects with API-specific fields + JsonHandle = &codec.JsonHandle{ + HTMLCharsAsIs: true, + } + JsonHandleWithExtensions = json.NomadJsonEncodingExtensions(&codec.JsonHandle{ + HTMLCharsAsIs: true, + }) + JsonHandlePretty = json.NomadJsonEncodingExtensions(&codec.JsonHandle{ + HTMLCharsAsIs: true, + Indent: 4, + }) +) diff --git a/nomad/stream/ndjson.go b/nomad/stream/ndjson.go index ec69a6c1c..9c9ee11be 100644 --- a/nomad/stream/ndjson.go +++ b/nomad/stream/ndjson.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/go-msgpack/codec" + "github.com/hashicorp/nomad/nomad/json/handlers" "github.com/hashicorp/nomad/nomad/structs" ) @@ -74,7 +75,7 @@ func (n *JsonStream) Send(v interface{}) error { } var buf bytes.Buffer - enc := codec.NewEncoder(&buf, structs.JsonHandleWithExtensions) + enc := codec.NewEncoder(&buf, handlers.JsonHandleWithExtensions) err := enc.Encode(v) if err != nil { return fmt.Errorf("error marshaling json for stream: %w", err) diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 222c7b86a..6a1d6028d 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -10581,23 +10581,6 @@ var MsgpackHandle = func() *codec.MsgpackHandle { return h }() -var ( - // JsonHandle and JsonHandlePretty are the codec handles to JSON encode - // structs. The pretty handle will add indents for easier human consumption. - // JsonHandleWithExtensions and JsonHandlePretty include extensions for - // encoding structs objects with API-specific fields - JsonHandle = &codec.JsonHandle{ - HTMLCharsAsIs: true, - } - JsonHandleWithExtensions = NomadJsonEncodingExtensions(&codec.JsonHandle{ - HTMLCharsAsIs: true, - }) - JsonHandlePretty = NomadJsonEncodingExtensions(&codec.JsonHandle{ - HTMLCharsAsIs: true, - Indent: 4, - }) -) - // Decode is used to decode a MsgPack encoded object func Decode(buf []byte, out interface{}) error { return codec.NewDecoder(bytes.NewReader(buf), MsgpackHandle).Decode(out)