From bfc766357e84967c21c1f09121186e139186eb09 Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Tue, 10 Aug 2021 17:06:40 -0400 Subject: [PATCH] deployments: canary=0 is implicitly autopromote (#11013) In a multi-task-group job, treat 0 canary groups as auto-promote. This change fixes an edge case where Nomad requires a manual promotion, if the job had any group with canary=0 and rest of groups having auto_promote set. Co-authored-by: Michael Schurter --- .changelog/11013.txt | 4 ++++ nomad/structs/structs.go | 15 ++++++++++----- nomad/structs/structs_test.go | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 .changelog/11013.txt diff --git a/.changelog/11013.txt b/.changelog/11013.txt new file mode 100644 index 000000000..0dadfa14e --- /dev/null +++ b/.changelog/11013.txt @@ -0,0 +1,4 @@ + +```release-note:bug +deployments: Fixed a bug where multi-group deployments don't get auto-promoted when one group has no canaries. +``` diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 71793496c..13f2125ee 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -4302,19 +4302,24 @@ func (j *Job) Warnings() error { var mErr multierror.Error // Check the groups - ap := 0 + hasAutoPromote, allAutoPromote := false, true + for _, tg := range j.TaskGroups { if err := tg.Warnings(j); err != nil { outer := fmt.Errorf("Group %q has warnings: %v", tg.Name, err) mErr.Errors = append(mErr.Errors, outer) } - if tg.Update != nil && tg.Update.AutoPromote { - ap += 1 + + if u := tg.Update; u != nil { + hasAutoPromote = hasAutoPromote || u.AutoPromote + + // Having no canaries implies auto-promotion since there are no canaries to promote. + allAutoPromote = allAutoPromote && (u.Canary == 0 || u.AutoPromote) } } // Check AutoPromote, should be all or none - if ap > 0 && ap < len(j.TaskGroups) { + if hasAutoPromote && !allAutoPromote { err := fmt.Errorf("auto_promote must be true for all groups to enable automatic promotion") mErr.Errors = append(mErr.Errors, err) } @@ -8877,7 +8882,7 @@ func (d *Deployment) HasAutoPromote() bool { return false } for _, group := range d.TaskGroups { - if !group.AutoPromote { + if group.DesiredCanaries > 0 && !group.AutoPromote { return false } } diff --git a/nomad/structs/structs_test.go b/nomad/structs/structs_test.go index 5d19f8b01..2409f7021 100644 --- a/nomad/structs/structs_test.go +++ b/nomad/structs/structs_test.go @@ -200,6 +200,27 @@ func TestJob_Warnings(t *testing.T) { { Update: &UpdateStrategy{ AutoPromote: false, + Canary: 1, + }, + }, + }, + }, + }, + { + Name: "no error for mixed but implied AutoPromote", + Expected: []string{}, + Job: &Job{ + Type: JobTypeService, + TaskGroups: []*TaskGroup{ + { + Update: &UpdateStrategy{ + AutoPromote: true, + }, + }, + { + Update: &UpdateStrategy{ + AutoPromote: false, + Canary: 0, }, }, },