From a707c83a074747211c09b4f5ea90295c0c4a0500 Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 2 Dec 2019 14:43:19 +0000 Subject: [PATCH 1/4] Use deployment watcher if there's a deploy ID Previously levant would check the template contained an update stanza at the job level, before watching for a service job deployment to complete. With this change, we'll always wait for a deployment to complete. This allows the Nomad server to be the one to determine if the template has a "deployment" rather than levant. --- levant/deploy.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/levant/deploy.go b/levant/deploy.go index 01b0c33eb..a0c983c6d 100644 --- a/levant/deploy.go +++ b/levant/deploy.go @@ -155,16 +155,7 @@ func (l *levantDeployment) deploy() (success bool) { switch *l.config.Template.Job.Type { case nomad.JobTypeService: - - // If the service job doesn't have an update stanza, the job will not use - // Nomad deployments. - if l.config.Template.Job.Update == nil { - log.Info().Msg("levant/deploy: job is not configured with update stanza, consider adding to use deployments") - return l.jobStatusChecker(&eval.EvalID) - } - log.Info().Msgf("levant/deploy: beginning deployment watcher for job") - // Get the deploymentID from the evaluationID so that we can watch the // deployment for end status. depID, err := l.getDeploymentID(eval.EvalID) @@ -173,6 +164,7 @@ func (l *levantDeployment) deploy() (success bool) { return } + log.Info().Msgf("levant/deploy: watching deployment %s for job", depID) // Get the success of the deployment and return if we have success. if success = l.deploymentWatcher(depID); success { return From 21eb9c4f14923f0422c91a103aa38698c457c14e Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Fri, 29 Jan 2021 03:09:48 +0000 Subject: [PATCH 2/4] Retain default behaviour if deployID is empty --- levant/deploy.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/levant/deploy.go b/levant/deploy.go index a0c983c6d..21ff3d740 100644 --- a/levant/deploy.go +++ b/levant/deploy.go @@ -164,6 +164,11 @@ func (l *levantDeployment) deploy() (success bool) { return } + if depID == "" { + log.Info().Msgf("levant/deploy: no deploy ID found for evaluation %s", eval.EvalID) + return l.jobStatusChecker(&eval.EvalID) + } + log.Info().Msgf("levant/deploy: watching deployment %s for job", depID) // Get the success of the deployment and return if we have success. if success = l.deploymentWatcher(depID); success { From 95ec8569d51c41a9a4bbe4846981f1f69339ce0e Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Fri, 23 Apr 2021 00:48:02 +0100 Subject: [PATCH 3/4] Fix panic when a job without update stanza fails deployment Currently levant panics if there's a failed deployment for a job without an update stanza. --- levant/deploy.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/levant/deploy.go b/levant/deploy.go index 21ff3d740..b59cd3331 100644 --- a/levant/deploy.go +++ b/levant/deploy.go @@ -181,15 +181,17 @@ func (l *levantDeployment) deploy() (success bool) { return } - // If the job is not a canary job, then run the auto-revert checker, the - // current checking mechanism is slightly hacky and should be updated. - // The reason for this is currently the config.Job is populate from the - // rendered job and so a user could potentially not set canary meaning - // the field shows a null. - if l.config.Template.Job.Update.Canary == nil { - l.checkAutoRevert(dep) - } else if *l.config.Template.Job.Update.Canary == 0 { - l.checkAutoRevert(dep) + if l.config.Template.Job.Update != nil { + // If the job is not a canary job, then run the auto-revert checker, the + // current checking mechanism is slightly hacky and should be updated. + // The reason for this is currently the config.Job is populates from the + // rendered job and so a user could potentially not set canary meaning + // the field shows a null. + if l.config.Template.Job.Update.Canary == nil { + l.checkAutoRevert(dep) + } else if *l.config.Template.Job.Update.Canary == 0 { + l.checkAutoRevert(dep) + } } case nomad.JobTypeBatch: From e04dd53745e4bd3aaa8f6e3e9bda669480b0ae0c Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Fri, 23 Apr 2021 01:15:22 +0100 Subject: [PATCH 4/4] Add test --- test/deploy_test.go | 15 +++++ .../fixtures/deploy_fail_with_no_update.nomad | 58 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 test/fixtures/deploy_fail_with_no_update.nomad diff --git a/test/deploy_test.go b/test/deploy_test.go index f30e0e499..e2f031f4c 100644 --- a/test/deploy_test.go +++ b/test/deploy_test.go @@ -135,6 +135,21 @@ func TestDeploy_canary(t *testing.T) { }) } +func TestDeploy_failed_deploy_with_no_update(t *testing.T) { + acctest.Test(t, acctest.TestCase{ + Steps: []acctest.TestStep{ + { + Runner: acctest.DeployTestStepRunner{ + FixtureName: "deploy_fail_with_no_update.nomad", + }, + ExpectErr: true, + Check: acctest.CheckDeploymentStatus("failed"), + }, + }, + CleanupFunc: acctest.CleanupPurgeJob, + }) +} + func TestDeploy_lifecycle(t *testing.T) { acctest.Test(t, acctest.TestCase{ Steps: []acctest.TestStep{ diff --git a/test/fixtures/deploy_fail_with_no_update.nomad b/test/fixtures/deploy_fail_with_no_update.nomad new file mode 100644 index 000000000..6b4a01a33 --- /dev/null +++ b/test/fixtures/deploy_fail_with_no_update.nomad @@ -0,0 +1,58 @@ +job "[[.job_name]]" { + datacenters = ["dc1"] + type = "service" + + group "test" { + count = 1 + + restart { + attempts = 1 + interval = "5s" + delay = "1s" + mode = "fail" + } + + ephemeral_disk { + size = 300 + } + + update { + max_parallel = 1 + min_healthy_time = "10s" + healthy_deadline = "1m" + } + + network { + port "http" { + to = 80 + } + } + + service { + name = "fake-service" + port = "http" + + check { + name = "alive" + type = "tcp" + interval = "10s" + timeout = "2s" + } + } + + task "alpine" { + driver = "docker" + config { + image = "alpine" + command = "sleep 1 && exit 1" + } + resources { + cpu = 100 + memory = 20 + network { + mbits = 10 + } + } + } + } +}