From 9621c073fe14e89de4078520eda981da2fa9bab6 Mon Sep 17 00:00:00 2001 From: Lang Martin Date: Thu, 9 May 2019 09:42:18 -0400 Subject: [PATCH] add update AutoPromote bool --- api/jobs.go | 9 ++++++ api/tasks_test.go | 1 + command/agent/job_endpoint.go | 1 + command/agent/job_endpoint_test.go | 1 + jobspec/parse.go | 1 + jobspec/parse_test.go | 2 ++ jobspec/test-fixtures/basic.hcl | 2 ++ nomad/deploymentwatcher/deployment_watcher.go | 3 -- .../deployments_watcher_test.go | 2 +- nomad/structs/diff_test.go | 28 +++++++++++++++++++ nomad/structs/structs.go | 10 +++++++ website/source/api/json-jobs.html.md | 4 +++ 12 files changed, 60 insertions(+), 4 deletions(-) diff --git a/api/jobs.go b/api/jobs.go index 973250f30..821d1f1b1 100644 --- a/api/jobs.go +++ b/api/jobs.go @@ -376,6 +376,7 @@ type UpdateStrategy struct { HealthyDeadline *time.Duration `mapstructure:"healthy_deadline"` ProgressDeadline *time.Duration `mapstructure:"progress_deadline"` AutoRevert *bool `mapstructure:"auto_revert"` + AutoPromote *bool `mapstructure:"auto_promote"` Canary *int `mapstructure:"canary"` } @@ -433,6 +434,10 @@ func (u *UpdateStrategy) Copy() *UpdateStrategy { copy.Canary = intToPtr(*u.Canary) } + if u.AutoPromote != nil { + copy.AutoPromote = boolToPtr(*u.AutoPromote) + } + return copy } @@ -472,6 +477,10 @@ func (u *UpdateStrategy) Merge(o *UpdateStrategy) { if o.Canary != nil { u.Canary = intToPtr(*o.Canary) } + + if o.AutoPromote != nil { + u.AutoPromote = boolToPtr(*o.AutoPromote) + } } func (u *UpdateStrategy) Canonicalize() { diff --git a/api/tasks_test.go b/api/tasks_test.go index 8ebea0585..3ee016073 100644 --- a/api/tasks_test.go +++ b/api/tasks_test.go @@ -374,6 +374,7 @@ func TestTaskGroup_Canonicalize_Update(t *testing.T) { ID: stringToPtr("test"), Update: &UpdateStrategy{ AutoRevert: boolToPtr(false), + AutoPromote: boolToPtr(false), Canary: intToPtr(0), HealthCheck: stringToPtr(""), HealthyDeadline: timeToPtr(0), diff --git a/command/agent/job_endpoint.go b/command/agent/job_endpoint.go index c29440234..7057264b1 100644 --- a/command/agent/job_endpoint.go +++ b/command/agent/job_endpoint.go @@ -719,6 +719,7 @@ func ApiTgToStructsTG(taskGroup *api.TaskGroup, tg *structs.TaskGroup) { HealthyDeadline: *taskGroup.Update.HealthyDeadline, ProgressDeadline: *taskGroup.Update.ProgressDeadline, AutoRevert: *taskGroup.Update.AutoRevert, + AutoPromote: *taskGroup.Update.AutoPromote, Canary: *taskGroup.Update.Canary, } } diff --git a/command/agent/job_endpoint_test.go b/command/agent/job_endpoint_test.go index a076a9b9d..aed3894e3 100644 --- a/command/agent/job_endpoint_test.go +++ b/command/agent/job_endpoint_test.go @@ -1624,6 +1624,7 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) { HealthyDeadline: 5 * time.Minute, ProgressDeadline: 5 * time.Minute, AutoRevert: true, + AutoPromote: false, Canary: 1, }, Meta: map[string]string{ diff --git a/jobspec/parse.go b/jobspec/parse.go index 2e281137a..f9d5a3096 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -1602,6 +1602,7 @@ func parseUpdate(result **api.UpdateStrategy, list *ast.ObjectList) error { "healthy_deadline", "progress_deadline", "auto_revert", + "auto_promote", "canary", } if err := helper.CheckHCLKeys(o.Val, valid); err != nil { diff --git a/jobspec/parse_test.go b/jobspec/parse_test.go index 1fc84f0f9..6fa295134 100644 --- a/jobspec/parse_test.go +++ b/jobspec/parse_test.go @@ -79,6 +79,7 @@ func TestParse(t *testing.T) { HealthyDeadline: helper.TimeToPtr(10 * time.Minute), ProgressDeadline: helper.TimeToPtr(10 * time.Minute), AutoRevert: helper.BoolToPtr(true), + AutoPromote: helper.BoolToPtr(true), Canary: helper.IntToPtr(1), }, @@ -163,6 +164,7 @@ func TestParse(t *testing.T) { HealthyDeadline: helper.TimeToPtr(1 * time.Minute), ProgressDeadline: helper.TimeToPtr(1 * time.Minute), AutoRevert: helper.BoolToPtr(false), + AutoPromote: helper.BoolToPtr(false), Canary: helper.IntToPtr(2), }, Migrate: &api.MigrateStrategy{ diff --git a/jobspec/test-fixtures/basic.hcl b/jobspec/test-fixtures/basic.hcl index 5a9184be8..86162cbe2 100644 --- a/jobspec/test-fixtures/basic.hcl +++ b/jobspec/test-fixtures/basic.hcl @@ -42,6 +42,7 @@ job "binstore-storagelocker" { healthy_deadline = "10m" progress_deadline = "10m" auto_revert = true + auto_promote = true canary = 1 } @@ -84,6 +85,7 @@ job "binstore-storagelocker" { healthy_deadline = "1m" progress_deadline = "1m" auto_revert = false + auto_promote = false canary = 2 } diff --git a/nomad/deploymentwatcher/deployment_watcher.go b/nomad/deploymentwatcher/deployment_watcher.go index 1c57edaed..7baa77113 100644 --- a/nomad/deploymentwatcher/deployment_watcher.go +++ b/nomad/deploymentwatcher/deployment_watcher.go @@ -597,9 +597,6 @@ func (w *deploymentWatcher) handleAllocUpdate(allocs []*structs.AllocListStub) ( // We need to create an eval so the job can progress. if alloc.DeploymentStatus.IsHealthy() && alloc.DeploymentStatus.ModifyIndex > latestEval { res.createEval = true - if alloc.DeploymentStatus.IsCanary() { - dstate.HealthyCanaries += 1 - } } // If the group is using a progress deadline, we don't have to do anything. diff --git a/nomad/deploymentwatcher/deployments_watcher_test.go b/nomad/deploymentwatcher/deployments_watcher_test.go index 885c27611..57d59da78 100644 --- a/nomad/deploymentwatcher/deployments_watcher_test.go +++ b/nomad/deploymentwatcher/deployments_watcher_test.go @@ -594,7 +594,7 @@ func TestWatcher_AutoPromoteDeployment(t *testing.T) { func() (bool, error) { ds, _ := m.state.DeploymentsByJobID(ws, j.Namespace, j.ID, true) d = ds[0] - return 2 == d.TaskGroups["web"].HealthyCanaries, nil + return 2 == d.TaskGroups["web"].HealthyAllocs, nil }, func(err error) { require.NoError(t, err) }, ) diff --git a/nomad/structs/diff_test.go b/nomad/structs/diff_test.go index 42321a413..dbdd83c7f 100644 --- a/nomad/structs/diff_test.go +++ b/nomad/structs/diff_test.go @@ -1977,6 +1977,12 @@ func TestTaskGroupDiff(t *testing.T) { Type: DiffTypeDeleted, Name: "Update", Fields: []*FieldDiff{ + { + Type: DiffTypeDeleted, + Name: "AutoPromote", + Old: "false", + New: "", + }, { Type: DiffTypeDeleted, Name: "AutoRevert", @@ -2033,6 +2039,12 @@ func TestTaskGroupDiff(t *testing.T) { Type: DiffTypeAdded, Name: "Update", Fields: []*FieldDiff{ + { + Type: DiffTypeAdded, + Name: "AutoPromote", + Old: "", + New: "false", + }, { Type: DiffTypeAdded, Name: "AutoRevert", @@ -2084,6 +2096,7 @@ func TestTaskGroupDiff(t *testing.T) { HealthyDeadline: 30 * time.Second, ProgressDeadline: 29 * time.Second, AutoRevert: true, + AutoPromote: true, Canary: 2, }, }, @@ -2095,6 +2108,7 @@ func TestTaskGroupDiff(t *testing.T) { HealthyDeadline: 31 * time.Second, ProgressDeadline: 32 * time.Second, AutoRevert: false, + AutoPromote: false, Canary: 1, }, }, @@ -2105,6 +2119,12 @@ func TestTaskGroupDiff(t *testing.T) { Type: DiffTypeEdited, Name: "Update", Fields: []*FieldDiff{ + { + Type: DiffTypeEdited, + Name: "AutoPromote", + Old: "true", + New: "false", + }, { Type: DiffTypeEdited, Name: "AutoRevert", @@ -2163,6 +2183,7 @@ func TestTaskGroupDiff(t *testing.T) { HealthyDeadline: 30 * time.Second, ProgressDeadline: 30 * time.Second, AutoRevert: true, + AutoPromote: true, Canary: 2, }, }, @@ -2174,6 +2195,7 @@ func TestTaskGroupDiff(t *testing.T) { HealthyDeadline: 30 * time.Second, ProgressDeadline: 30 * time.Second, AutoRevert: true, + AutoPromote: true, Canary: 2, }, }, @@ -2184,6 +2206,12 @@ func TestTaskGroupDiff(t *testing.T) { Type: DiffTypeEdited, Name: "Update", Fields: []*FieldDiff{ + { + Type: DiffTypeNone, + Name: "AutoPromote", + Old: "true", + New: "true", + }, { Type: DiffTypeNone, Name: "AutoRevert", diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 33c81dd7e..82e7320dd 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -3804,6 +3804,7 @@ var ( HealthyDeadline: 5 * time.Minute, ProgressDeadline: 10 * time.Minute, AutoRevert: false, + AutoPromote: false, Canary: 0, } ) @@ -3842,6 +3843,10 @@ type UpdateStrategy struct { // stable version. AutoRevert bool + // AutoPromote declares that the deployment should be promoted when all canaries are + // healthy + AutoPromote bool + // Canary is the number of canaries to deploy when a change to the task // group is detected. Canary int @@ -7162,6 +7167,10 @@ type DeploymentState struct { // reverted on failure AutoRevert bool + // AutoPromote marks promotion triggered automatically by healthy canaries + // copied from TaskGroup UpdateStrategy in scheduler.reconcile + AutoPromote bool + // ProgressDeadline is the deadline by which an allocation must transition // to healthy before the deployment is considered failed. ProgressDeadline time.Duration @@ -7202,6 +7211,7 @@ func (d *DeploymentState) GoString() string { base += fmt.Sprintf("\n\tHealthy: %d", d.HealthyAllocs) base += fmt.Sprintf("\n\tUnhealthy: %d", d.UnhealthyAllocs) base += fmt.Sprintf("\n\tAutoRevert: %v", d.AutoRevert) + base += fmt.Sprintf("\n\tAutoPromote: %v", d.AutoPromote) return base } diff --git a/website/source/api/json-jobs.html.md b/website/source/api/json-jobs.html.md index b0a26fcaf..2b6f2fb54 100644 --- a/website/source/api/json-jobs.html.md +++ b/website/source/api/json-jobs.html.md @@ -691,6 +691,9 @@ determined. The potential values are: they can be promoted which unblocks a rolling update of the remaining allocations at a rate of `max_parallel`. +- `AutoPromote` - Specifies if the job should automatically promote to + the new deployment if all canaries become healthy. + - `Stagger` - Specifies the delay between migrating allocations off nodes marked for draining. @@ -704,6 +707,7 @@ An example `Update` block: "MinHealthyTime": 15000000000, "HealthyDeadline": 180000000000, "AutoRevert": false, + "AutoPromote": false, "Canary": 1 } }