Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add dispatch idempotency token support in the CLI #10930

Merged
merged 5 commits into from
Oct 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/10930.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
cli: Add `-idempotency-token` option for the `nomad job dispatch` command
```
31 changes: 16 additions & 15 deletions api/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -813,21 +813,22 @@ type Job struct {

/* Fields set by server, not sourced from job config file */

Stop *bool
ParentID *string
Dispatched bool
Payload []byte
ConsulNamespace *string `mapstructure:"consul_namespace"`
VaultNamespace *string `mapstructure:"vault_namespace"`
NomadTokenID *string `mapstructure:"nomad_token_id"`
Status *string
StatusDescription *string
Stable *bool
Version *uint64
SubmitTime *int64
CreateIndex *uint64
ModifyIndex *uint64
JobModifyIndex *uint64
Stop *bool
ParentID *string
Dispatched bool
DispatchIdempotencyToken *string
Payload []byte
ConsulNamespace *string `mapstructure:"consul_namespace"`
VaultNamespace *string `mapstructure:"vault_namespace"`
NomadTokenID *string `mapstructure:"nomad_token_id"`
Status *string
StatusDescription *string
Stable *bool
Version *uint64
SubmitTime *int64
CreateIndex *uint64
ModifyIndex *uint64
JobModifyIndex *uint64
}

// IsPeriodic returns whether a job is periodic.
Expand Down
23 changes: 19 additions & 4 deletions command/job_dispatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"strings"

"github.com/hashicorp/nomad/api"
flaghelper "github.com/hashicorp/nomad/helper/flags"
"github.com/posener/complete"
)
Expand All @@ -23,6 +24,10 @@ Usage: nomad job dispatch [options] <parameterized job> [input source]
path to a file. Metadata can be supplied by using the meta flag one or more
times.

An optional idempotency token can be used to prevent more than one instance
of the job to be dispatched. If an instance with the same token already
exists, the command returns without any action.

Upon successful creation, the dispatched job ID will be printed and the
triggered evaluation will be monitored. This can be disabled by supplying the
detach flag.
Expand All @@ -48,6 +53,10 @@ Dispatch Options:
the evaluation ID will be printed to the screen, which can be used to
examine the evaluation using the eval-status command.

-idempotency-token
Optional identifier used to prevent more than one instance of the job from
being dispatched.

-verbose
Display full information.
`
Expand All @@ -61,9 +70,10 @@ func (c *JobDispatchCommand) Synopsis() string {
func (c *JobDispatchCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-meta": complete.PredictAnything,
"-detach": complete.PredictNothing,
"-verbose": complete.PredictNothing,
"-meta": complete.PredictAnything,
"-detach": complete.PredictNothing,
"-idempotency-token": complete.PredictAnything,
"-verbose": complete.PredictNothing,
})
}

Expand Down Expand Up @@ -95,12 +105,14 @@ func (c *JobDispatchCommand) Name() string { return "job dispatch" }

func (c *JobDispatchCommand) Run(args []string) int {
var detach, verbose bool
var idempotencyToken string
var meta []string

flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detach, "detach", false, "")
flags.BoolVar(&verbose, "verbose", false, "")
flags.StringVar(&idempotencyToken, "idempotency-token", "", "")
flags.Var((*flaghelper.StringFlag)(&meta), "meta", "")

if err := flags.Parse(args); err != nil {
Expand Down Expand Up @@ -159,7 +171,10 @@ func (c *JobDispatchCommand) Run(args []string) int {
}

// Dispatch the job
resp, _, err := client.Jobs().Dispatch(job, metaMap, payload, nil)
w := &api.WriteOptions{
IdempotencyToken: idempotencyToken,
}
resp, _, err := client.Jobs().Dispatch(job, metaMap, payload, w)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to dispatch job: %s", err))
return 1
Expand Down
4 changes: 4 additions & 0 deletions command/job_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ func (c *JobStatusCommand) Run(args []string) int {
fmt.Sprintf("Parameterized|%v", parameterized),
}

if job.DispatchIdempotencyToken != nil && *job.DispatchIdempotencyToken != "" {
basic = append(basic, fmt.Sprintf("Idempotency Token|%v", *job.DispatchIdempotencyToken))
}

if periodic && !parameterized {
if *job.Stop {
basic = append(basic, "Next Periodic Launch|none (job stopped)")
Expand Down
4 changes: 4 additions & 0 deletions website/content/api-docs/jobs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,10 @@ The table below shows this endpoint's support for
- `:job_id` `(string: <required>)` - Specifies the ID of the job (as specified
in the job file during submission). This is specified as part of the path.

- `idempotency_token` `(string: "")` - Optional identifier used to prevent more
than one instance of the job from being dispatched. This is specified as a
URL query parameter.

- `Payload` `(string: "")` - Specifies a base64 encoded string containing the
payload. This is limited to 16384 bytes (16KiB).

Expand Down
29 changes: 29 additions & 0 deletions website/content/docs/commands/job/dispatch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ flag one or more times.

The payload has a **size limit of 16384 bytes (16KiB)**.

An optional idempotency token can be specified to prevent dispatching more than
one instance of the same job. The token can have any value and will be matched
with existing jobs. If an instance with the same token already exists, the job
will not be dispatched.

Upon successful creation, the dispatched job ID will be printed and the
triggered evaluation will be monitored. This can be disabled by supplying the
detach flag.
Expand Down Expand Up @@ -58,6 +63,9 @@ capability for the job's namespace.
will be output, which can be used to examine the evaluation using the
[eval status] command

- `-idempotency-token`: Optional identifier used to prevent more than one
instance of the job from being dispatched.

- `-verbose`: Show full information.

## Examples
Expand Down Expand Up @@ -109,5 +117,26 @@ Dispatched Job ID = example/dispatch-1485380684-c37b3dba
Evaluation ID = d9034c4e
```

Dispatch with an idempotency token for the first time:

```shell-session
$ nomad job dispatch -idempotency-token=prod video-encode video-config.json
Dispatched Job ID = video-encode/dispatch-1485379325-cb38d00d
Evaluation ID = 31199841

==> Monitoring evaluation "31199841"
Evaluation triggered by job "example/dispatch-1485379325-cb38d00d"
Allocation "8254b85f" created: node "82ff9c50", group "cache"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "31199841" finished with status "complete"
```

Dispatch with the same idempotency token:

```shell-session
$ nomad job dispatch -idempotency-token=prod video-encode video-config.json
Job "video-encode/dispatch-1485379325-cb38d00d" already dispatched with idempotency token "prod".
```

[eval status]: /docs/commands/eval-status
[parameterized job]: /docs/job-specification/parameterized 'Nomad parameterized Job Specification'