Skip to content

Commit

Permalink
Merge pull request #253 from jrasell/gh_251
Browse files Browse the repository at this point in the history
Fix a panic when running scale* deployment watcher.
  • Loading branch information
jrasell committed Nov 5, 2018
2 parents 66ea059 + 9f5a9f7 commit 8011161
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 90 deletions.
35 changes: 21 additions & 14 deletions command/scale_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ General Options:
-address=<http_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=<level>
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down
34 changes: 21 additions & 13 deletions command/scale_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ General Options:
-address=<http_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=<level>
Specify the verbosity level of Levant's logs. Valid values include DEBUG,
Expand All @@ -48,7 +51,7 @@ Scale Out Options:
-task-group=<name>
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)
}
Expand All @@ -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
Expand All @@ -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 {
Expand Down
37 changes: 37 additions & 0 deletions levant/structs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
40 changes: 0 additions & 40 deletions levant/structs/scaling.go

This file was deleted.

33 changes: 20 additions & 13 deletions scale/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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)
}

Expand All @@ -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",
Expand Down
24 changes: 14 additions & 10 deletions scale/scale_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestScale_updateTaskGroup(t *testing.T) {
sPercent := structs.ScalingDirectionTypePercent

cases := []struct {
Config *structs.ScalingConfig
Config *Config
Group *nomad.TaskGroup
EndCount int
}{
Expand Down Expand Up @@ -83,17 +83,20 @@ func TestScale_calculateCountBasedOnPercent(t *testing.T) {
}
}

func buildScalingConfig(direction, dType string, number int) *structs.ScalingConfig {
func buildScalingConfig(direction, dType string, number int) *Config {

c := &structs.ScalingConfig{}
c.Direction = direction
c.DirectionType = dType
c := &Config{
Scale: &structs.ScaleConfig{
Direction: direction,
DirectionType: dType,
},
}

switch dType {
case structs.ScalingDirectionTypeCount:
c.Count = number
c.Scale.Count = number
case structs.ScalingDirectionTypePercent:
c.Percent = number
c.Scale.Percent = number
}

return c
Expand All @@ -104,9 +107,10 @@ func buildTaskGroup(count int) *nomad.TaskGroup {
n := "LevantTest"
c := count

t := &nomad.TaskGroup{}
t.Name = &n
t.Count = &c
t := &nomad.TaskGroup{
Name: &n,
Count: &c,
}

return t
}

0 comments on commit 8011161

Please sign in to comment.