Skip to content

Commit

Permalink
Add -ignore-no-changes to change no changes on plan exit code.
Browse files Browse the repository at this point in the history
Previously if no changes were detected on a deployment Levant
would exit with status 1 which caused some CI/CD pipeline issues.

This change allows users to change this behaviouer using the flag
whereby if no changes are detected, Levant will exit with a status
code 0.

Closes #186
  • Loading branch information
jrasell committed Jun 27, 2018
1 parent 9012dba commit e1fdaad
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 21 deletions.
19 changes: 13 additions & 6 deletions command/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ func (c *DeployCommand) Help() string {
helpText := `
Usage: levant deploy [options] [TEMPLATE]
Deploy a Nomad job based on input templates and variable files. The deploy
command supports passing variables individually on the command line. Multiple
commands can be passed in the format of -var 'key=value'. Variables passed
via the command line take precedence over the same variable declared within
a passed variable file.
Deploy a Nomad job based on input templates and variable files. The deploy
command supports passing variables individually on the command line. Multiple
commands can be passed in the format of -var 'key=value'. Variables passed
via the command line take precedence over the same variable declared within
a passed variable file.
Arguments:
Expand Down Expand Up @@ -57,6 +57,12 @@ General Options:
Use the taskgroup count from the Nomad jobfile instead of the count that
is currently set in a running job.
-ignore-no-changes
By default if no changes are detected when running a deployment Levant will
exit with a status 1 to indicate a deployment didn't happen. This behaviour
can be changed using this flag so that Levant will exit cleanly ensuring CD
pipelines don't fail when no changes are detected.
-log-level=<level>
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
INFO, and WARN, in decreasing order of verbosity. The default is INFO.
Expand All @@ -68,7 +74,7 @@ General Options:
-var-file=<file>
Used in conjunction with the -job-file will deploy a templated job to your
Nomad cluster. You can repeat this flag multiple times to supply multiple var-files.
[default: levant.(yaml|yml|tf)]
[default: levant.(yaml|yml|tf)]
`
return strings.TrimSpace(helpText)
}
Expand All @@ -93,6 +99,7 @@ func (c *DeployCommand) Run(args []string) int {
flags.StringVar(&addr, "consul-address", "", "")
flags.BoolVar(&config.ForceBatch, "force-batch", false, "")
flags.BoolVar(&config.ForceCount, "force-count", false, "")
flags.BoolVar(&config.IgnoreNoChanges, "ignore-no-changes", false, "")
flags.StringVar(&config.LogLevel, "log-level", "INFO", "")
flags.StringVar(&config.LogFormat, "log-format", "HUMAN", "")
flags.Var((*helper.FlagStringSlice)(&config.VariableFiles), "var-file", "")
Expand Down
32 changes: 22 additions & 10 deletions levant/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,27 @@ func TriggerDeployment(config *structs.Config, nomadClient *nomad.Client) bool {
return false
}

preDep := levantDep.preDeploy()
if !preDep {
log.Error().Msg("levant/deploy: pre-deployment process failed")
// Run the job validation steps and count updater.
preDepVal := levantDep.preDeployValidate()
if !preDepVal {
log.Error().Msg("levant/deploy: pre-deployment validation process failed")
return false
}

// Run the plan functionality and return if an error occurred during the run.
// This would have already been logged, so its just used to control the flow
// and pass the correct signal up the stack.
c, err := levantDep.plan()
if err != nil {
return false
}

// If no changes were detected, see whether the user wants to exit cleanly
// or wants to exit 1 if no changes were detected. GH-186.
if !c {
if levantDep.config.IgnoreNoChanges {
return true
}
return false
}

Expand All @@ -71,7 +89,7 @@ func TriggerDeployment(config *structs.Config, nomadClient *nomad.Client) bool {
return true
}

func (l *levantDeployment) preDeploy() (success bool) {
func (l *levantDeployment) preDeployValidate() (success bool) {

// Validate the job to check it is syntactically correct.
if _, _, err := l.nomad.Jobs().Validate(l.config.Job, nil); err != nil {
Expand All @@ -92,12 +110,6 @@ func (l *levantDeployment) preDeploy() (success bool) {
}
}

// Trigger a Nomad plan and Levants functionality to log all planned changes
// upon job registration.
if !l.plan() {
return
}

return true
}

Expand Down
10 changes: 5 additions & 5 deletions levant/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ var (
// plan is the entry point into running the Levant plan function which logs all
// changes anticipated by Nomad of the upcoming job registration. If there are
// no planned changes here, return false to indicate we should stop the process.
func (l *levantDeployment) plan() bool {
func (l *levantDeployment) plan() (bool, error) {

log.Debug().Msg("levant/plan: triggering Nomad plan")

// Run a plan using the rendered job.
resp, _, err := l.nomad.Jobs().Plan(l.config.Job, true, nil)
if err != nil {
log.Error().Err(err).Msg("levant/plan: unable to run a job plan")
return false
return false, err
}

switch resp.Diff.Type {
Expand All @@ -34,21 +34,21 @@ func (l *levantDeployment) plan() bool {
// is a new registration.
case diffTypeAdded:
log.Info().Msg("levant/plan: job is a new addition to the cluster")
return true
return true, nil

// If there are no changes, then log an error so the user can see this and
// exit the deployment.
case diffTypeNone:
log.Error().Msg("levant/plan: no changes detected for job")
return false
return false, nil

// If there are changes, run the planDiff function which is responsible for
// iterating through the plan and logging all the planned changes.
case diffTypeEdited:
planDiff(resp.Diff)
}

return true
return true, nil
}

func planDiff(plan *nomad.JobDiff) {
Expand Down
4 changes: 4 additions & 0 deletions levant/structs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type Config struct {
// and force the count based on the rendered job file.
ForceCount bool

// IgnoreNoChanges is used to allow operators to force Levant to exit cleanly
// even if there are no changes found during the plan.
IgnoreNoChanges bool

// Job represents the Nomad Job definition that will be deployed.
Job *nomad.Job

Expand Down

0 comments on commit e1fdaad

Please sign in to comment.