diff --git a/command/scale_in.go b/command/scale_in.go index 1d5fa920..095cd04f 100644 --- a/command/scale_in.go +++ b/command/scale_in.go @@ -26,6 +26,9 @@ General Options: -address= The Nomad HTTP API address including port which Levant will use to make calls. + + -allow-stale + Allow stale consistency mode for requests into nomad. -log-level= Specify the verbosity level of Levant's logs. Valid values include DEBUG, @@ -64,18 +67,23 @@ func (c *ScaleInCommand) Run(args []string) int { var err error var logL, logF string - config := &structs.ScalingConfig{} - config.Direction = structs.ScalingDirectionIn + config := &scale.Config{ + Client: &structs.ClientConfig{}, + Scale: &structs.ScaleConfig{ + Direction: structs.ScalingDirectionIn, + }, + } flags := c.Meta.FlagSet("scale-in", FlagSetVars) flags.Usage = func() { c.UI.Output(c.Help()) } - flags.StringVar(&config.Addr, "address", "", "") + flags.StringVar(&config.Client.Addr, "address", "", "") + flags.BoolVar(&config.Client.AllowStale, "allow-stale", false, "") flags.StringVar(&logL, "log-level", "INFO", "") flags.StringVar(&logF, "log-format", "HUMAN", "") - flags.IntVar(&config.Count, "count", 0, "") - flags.IntVar(&config.Percent, "percent", 0, "") - flags.StringVar(&config.TaskGroup, "task-group", "", "") + flags.IntVar(&config.Scale.Count, "count", 0, "") + flags.IntVar(&config.Scale.Percent, "percent", 0, "") + flags.StringVar(&config.Scale.TaskGroup, "task-group", "", "") if err = flags.Parse(args); err != nil { return 1 @@ -88,20 +96,19 @@ func (c *ScaleInCommand) Run(args []string) int { return 1 } - config.JobID = args[0] + config.Scale.JobID = args[0] - if config.Count == 0 && config.Percent == 0 || config.Count > 0 && config.Percent > 0 || - config.Count < 0 || config.Percent < 0 { - c.UI.Error("You must set either -count or -percent flag to scale-in") + if config.Scale.Count == 0 && config.Scale.Percent == 0 || config.Scale.Count > 0 && config.Scale.Percent > 0 { + c.UI.Error("You must set either -count or -percent flag to scale-out") return 1 } - if config.Count > 0 { - config.DirectionType = structs.ScalingDirectionTypeCount + if config.Scale.Count > 0 { + config.Scale.DirectionType = structs.ScalingDirectionTypeCount } - if config.Percent > 0 { - config.DirectionType = structs.ScalingDirectionTypePercent + if config.Scale.Percent > 0 { + config.Scale.DirectionType = structs.ScalingDirectionTypePercent } if err = logging.SetupLogger(logL, logF); err != nil { diff --git a/command/scale_out.go b/command/scale_out.go index 7e96e824..8beb5b3d 100644 --- a/command/scale_out.go +++ b/command/scale_out.go @@ -26,6 +26,9 @@ General Options: -address= The Nomad HTTP API address including port which Levant will use to make calls. + + -allow-stale + Allow stale consistency mode for requests into nomad. -log-level= Specify the verbosity level of Levant's logs. Valid values include DEBUG, @@ -48,7 +51,7 @@ Scale Out Options: -task-group= The name of the task group you wish to target for scaling. Is this is not - speicified all task groups within the job will be scaled. + specified all task groups within the job will be scaled. ` return strings.TrimSpace(helpText) } @@ -64,18 +67,23 @@ func (c *ScaleOutCommand) Run(args []string) int { var err error var logL, logF string - config := &structs.ScalingConfig{} - config.Direction = structs.ScalingDirectionOut + config := &scale.Config{ + Client: &structs.ClientConfig{}, + Scale: &structs.ScaleConfig{ + Direction: structs.ScalingDirectionOut, + }, + } flags := c.Meta.FlagSet("scale-out", FlagSetVars) flags.Usage = func() { c.UI.Output(c.Help()) } - flags.StringVar(&config.Addr, "address", "", "") + flags.StringVar(&config.Client.Addr, "address", "", "") + flags.BoolVar(&config.Client.AllowStale, "allow-stale", false, "") flags.StringVar(&logL, "log-level", "INFO", "") flags.StringVar(&logF, "log-format", "HUMAN", "") - flags.IntVar(&config.Count, "count", 0, "") - flags.IntVar(&config.Percent, "percent", 0, "") - flags.StringVar(&config.TaskGroup, "task-group", "", "") + flags.IntVar(&config.Scale.Count, "count", 0, "") + flags.IntVar(&config.Scale.Percent, "percent", 0, "") + flags.StringVar(&config.Scale.TaskGroup, "task-group", "", "") if err = flags.Parse(args); err != nil { return 1 @@ -88,19 +96,19 @@ func (c *ScaleOutCommand) Run(args []string) int { return 1 } - config.JobID = args[0] + config.Scale.JobID = args[0] - if config.Count == 0 && config.Percent == 0 || config.Count > 0 && config.Percent > 0 { + if config.Scale.Count == 0 && config.Scale.Percent == 0 || config.Scale.Count > 0 && config.Scale.Percent > 0 { c.UI.Error("You must set either -count or -percent flag to scale-out") return 1 } - if config.Count > 0 { - config.DirectionType = structs.ScalingDirectionTypeCount + if config.Scale.Count > 0 { + config.Scale.DirectionType = structs.ScalingDirectionTypeCount } - if config.Percent > 0 { - config.DirectionType = structs.ScalingDirectionTypePercent + if config.Scale.Percent > 0 { + config.Scale.DirectionType = structs.ScalingDirectionTypePercent } if err = logging.SetupLogger(logL, logF); err != nil { diff --git a/levant/structs/config.go b/levant/structs/config.go index 4c835bcd..ce0d39b5 100644 --- a/levant/structs/config.go +++ b/levant/structs/config.go @@ -6,6 +6,18 @@ const ( // JobIDContextField is the logging context feild added when interacting // with jobs. JobIDContextField = "job_id" + + // ScalingDirectionOut represents a scaling out event; adding to the total number. + ScalingDirectionOut = "Out" + + // ScalingDirectionIn represents a scaling in event; removing from the total number. + ScalingDirectionIn = "In" + + // ScalingDirectionTypeCount means the scale event will use a change by count. + ScalingDirectionTypeCount = "Count" + + // ScalingDirectionTypePercent means the scale event will use a percentage of current change. + ScalingDirectionTypePercent = "Percent" ) // DeployConfig is the main struct used to configure and run a Levant deployment on @@ -61,3 +73,28 @@ type TemplateConfig struct { // templateFile before deployment. VariableFiles []string } + +// ScaleConfig contains all the scaling specific configuration options. +type ScaleConfig struct { + // Count is the count by which the operator has asked to scale the Nomad job + // and optional taskgroup by. + Count int + + // Direction is the direction in which the scaling will take place and is + // populated by consts. + Direction string + + // DirectionType is an identifier on whether the operator has specified to + // scale using a count increase or percentage. + DirectionType string + + // JobID is the Nomad job which will be interacted with for scaling. + JobID string + + // Percent is the percentage by which the operator has asked to scale the + // Nomad job and optional taskgroup by. + Percent int + + // TaskGroup is the Nomad job taskgroup which has been selected for scaling. + TaskGroup string +} diff --git a/levant/structs/scaling.go b/levant/structs/scaling.go deleted file mode 100644 index b7979d8a..00000000 --- a/levant/structs/scaling.go +++ /dev/null @@ -1,40 +0,0 @@ -package structs - -// These consts represent configuration indentifers to use when performing -// either a scale-out or scale-in operation. -const ( - ScalingDirectionOut = "Out" - ScalingDirectionIn = "In" - ScalingDirectionTypeCount = "Count" - ScalingDirectionTypePercent = "Percent" -) - -// ScalingConfig is an internal config struct used to track configuration -// details when performing a scale-out or scale-in operation. -type ScalingConfig struct { - // Addr is the Nomad API address to use for all calls and must include both - // protocol and port. - Addr string - - // Count is the count by which the operator has asked to scale the Nomad job - // and optional taskgroup by. - Count int - - // Direction is the direction in which the scaling will take place and is - // populated by consts. - Direction string - - // DirectionType is an identifier on whether the operator has specified to - // scale using a count increase or percentage. - DirectionType string - - // JobID is the Nomad job which will be interacted with for scaling. - JobID string - - // Percent is the percentage by which the operator has asked to scale the - // Nomad job and optional taskgroup by. - Percent int - - // TaskGroup is the Nomad job taskgroup which has been selected for scaling. - TaskGroup string -} diff --git a/scale/scale.go b/scale/scale.go index 4bbd98c6..2ba76f6b 100644 --- a/scale/scale.go +++ b/scale/scale.go @@ -10,14 +10,20 @@ import ( "github.com/rs/zerolog/log" ) +// Config is the set of config structs required to run a Levant scale. +type Config struct { + Client *structs.ClientConfig + Scale *structs.ScaleConfig +} + // TriggerScalingEvent provides the exported entry point into performing a job // scale based on user inputs. -func TriggerScalingEvent(config *structs.ScalingConfig) bool { +func TriggerScalingEvent(config *Config) bool { // Add the JobID as a log context field. - log.Logger = log.With().Str(structs.JobIDContextField, config.JobID).Logger() + log.Logger = log.With().Str(structs.JobIDContextField, config.Scale.JobID).Logger() - nomadClient, err := client.NewNomadClient(config.Addr) + nomadClient, err := client.NewNomadClient(config.Client.Addr) if err != nil { log.Error().Msg("levant/scale: unable to setup Levant scaling event") return false @@ -33,6 +39,7 @@ func TriggerScalingEvent(config *structs.ScalingConfig) bool { // go through the same process and code upgrades. deploymentConfig := &levant.DeployConfig{} deploymentConfig.Template = &structs.TemplateConfig{Job: job} + deploymentConfig.Client = config.Client deploymentConfig.Deploy = &structs.DeployConfig{ForceCount: true} log.Info().Msg("levant/scale: job will now be deployed with updated counts") @@ -51,9 +58,9 @@ func TriggerScalingEvent(config *structs.ScalingConfig) bool { // updateJob gathers information on the current state of the running job and // along with the user defined input updates the in-memory job specification // to reflect the desired scaled state. -func updateJob(client *nomad.Client, config *structs.ScalingConfig) *nomad.Job { +func updateJob(client *nomad.Client, config *Config) *nomad.Job { - job, _, err := client.Jobs().Info(config.JobID, nil) + job, _, err := client.Jobs().Info(config.Scale.JobID, nil) if err != nil { log.Error().Err(err).Msg("levant/scale: unable to obtain job information from Nomad") return nil @@ -70,10 +77,10 @@ func updateJob(client *nomad.Client, config *structs.ScalingConfig) *nomad.Job { // If the user has specified a taskgroup to scale, ensure we only change // the specific of this. - if config.TaskGroup != "" { - if *group.Name == config.TaskGroup { + if config.Scale.TaskGroup != "" { + if *group.Name == config.Scale.TaskGroup { log.Debug().Msgf("levant/scale: scaling action to be requested on taskgroup %s only", - config.TaskGroup) + config.Scale.TaskGroup) updateTaskGroup(config, group) } @@ -90,24 +97,24 @@ func updateJob(client *nomad.Client, config *structs.ScalingConfig) *nomad.Job { // updateTaskGroup is tasked with performing the count update based on the user // configuration when a group is identified as being marked for scaling. -func updateTaskGroup(config *structs.ScalingConfig, group *nomad.TaskGroup) { +func updateTaskGroup(config *Config, group *nomad.TaskGroup) { var c int // If a percentage scale value has been passed, we must convert this to an // int which represents the count to scale by as Nomad job submissions must // be done with group counts as desired ints. - switch config.DirectionType { + switch config.Scale.DirectionType { case structs.ScalingDirectionTypeCount: - c = config.Count + c = config.Scale.Count case structs.ScalingDirectionTypePercent: - c = calculateCountBasedOnPercent(*group.Count, config.Percent) + c = calculateCountBasedOnPercent(*group.Count, config.Scale.Percent) } // Depending on whether we are scaling-out or scaling-in we need to perform // the correct maths. There is a little duplication here, but that is to // provide better logging. - switch config.Direction { + switch config.Scale.Direction { case structs.ScalingDirectionOut: nc := *group.Count + c log.Info().Msgf("levant/scale: task group %s will scale-out from %v to %v",