diff --git a/CHANGELOG.md b/CHANGELOG.md index 14046b8f..b43e2b3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -## 1.5.0 (Unreleased) +## 1.4.4 (Unreleased) + +IMPROVEMENTS: + +* **Target Nomad 0.10.3**: updated the nomad client to support Nomad API version 0.10.3 ([#96](https://github.com/terraform-providers/terraform-provider-nomad/issues/96)) + ## 1.4.3 (February 07, 2020) IMPROVEMENTS: @@ -13,7 +18,7 @@ BUG FIXES: IMPROVEMENTS: -* **Target Nomad 0.10.0**: updated the noomad client to support Nomad API version 0.10.0 ([#77](https://github.com/terraform-providers/terraform-provider-nomad/issues/77)) +* **Target Nomad 0.10.0**: updated the nomad client to support Nomad API version 0.10.0 ([#77](https://github.com/terraform-providers/terraform-provider-nomad/issues/77)) BUG FIXES: diff --git a/go.mod b/go.mod index cb926f60..69b874cb 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,10 @@ exclude ( require ( github.com/google/go-cmp v0.3.0 - github.com/gorilla/websocket v1.4.1 // indirect github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-version v1.2.0 github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f - github.com/hashicorp/nomad/api v0.0.0-20191010200500-0e6af1085602 + github.com/hashicorp/nomad/api v0.0.0-20200129172448-74e08d5af489 github.com/hashicorp/terraform-plugin-sdk v1.0.0 github.com/hashicorp/vault v0.10.4 github.com/mitchellh/mapstructure v1.1.2 diff --git a/go.sum b/go.sum index fa79f02a..5c4ad80a 100644 --- a/go.sum +++ b/go.sum @@ -113,12 +113,8 @@ github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 h1:2yzhWGdgQUWZUCNK+ github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/nomad/api v0.0.0-20190906191921-82f214630cd6 h1:kiTndH1QxgBybn2s/sHk75LDre3hjZ8Ihrb8ycM+9PM= -github.com/hashicorp/nomad/api v0.0.0-20190906191921-82f214630cd6/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= -github.com/hashicorp/nomad/api v0.0.0-20191007164342-7b08e19f7268 h1:vqGLw5utD6HsEvEd1vqTZ6nMZHjdc8suiuc5/76GTSo= -github.com/hashicorp/nomad/api v0.0.0-20191007164342-7b08e19f7268/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= -github.com/hashicorp/nomad/api v0.0.0-20191010200500-0e6af1085602 h1:rpJ6qZg+bTbf29ME0azxxW1zUZKq+Wh8hukVLlH5Bmw= -github.com/hashicorp/nomad/api v0.0.0-20191010200500-0e6af1085602/go.mod h1:BDngVi1f4UA6aJq9WYTgxhfWSE1+42xshvstLU2fRGk= +github.com/hashicorp/nomad/api v0.0.0-20200129172448-74e08d5af489 h1:MCZpZRk0tN0ezSBjwtVzYZwOz2KBmNONI1rHz6XE39E= +github.com/hashicorp/nomad/api v0.0.0-20200129172448-74e08d5af489/go.mod h1:Kbx02dGxN6wnAHhSbTqeg/sdACnMMD20BFkVuAxJzds= github.com/hashicorp/terraform-config-inspect v0.0.0-20190821133035-82a99dc22ef4 h1:fTkL0YwjohGyN7AqsDhz6bwcGBpT+xBqi3Qhpw58Juw= github.com/hashicorp/terraform-config-inspect v0.0.0-20190821133035-82a99dc22ef4/go.mod h1:JDmizlhaP5P0rYTTZB0reDMefAiJyfWPEtugV4in1oI= github.com/hashicorp/terraform-plugin-sdk v1.0.0 h1:3AjuuV1LJKs1NlG+heUgqWN6/QCSx2kDhyS6K7F0fTw= diff --git a/nomad/core/jobspec/parse.go b/nomad/core/jobspec/parse.go index 7bdfd05e..fd73571a 100644 --- a/nomad/core/jobspec/parse.go +++ b/nomad/core/jobspec/parse.go @@ -138,6 +138,7 @@ func parseConstraints(result *[]*api.Constraint, list *ast.ObjectList) error { "set_contains", "value", "version", + "semver", } if err := helper.CheckHCLKeys(o.Val, valid); err != nil { return err @@ -159,6 +160,13 @@ func parseConstraints(result *[]*api.Constraint, list *ast.ObjectList) error { m["RTarget"] = constraint } + // If "semver" is provided, set the operand + // to "semver" and the value to the "RTarget" + if constraint, ok := m[api.ConstraintSemver]; ok { + m["Operand"] = api.ConstraintSemver + m["RTarget"] = constraint + } + // If "regexp" is provided, set the operand // to "regexp" and the value to the "RTarget" if constraint, ok := m[api.ConstraintRegex]; ok { @@ -219,6 +227,7 @@ func parseAffinities(result *[]*api.Affinity, list *ast.ObjectList) error { "set_contains_all", "value", "version", + "semver", "weight", } if err := helper.CheckHCLKeys(o.Val, valid); err != nil { @@ -241,6 +250,13 @@ func parseAffinities(result *[]*api.Affinity, list *ast.ObjectList) error { m["RTarget"] = affinity } + // If "semver" is provided, set the operand + // to "semver" and the value to the "RTarget" + if affinity, ok := m[api.ConstraintSemver]; ok { + m["Operand"] = api.ConstraintSemver + m["RTarget"] = affinity + } + // If "regexp" is provided, set the operand // to "regexp" and the value to the "RTarget" if affinity, ok := m[api.ConstraintRegex]; ok { diff --git a/nomad/core/jobspec/parse_group.go b/nomad/core/jobspec/parse_group.go index 99d9111c..f7966bae 100644 --- a/nomad/core/jobspec/parse_group.go +++ b/nomad/core/jobspec/parse_group.go @@ -114,7 +114,7 @@ func parseGroups(result *api.Job, list *ast.ObjectList) error { // Parse network if o := listVal.Filter("network"); len(o.Items) > 0 { - networks, err := parseNetwork(o) + networks, err := ParseNetwork(o) if err != nil { return err } diff --git a/nomad/core/jobspec/parse_network.go b/nomad/core/jobspec/parse_network.go index 3b0ea70f..3d0a8e52 100644 --- a/nomad/core/jobspec/parse_network.go +++ b/nomad/core/jobspec/parse_network.go @@ -12,7 +12,8 @@ import ( "github.com/terraform-providers/terraform-provider-nomad/nomad/core/helper" ) -func parseNetwork(o *ast.ObjectList) (*api.NetworkResource, error) { +// ParseNetwork parses a collection containing exactly one NetworkResource +func ParseNetwork(o *ast.ObjectList) (*api.NetworkResource, error) { if len(o.Items) > 1 { return nil, fmt.Errorf("only one 'network' resource allowed") } diff --git a/nomad/core/jobspec/parse_service.go b/nomad/core/jobspec/parse_service.go index 60a614b3..f91fe615 100644 --- a/nomad/core/jobspec/parse_service.go +++ b/nomad/core/jobspec/parse_service.go @@ -193,6 +193,7 @@ func parseSidecarService(o *ast.ObjectItem) (*api.ConsulSidecarService, error) { valid := []string{ "port", "proxy", + "tags", } if err := helper.CheckHCLKeys(o.Val, valid); err != nil { @@ -216,7 +217,7 @@ func parseSidecarService(o *ast.ObjectItem) (*api.ConsulSidecarService, error) { return nil, err } if err := dec.Decode(m); err != nil { - return nil, fmt.Errorf("foo: %v", err) + return nil, fmt.Errorf("sidecar_service: %v", err) } var proxyList *ast.ObjectList diff --git a/nomad/core/jobspec/parse_task.go b/nomad/core/jobspec/parse_task.go index 305151c0..5436de06 100644 --- a/nomad/core/jobspec/parse_task.go +++ b/nomad/core/jobspec/parse_task.go @@ -440,7 +440,7 @@ func parseResources(result *api.Resources, list *ast.ObjectList) error { // Parse the network resources if o := listVal.Filter("network"); len(o.Items) > 0 { - r, err := parseNetwork(o) + r, err := ParseNetwork(o) if err != nil { return fmt.Errorf("resource, %v", err) } @@ -522,6 +522,7 @@ func parseVolumeMounts(out *[]*api.VolumeMount, list *ast.ObjectList) error { "volume", "read_only", "destination", + "propagation_mode", } if err := helper.CheckHCLKeys(item.Val, valid); err != nil { return err diff --git a/nomad/resource_job_test.go b/nomad/resource_job_test.go index 0060d6a3..f6aa4d92 100644 --- a/nomad/resource_job_test.go +++ b/nomad/resource_job_test.go @@ -1397,6 +1397,7 @@ resource "nomad_job" "test" { volume = "data" destination = "/var/lib/data" read_only = true + propagation_mode = "private" } } } @@ -1430,6 +1431,7 @@ resource "nomad_job" "test" { local_bind_port = 8080 } } + tags = ["bar", "foo"] } } } diff --git a/vendor/github.com/hashicorp/nomad/api/agent.go b/vendor/github.com/hashicorp/nomad/api/agent.go index 46979403..d372b806 100644 --- a/vendor/github.com/hashicorp/nomad/api/agent.go +++ b/vendor/github.com/hashicorp/nomad/api/agent.go @@ -237,6 +237,57 @@ func (a *Agent) Health() (*AgentHealthResponse, error) { return nil, fmt.Errorf("unable to unmarshal response with status %d: %v", resp.StatusCode, err) } +// Monitor returns a channel which will receive streaming logs from the agent +// Providing a non-nil stopCh can be used to close the connection and stop log streaming +func (a *Agent) Monitor(stopCh <-chan struct{}, q *QueryOptions) (<-chan *StreamFrame, <-chan error) { + errCh := make(chan error, 1) + r, err := a.client.newRequest("GET", "/v1/agent/monitor") + if err != nil { + errCh <- err + return nil, errCh + } + + r.setQueryOptions(q) + _, resp, err := requireOK(a.client.doRequest(r)) + if err != nil { + errCh <- err + return nil, errCh + } + + frames := make(chan *StreamFrame, 10) + go func() { + defer resp.Body.Close() + + dec := json.NewDecoder(resp.Body) + + for { + select { + case <-stopCh: + close(frames) + return + default: + } + + // Decode the next frame + var frame StreamFrame + if err := dec.Decode(&frame); err != nil { + close(frames) + errCh <- err + return + } + + // Discard heartbeat frame + if frame.IsHeartbeat() { + continue + } + + frames <- &frame + } + }() + + return frames, errCh +} + // joinResponse is used to decode the response we get while // sending a member join request. type joinResponse struct { diff --git a/vendor/github.com/hashicorp/nomad/api/allocations.go b/vendor/github.com/hashicorp/nomad/api/allocations.go index 3a22af78..05892a77 100644 --- a/vendor/github.com/hashicorp/nomad/api/allocations.go +++ b/vendor/github.com/hashicorp/nomad/api/allocations.go @@ -210,12 +210,7 @@ func (a *Allocations) Exec(ctx context.Context, func (a *Allocations) execFrames(ctx context.Context, alloc *Allocation, task string, tty bool, command []string, errCh chan<- error, q *QueryOptions) (sendFn func(*ExecStreamingInput) error, output <-chan *ExecStreamingOutput) { - - nodeClient, err := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) - if err != nil { - errCh <- err - return nil, nil - } + nodeClient, _ := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) if q == nil { q = &QueryOptions{} @@ -236,15 +231,17 @@ func (a *Allocations) execFrames(ctx context.Context, alloc *Allocation, task st reqPath := fmt.Sprintf("/v1/client/allocation/%s/exec", alloc.ID) - conn, _, err := nodeClient.websocket(reqPath, q) - if err != nil { - // There was an error talking directly to the client. Non-network - // errors are fatal, but network errors can attempt to route via RPC. - if _, ok := err.(net.Error); !ok { + var conn *websocket.Conn + + if nodeClient != nil { + conn, _, err = nodeClient.websocket(reqPath, q) + if _, ok := err.(net.Error); err != nil && !ok { errCh <- err return nil, nil } + } + if conn == nil { conn, _, err = a.client.websocket(reqPath, q) if err != nil { errCh <- err diff --git a/vendor/github.com/hashicorp/nomad/api/api.go b/vendor/github.com/hashicorp/nomad/api/api.go index bacb7c3c..1ee9f19d 100644 --- a/vendor/github.com/hashicorp/nomad/api/api.go +++ b/vendor/github.com/hashicorp/nomad/api/api.go @@ -257,6 +257,9 @@ func DefaultConfig() *Config { if v := os.Getenv("NOMAD_CLIENT_KEY"); v != "" { config.TLSConfig.ClientKey = v } + if v := os.Getenv("NOMAD_TLS_SERVER_NAME"); v != "" { + config.TLSConfig.TLSServerName = v + } if v := os.Getenv("NOMAD_SKIP_VERIFY"); v != "" { if insecure, err := strconv.ParseBool(v); err == nil { config.TLSConfig.Insecure = insecure @@ -592,10 +595,11 @@ func (c *Client) newRequest(method, path string) (*request, error) { config: &c.config, method: method, url: &url.URL{ - Scheme: base.Scheme, - User: base.User, - Host: base.Host, - Path: u.Path, + Scheme: base.Scheme, + User: base.User, + Host: base.Host, + Path: u.Path, + RawPath: u.RawPath, }, params: make(map[string][]string), } @@ -741,7 +745,16 @@ func (c *Client) websocket(endpoint string, q *QueryOptions) (*websocket.Conn, * // check resp status code, as it's more informative than handshake error we get from ws library if resp != nil && resp.StatusCode != 101 { var buf bytes.Buffer - io.Copy(&buf, resp.Body) + + if resp.Header.Get("Content-Encoding") == "gzip" { + greader, err := gzip.NewReader(resp.Body) + if err != nil { + return nil, nil, fmt.Errorf("Unexpected response code: %d", resp.StatusCode) + } + io.Copy(&buf, greader) + } else { + io.Copy(&buf, resp.Body) + } resp.Body.Close() return nil, nil, fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) diff --git a/vendor/github.com/hashicorp/nomad/api/constraint.go b/vendor/github.com/hashicorp/nomad/api/constraint.go index 7b18ade9..3233a3bf 100644 --- a/vendor/github.com/hashicorp/nomad/api/constraint.go +++ b/vendor/github.com/hashicorp/nomad/api/constraint.go @@ -5,6 +5,7 @@ const ( ConstraintDistinctHosts = "distinct_hosts" ConstraintRegex = "regexp" ConstraintVersion = "version" + ConstraintSemver = "semver" ConstraintSetContains = "set_contains" ConstraintSetContainsAll = "set_contains_all" ConstraintSetContainsAny = "set_contains_any" diff --git a/vendor/github.com/hashicorp/nomad/api/fs.go b/vendor/github.com/hashicorp/nomad/api/fs.go index b769236f..e5340c96 100644 --- a/vendor/github.com/hashicorp/nomad/api/fs.go +++ b/vendor/github.com/hashicorp/nomad/api/fs.go @@ -92,72 +92,24 @@ func (a *AllocFS) Stat(alloc *Allocation, path string, q *QueryOptions) (*AllocF // ReadAt is used to read bytes at a given offset until limit at the given path // in an allocation directory. If limit is <= 0, there is no limit. func (a *AllocFS) ReadAt(alloc *Allocation, path string, offset int64, limit int64, q *QueryOptions) (io.ReadCloser, error) { - nodeClient, err := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) - if err != nil { - return nil, err - } - - if q == nil { - q = &QueryOptions{} - } - if q.Params == nil { - q.Params = make(map[string]string) - } - - q.Params["path"] = path - q.Params["offset"] = strconv.FormatInt(offset, 10) - q.Params["limit"] = strconv.FormatInt(limit, 10) - reqPath := fmt.Sprintf("/v1/client/fs/readat/%s", alloc.ID) - r, err := nodeClient.rawQuery(reqPath, q) - if err != nil { - // There was a networking error when talking directly to the client. - if _, ok := err.(net.Error); !ok { - return nil, err - } - // Try via the server - r, err = a.client.rawQuery(reqPath, q) - if err != nil { - return nil, err - } - } - - return r, nil + return queryClientNode(a.client, alloc, reqPath, q, + func(q *QueryOptions) { + q.Params["path"] = path + q.Params["offset"] = strconv.FormatInt(offset, 10) + q.Params["limit"] = strconv.FormatInt(limit, 10) + }) } // Cat is used to read contents of a file at the given path in an allocation // directory func (a *AllocFS) Cat(alloc *Allocation, path string, q *QueryOptions) (io.ReadCloser, error) { - nodeClient, err := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) - if err != nil { - return nil, err - } - - if q == nil { - q = &QueryOptions{} - } - if q.Params == nil { - q.Params = make(map[string]string) - } - - q.Params["path"] = path reqPath := fmt.Sprintf("/v1/client/fs/cat/%s", alloc.ID) - r, err := nodeClient.rawQuery(reqPath, q) - if err != nil { - // There was a networking error when talking directly to the client. - if _, ok := err.(net.Error); !ok { - return nil, err - } - - // Try via the server - r, err = a.client.rawQuery(reqPath, q) - if err != nil { - return nil, err - } - } - - return r, nil + return queryClientNode(a.client, alloc, reqPath, q, + func(q *QueryOptions) { + q.Params["path"] = path + }) } // Stream streams the content of a file blocking on EOF. @@ -172,38 +124,17 @@ func (a *AllocFS) Stream(alloc *Allocation, path, origin string, offset int64, cancel <-chan struct{}, q *QueryOptions) (<-chan *StreamFrame, <-chan error) { errCh := make(chan error, 1) - nodeClient, err := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) - if err != nil { - errCh <- err - return nil, errCh - } - - if q == nil { - q = &QueryOptions{} - } - if q.Params == nil { - q.Params = make(map[string]string) - } - - q.Params["path"] = path - q.Params["offset"] = strconv.FormatInt(offset, 10) - q.Params["origin"] = origin reqPath := fmt.Sprintf("/v1/client/fs/stream/%s", alloc.ID) - r, err := nodeClient.rawQuery(reqPath, q) + r, err := queryClientNode(a.client, alloc, reqPath, q, + func(q *QueryOptions) { + q.Params["path"] = path + q.Params["offset"] = strconv.FormatInt(offset, 10) + q.Params["origin"] = origin + }) if err != nil { - // There was a networking error when talking directly to the client. - if _, ok := err.(net.Error); !ok { - errCh <- err - return nil, errCh - } - - // Try via the server - r, err = a.client.rawQuery(reqPath, q) - if err != nil { - errCh <- err - return nil, errCh - } + errCh <- err + return nil, errCh } // Create the output channel @@ -244,6 +175,40 @@ func (a *AllocFS) Stream(alloc *Allocation, path, origin string, offset int64, return frames, errCh } +func queryClientNode(c *Client, alloc *Allocation, reqPath string, q *QueryOptions, customizeQ func(*QueryOptions)) (io.ReadCloser, error) { + nodeClient, _ := c.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) + + if q == nil { + q = &QueryOptions{} + } + if q.Params == nil { + q.Params = make(map[string]string) + } + if customizeQ != nil { + customizeQ(q) + } + + var r io.ReadCloser + var err error + + if nodeClient != nil { + r, err = nodeClient.rawQuery(reqPath, q) + if _, ok := err.(net.Error); err != nil && !ok { + // found a non networking error talking to client directly + return nil, err + } + + } + + // failed to query node, access through server directly + // or network error when talking to the client directly + if r == nil { + return c.rawQuery(reqPath, q) + } + + return r, err +} + // Logs streams the content of a tasks logs blocking on EOF. // The parameters are: // * allocation: the allocation to stream from. @@ -264,42 +229,20 @@ func (a *AllocFS) Logs(alloc *Allocation, follow bool, task, logType, origin str errCh := make(chan error, 1) - nodeClient, err := a.client.GetNodeClientWithTimeout(alloc.NodeID, ClientConnTimeout, q) + reqPath := fmt.Sprintf("/v1/client/fs/logs/%s", alloc.ID) + r, err := queryClientNode(a.client, alloc, reqPath, q, + func(q *QueryOptions) { + q.Params["follow"] = strconv.FormatBool(follow) + q.Params["task"] = task + q.Params["type"] = logType + q.Params["origin"] = origin + q.Params["offset"] = strconv.FormatInt(offset, 10) + }) if err != nil { errCh <- err return nil, errCh } - if q == nil { - q = &QueryOptions{} - } - if q.Params == nil { - q.Params = make(map[string]string) - } - - q.Params["follow"] = strconv.FormatBool(follow) - q.Params["task"] = task - q.Params["type"] = logType - q.Params["origin"] = origin - q.Params["offset"] = strconv.FormatInt(offset, 10) - - reqPath := fmt.Sprintf("/v1/client/fs/logs/%s", alloc.ID) - r, err := nodeClient.rawQuery(reqPath, q) - if err != nil { - // There was a networking error when talking directly to the client. - if _, ok := err.(net.Error); !ok { - errCh <- err - return nil, errCh - } - - // Try via the server - r, err = a.client.rawQuery(reqPath, q) - if err != nil { - errCh <- err - return nil, errCh - } - } - // Create the output channel frames := make(chan *StreamFrame, 10) diff --git a/vendor/github.com/hashicorp/nomad/api/go.mod b/vendor/github.com/hashicorp/nomad/api/go.mod index dd8d5f43..8e89f7f5 100644 --- a/vendor/github.com/hashicorp/nomad/api/go.mod +++ b/vendor/github.com/hashicorp/nomad/api/go.mod @@ -5,9 +5,9 @@ go 1.12 require ( github.com/docker/go-units v0.3.3 github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 + github.com/gorilla/websocket v1.4.1 github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/go-rootcerts v1.0.0 - github.com/hashicorp/go-uuid v1.0.1 github.com/kr/pretty v0.1.0 github.com/mitchellh/go-testing-interface v1.0.0 github.com/stretchr/testify v1.3.0 diff --git a/vendor/github.com/hashicorp/nomad/api/go.sum b/vendor/github.com/hashicorp/nomad/api/go.sum index c7297afe..bf994bbd 100644 --- a/vendor/github.com/hashicorp/nomad/api/go.sum +++ b/vendor/github.com/hashicorp/nomad/api/go.sum @@ -4,12 +4,12 @@ github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/vendor/github.com/hashicorp/nomad/api/jobs.go b/vendor/github.com/hashicorp/nomad/api/jobs.go index b240b394..e1270914 100644 --- a/vendor/github.com/hashicorp/nomad/api/jobs.go +++ b/vendor/github.com/hashicorp/nomad/api/jobs.go @@ -146,7 +146,7 @@ func (j *Jobs) PrefixList(prefix string) ([]*JobListStub, *QueryMeta, error) { // job given its unique ID. func (j *Jobs) Info(jobID string, q *QueryOptions) (*Job, *QueryMeta, error) { var resp Job - qm, err := j.client.query("/v1/job/"+jobID, &resp, q) + qm, err := j.client.query("/v1/job/"+url.PathEscape(jobID), &resp, q) if err != nil { return nil, nil, err } @@ -157,7 +157,7 @@ func (j *Jobs) Info(jobID string, q *QueryOptions) (*Job, *QueryMeta, error) { // unique ID. func (j *Jobs) Versions(jobID string, diffs bool, q *QueryOptions) ([]*Job, []*JobDiff, *QueryMeta, error) { var resp JobVersionsResponse - qm, err := j.client.query(fmt.Sprintf("/v1/job/%s/versions?diffs=%v", jobID, diffs), &resp, q) + qm, err := j.client.query(fmt.Sprintf("/v1/job/%s/versions?diffs=%v", url.PathEscape(jobID), diffs), &resp, q) if err != nil { return nil, nil, nil, err } @@ -167,7 +167,7 @@ func (j *Jobs) Versions(jobID string, diffs bool, q *QueryOptions) ([]*Job, []*J // Allocations is used to return the allocs for a given job ID. func (j *Jobs) Allocations(jobID string, allAllocs bool, q *QueryOptions) ([]*AllocationListStub, *QueryMeta, error) { var resp []*AllocationListStub - u, err := url.Parse("/v1/job/" + jobID + "/allocations") + u, err := url.Parse("/v1/job/" + url.PathEscape(jobID) + "/allocations") if err != nil { return nil, nil, err } @@ -188,7 +188,7 @@ func (j *Jobs) Allocations(jobID string, allAllocs bool, q *QueryOptions) ([]*Al // ID. func (j *Jobs) Deployments(jobID string, all bool, q *QueryOptions) ([]*Deployment, *QueryMeta, error) { var resp []*Deployment - u, err := url.Parse("/v1/job/" + jobID + "/deployments") + u, err := url.Parse("/v1/job/" + url.PathEscape(jobID) + "/deployments") if err != nil { return nil, nil, err } @@ -208,7 +208,7 @@ func (j *Jobs) Deployments(jobID string, all bool, q *QueryOptions) ([]*Deployme // the given job ID. func (j *Jobs) LatestDeployment(jobID string, q *QueryOptions) (*Deployment, *QueryMeta, error) { var resp *Deployment - qm, err := j.client.query("/v1/job/"+jobID+"/deployment", &resp, q) + qm, err := j.client.query("/v1/job/"+url.PathEscape(jobID)+"/deployment", &resp, q) if err != nil { return nil, nil, err } @@ -219,7 +219,7 @@ func (j *Jobs) LatestDeployment(jobID string, q *QueryOptions) (*Deployment, *Qu // ID. func (j *Jobs) Evaluations(jobID string, q *QueryOptions) ([]*Evaluation, *QueryMeta, error) { var resp []*Evaluation - qm, err := j.client.query("/v1/job/"+jobID+"/evaluations", &resp, q) + qm, err := j.client.query("/v1/job/"+url.PathEscape(jobID)+"/evaluations", &resp, q) if err != nil { return nil, nil, err } @@ -232,7 +232,7 @@ func (j *Jobs) Evaluations(jobID string, q *QueryOptions) ([]*Evaluation, *Query // eventually GC'ed from the system. Most callers should not specify purge. func (j *Jobs) Deregister(jobID string, purge bool, q *WriteOptions) (string, *WriteMeta, error) { var resp JobDeregisterResponse - wm, err := j.client.delete(fmt.Sprintf("/v1/job/%v?purge=%t", jobID, purge), &resp, q) + wm, err := j.client.delete(fmt.Sprintf("/v1/job/%v?purge=%t", url.PathEscape(jobID), purge), &resp, q) if err != nil { return "", nil, err } @@ -242,7 +242,7 @@ func (j *Jobs) Deregister(jobID string, purge bool, q *WriteOptions) (string, *W // ForceEvaluate is used to force-evaluate an existing job. func (j *Jobs) ForceEvaluate(jobID string, q *WriteOptions) (string, *WriteMeta, error) { var resp JobRegisterResponse - wm, err := j.client.write("/v1/job/"+jobID+"/evaluate", nil, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/evaluate", nil, &resp, q) if err != nil { return "", nil, err } @@ -258,7 +258,7 @@ func (j *Jobs) EvaluateWithOpts(jobID string, opts EvalOptions, q *WriteOptions) } var resp JobRegisterResponse - wm, err := j.client.write("/v1/job/"+jobID+"/evaluate", req, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/evaluate", req, &resp, q) if err != nil { return "", nil, err } @@ -268,7 +268,7 @@ func (j *Jobs) EvaluateWithOpts(jobID string, opts EvalOptions, q *WriteOptions) // PeriodicForce spawns a new instance of the periodic job and returns the eval ID func (j *Jobs) PeriodicForce(jobID string, q *WriteOptions) (string, *WriteMeta, error) { var resp periodicForceResponse - wm, err := j.client.write("/v1/job/"+jobID+"/periodic/force", nil, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/periodic/force", nil, &resp, q) if err != nil { return "", nil, err } @@ -301,7 +301,7 @@ func (j *Jobs) PlanOpts(job *Job, opts *PlanOptions, q *WriteOptions) (*JobPlanR } var resp JobPlanResponse - wm, err := j.client.write("/v1/job/"+*job.ID+"/plan", req, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(*job.ID)+"/plan", req, &resp, q) if err != nil { return nil, nil, err } @@ -310,7 +310,7 @@ func (j *Jobs) PlanOpts(job *Job, opts *PlanOptions, q *WriteOptions) (*JobPlanR func (j *Jobs) Summary(jobID string, q *QueryOptions) (*JobSummary, *QueryMeta, error) { var resp JobSummary - qm, err := j.client.query("/v1/job/"+jobID+"/summary", &resp, q) + qm, err := j.client.query("/v1/job/"+url.PathEscape(jobID)+"/summary", &resp, q) if err != nil { return nil, nil, err } @@ -325,7 +325,7 @@ func (j *Jobs) Dispatch(jobID string, meta map[string]string, Meta: meta, Payload: payload, } - wm, err := j.client.write("/v1/job/"+jobID+"/dispatch", req, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/dispatch", req, &resp, q) if err != nil { return nil, nil, err } @@ -345,7 +345,7 @@ func (j *Jobs) Revert(jobID string, version uint64, enforcePriorVersion *uint64, EnforcePriorVersion: enforcePriorVersion, VaultToken: vaultToken, } - wm, err := j.client.write("/v1/job/"+jobID+"/revert", req, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/revert", req, &resp, q) if err != nil { return nil, nil, err } @@ -362,7 +362,7 @@ func (j *Jobs) Stable(jobID string, version uint64, stable bool, JobVersion: version, Stable: stable, } - wm, err := j.client.write("/v1/job/"+jobID+"/stable", req, &resp, q) + wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/stable", req, &resp, q) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/hashicorp/nomad/api/nodes.go b/vendor/github.com/hashicorp/nomad/api/nodes.go index bf72034f..4a264eb4 100644 --- a/vendor/github.com/hashicorp/nomad/api/nodes.go +++ b/vendor/github.com/hashicorp/nomad/api/nodes.go @@ -126,7 +126,7 @@ func (m *MonitorMessage) String() string { // MonitorDrain emits drain related events on the returned string channel. The // channel will be closed when all allocations on the draining node have -// stopped or the context is canceled. +// stopped, when an error occurs, or if the context is canceled. func (n *Nodes) MonitorDrain(ctx context.Context, nodeID string, index uint64, ignoreSys bool) <-chan *MonitorMessage { outCh := make(chan *MonitorMessage, 8) nodeCh := make(chan *MonitorMessage, 1) @@ -335,7 +335,7 @@ func (n *Nodes) monitorDrainAllocs(ctx context.Context, nodeID string, ignoreSys // Exit if all allocs are terminal if runningAllocs == 0 { - msg := Messagef(MonitorMsgLevelInfo, "All allocations on node %q have stopped.", nodeID) + msg := Messagef(MonitorMsgLevelInfo, "All allocations on node %q have stopped", nodeID) select { case allocCh <- msg: case <-ctx.Done(): @@ -521,6 +521,9 @@ type DrainStrategy struct { // ForceDeadline is the deadline time for the drain after which drains will // be forced ForceDeadline time.Time + + // StartedAt is the time the drain process started + StartedAt time.Time } // DrainSpec describes a Node's drain behavior. diff --git a/vendor/github.com/hashicorp/nomad/api/services.go b/vendor/github.com/hashicorp/nomad/api/services.go index dbe0fcfe..8630126c 100644 --- a/vendor/github.com/hashicorp/nomad/api/services.go +++ b/vendor/github.com/hashicorp/nomad/api/services.go @@ -143,6 +143,7 @@ type ConsulConnect struct { // ConsulSidecarService represents a Consul Connect SidecarService jobspec // stanza. type ConsulSidecarService struct { + Tags []string Port string Proxy *ConsulProxy } diff --git a/vendor/github.com/hashicorp/nomad/api/tasks.go b/vendor/github.com/hashicorp/nomad/api/tasks.go index 9c017887..578188cc 100644 --- a/vendor/github.com/hashicorp/nomad/api/tasks.go +++ b/vendor/github.com/hashicorp/nomad/api/tasks.go @@ -370,12 +370,28 @@ type VolumeRequest struct { ReadOnly bool `mapstructure:"read_only"` } +const ( + VolumeMountPropagationPrivate = "private" + VolumeMountPropagationHostToTask = "host-to-task" + VolumeMountPropagationBidirectional = "bidirectional" +) + // VolumeMount represents the relationship between a destination path in a task // and the task group volume that should be mounted there. type VolumeMount struct { - Volume string - Destination string - ReadOnly bool `mapstructure:"read_only"` + Volume *string + Destination *string + ReadOnly *bool `mapstructure:"read_only"` + PropagationMode *string `mapstructure:"propagation_mode"` +} + +func (vm *VolumeMount) Canonicalize() { + if vm.PropagationMode == nil { + vm.PropagationMode = stringToPtr(VolumeMountPropagationPrivate) + } + if vm.ReadOnly == nil { + vm.ReadOnly = boolToPtr(false) + } } // TaskGroup is the unit of scheduling. @@ -632,6 +648,9 @@ func (t *Task) Canonicalize(tg *TaskGroup, job *Job) { for _, a := range t.Affinities { a.Canonicalize() } + for _, vm := range t.VolumeMounts { + vm.Canonicalize() + } } // TaskArtifact is used to download artifacts before running a task. diff --git a/vendor/modules.txt b/vendor/modules.txt index 015d9fa4..8e4ee1c6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -128,7 +128,7 @@ github.com/hashicorp/hcl2/hclwrite github.com/hashicorp/hil/ast # github.com/hashicorp/logutils v1.0.0 github.com/hashicorp/logutils -# github.com/hashicorp/nomad/api v0.0.0-20191010200500-0e6af1085602 +# github.com/hashicorp/nomad/api v0.0.0-20200129172448-74e08d5af489 github.com/hashicorp/nomad/api github.com/hashicorp/nomad/api/contexts # github.com/hashicorp/terraform-config-inspect v0.0.0-20190821133035-82a99dc22ef4