From 8de01fb7a8ff5589a57400684cd6fc07fbd89308 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Wed, 15 Feb 2017 16:04:30 -0800 Subject: [PATCH] Add support for rollback flags Signed-off-by: Aaron Lehmann --- command/formatter/service.go | 44 ++++++++ command/service/inspect_test.go | 1 - command/service/opts.go | 188 ++++++++++++++++++-------------- command/service/update.go | 11 ++ 4 files changed, 160 insertions(+), 84 deletions(-) diff --git a/command/formatter/service.go b/command/formatter/service.go index 421728976f..98c760ed7f 100644 --- a/command/formatter/service.go +++ b/command/formatter/service.go @@ -57,6 +57,18 @@ UpdateConfig: {{- end }} Max failure ratio: {{ .UpdateMaxFailureRatio }} {{- end }} +{{- if .HasRollbackConfig }} +RollbackConfig: + Parallelism: {{ .RollbackParallelism }} +{{- if .HasRollbackDelay}} + Delay: {{ .RollbackDelay }} +{{- end }} + On failure: {{ .RollbackOnFailure }} +{{- if .HasRollbackMonitor}} + Monitoring Period: {{ .RollbackMonitor }} +{{- end }} + Max failure ratio: {{ .RollbackMaxFailureRatio }} +{{- end }} ContainerSpec: Image: {{ .ContainerImage }} {{- if .ContainerArgs }} @@ -259,6 +271,38 @@ func (ctx *serviceInspectContext) UpdateMaxFailureRatio() float32 { return ctx.Service.Spec.UpdateConfig.MaxFailureRatio } +func (ctx *serviceInspectContext) HasRollbackConfig() bool { + return ctx.Service.Spec.RollbackConfig != nil +} + +func (ctx *serviceInspectContext) RollbackParallelism() uint64 { + return ctx.Service.Spec.RollbackConfig.Parallelism +} + +func (ctx *serviceInspectContext) HasRollbackDelay() bool { + return ctx.Service.Spec.RollbackConfig.Delay.Nanoseconds() > 0 +} + +func (ctx *serviceInspectContext) RollbackDelay() time.Duration { + return ctx.Service.Spec.RollbackConfig.Delay +} + +func (ctx *serviceInspectContext) RollbackOnFailure() string { + return ctx.Service.Spec.RollbackConfig.FailureAction +} + +func (ctx *serviceInspectContext) HasRollbackMonitor() bool { + return ctx.Service.Spec.RollbackConfig.Monitor.Nanoseconds() > 0 +} + +func (ctx *serviceInspectContext) RollbackMonitor() time.Duration { + return ctx.Service.Spec.RollbackConfig.Monitor +} + +func (ctx *serviceInspectContext) RollbackMaxFailureRatio() float32 { + return ctx.Service.Spec.RollbackConfig.MaxFailureRatio +} + func (ctx *serviceInspectContext) ContainerImage() string { return ctx.Service.Spec.TaskTemplate.ContainerSpec.Image } diff --git a/command/service/inspect_test.go b/command/service/inspect_test.go index 34c41ee78a..94c96cc164 100644 --- a/command/service/inspect_test.go +++ b/command/service/inspect_test.go @@ -49,7 +49,6 @@ func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time) Replicas: &two, }, }, - UpdateConfig: nil, Networks: []swarm.NetworkAttachmentConfig{ { Target: "5vpyomhb6ievnk0i0o60gcnei", diff --git a/command/service/opts.go b/command/service/opts.go index b9ae89ad0c..baaa58e1f0 100644 --- a/command/service/opts.go +++ b/command/service/opts.go @@ -165,6 +165,16 @@ type updateOptions struct { maxFailureRatio floatValue } +func (opts updateOptions) config() *swarm.UpdateConfig { + return &swarm.UpdateConfig{ + Parallelism: opts.parallelism, + Delay: opts.delay, + Monitor: opts.monitor, + FailureAction: opts.onFailure, + MaxFailureRatio: opts.maxFailureRatio.Value(), + } +} + type resourceOptions struct { limitCPU opts.NanoCPUs limitMemBytes opts.MemBytes @@ -328,6 +338,7 @@ type serviceOptions struct { constraints opts.ListOpts placementPrefs placementPrefOpts update updateOptions + rollback updateOptions networks opts.ListOpts endpoint endpointOptions @@ -445,16 +456,11 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) { }, LogDriver: opts.logDriver.toLogDriver(), }, - Networks: convertNetworks(opts.networks.GetAll()), - Mode: serviceMode, - UpdateConfig: &swarm.UpdateConfig{ - Parallelism: opts.update.parallelism, - Delay: opts.update.delay, - Monitor: opts.update.monitor, - FailureAction: opts.update.onFailure, - MaxFailureRatio: opts.update.maxFailureRatio.Value(), - }, - EndpointSpec: opts.endpoint.ToEndpointSpec(), + Networks: convertNetworks(opts.networks.GetAll()), + Mode: serviceMode, + UpdateConfig: opts.update.config(), + RollbackConfig: opts.rollback.config(), + EndpointSpec: opts.endpoint.ToEndpointSpec(), } return service, nil @@ -491,6 +497,17 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) { flags.Var(&opts.update.maxFailureRatio, flagUpdateMaxFailureRatio, "Failure rate to tolerate during an update") flags.SetAnnotation(flagUpdateMaxFailureRatio, "version", []string{"1.25"}) + flags.Uint64Var(&opts.rollback.parallelism, flagRollbackParallelism, 1, "Maximum number of tasks rolled back simultaneously (0 to roll back all at once)") + flags.SetAnnotation(flagRollbackParallelism, "version", []string{"1.27"}) + flags.DurationVar(&opts.rollback.delay, flagRollbackDelay, time.Duration(0), "Delay between task rollbacks (ns|us|ms|s|m|h) (default 0s)") + flags.SetAnnotation(flagRollbackDelay, "version", []string{"1.27"}) + flags.DurationVar(&opts.rollback.monitor, flagRollbackMonitor, time.Duration(0), "Duration after each task rollback to monitor for failure (ns|us|ms|s|m|h) (default 0s)") + flags.SetAnnotation(flagRollbackMonitor, "version", []string{"1.27"}) + flags.StringVar(&opts.rollback.onFailure, flagRollbackFailureAction, "pause", `Action on rollback failure ("pause"|"continue")`) + flags.SetAnnotation(flagRollbackFailureAction, "version", []string{"1.27"}) + flags.Var(&opts.rollback.maxFailureRatio, flagRollbackMaxFailureRatio, "Failure rate to tolerate during a rollback") + flags.SetAnnotation(flagRollbackMaxFailureRatio, "version", []string{"1.27"}) + flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "vip", "Endpoint mode (vip or dnsrr)") flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to swarm agents") @@ -520,77 +537,82 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) { } const ( - flagPlacementPref = "placement-pref" - flagPlacementPrefAdd = "placement-pref-add" - flagPlacementPrefRemove = "placement-pref-rm" - flagConstraint = "constraint" - flagConstraintRemove = "constraint-rm" - flagConstraintAdd = "constraint-add" - flagContainerLabel = "container-label" - flagContainerLabelRemove = "container-label-rm" - flagContainerLabelAdd = "container-label-add" - flagDNS = "dns" - flagDNSRemove = "dns-rm" - flagDNSAdd = "dns-add" - flagDNSOption = "dns-option" - flagDNSOptionRemove = "dns-option-rm" - flagDNSOptionAdd = "dns-option-add" - flagDNSSearch = "dns-search" - flagDNSSearchRemove = "dns-search-rm" - flagDNSSearchAdd = "dns-search-add" - flagEndpointMode = "endpoint-mode" - flagHost = "host" - flagHostAdd = "host-add" - flagHostRemove = "host-rm" - flagHostname = "hostname" - flagEnv = "env" - flagEnvFile = "env-file" - flagEnvRemove = "env-rm" - flagEnvAdd = "env-add" - flagGroup = "group" - flagGroupAdd = "group-add" - flagGroupRemove = "group-rm" - flagLabel = "label" - flagLabelRemove = "label-rm" - flagLabelAdd = "label-add" - flagLimitCPU = "limit-cpu" - flagLimitMemory = "limit-memory" - flagMode = "mode" - flagMount = "mount" - flagMountRemove = "mount-rm" - flagMountAdd = "mount-add" - flagName = "name" - flagNetwork = "network" - flagPublish = "publish" - flagPublishRemove = "publish-rm" - flagPublishAdd = "publish-add" - flagReadOnly = "read-only" - flagReplicas = "replicas" - flagReserveCPU = "reserve-cpu" - flagReserveMemory = "reserve-memory" - flagRestartCondition = "restart-condition" - flagRestartDelay = "restart-delay" - flagRestartMaxAttempts = "restart-max-attempts" - flagRestartWindow = "restart-window" - flagStopGracePeriod = "stop-grace-period" - flagStopSignal = "stop-signal" - flagTTY = "tty" - flagUpdateDelay = "update-delay" - flagUpdateFailureAction = "update-failure-action" - flagUpdateMaxFailureRatio = "update-max-failure-ratio" - flagUpdateMonitor = "update-monitor" - flagUpdateParallelism = "update-parallelism" - flagUser = "user" - flagWorkdir = "workdir" - flagRegistryAuth = "with-registry-auth" - flagLogDriver = "log-driver" - flagLogOpt = "log-opt" - flagHealthCmd = "health-cmd" - flagHealthInterval = "health-interval" - flagHealthRetries = "health-retries" - flagHealthTimeout = "health-timeout" - flagNoHealthcheck = "no-healthcheck" - flagSecret = "secret" - flagSecretAdd = "secret-add" - flagSecretRemove = "secret-rm" + flagPlacementPref = "placement-pref" + flagPlacementPrefAdd = "placement-pref-add" + flagPlacementPrefRemove = "placement-pref-rm" + flagConstraint = "constraint" + flagConstraintRemove = "constraint-rm" + flagConstraintAdd = "constraint-add" + flagContainerLabel = "container-label" + flagContainerLabelRemove = "container-label-rm" + flagContainerLabelAdd = "container-label-add" + flagDNS = "dns" + flagDNSRemove = "dns-rm" + flagDNSAdd = "dns-add" + flagDNSOption = "dns-option" + flagDNSOptionRemove = "dns-option-rm" + flagDNSOptionAdd = "dns-option-add" + flagDNSSearch = "dns-search" + flagDNSSearchRemove = "dns-search-rm" + flagDNSSearchAdd = "dns-search-add" + flagEndpointMode = "endpoint-mode" + flagHost = "host" + flagHostAdd = "host-add" + flagHostRemove = "host-rm" + flagHostname = "hostname" + flagEnv = "env" + flagEnvFile = "env-file" + flagEnvRemove = "env-rm" + flagEnvAdd = "env-add" + flagGroup = "group" + flagGroupAdd = "group-add" + flagGroupRemove = "group-rm" + flagLabel = "label" + flagLabelRemove = "label-rm" + flagLabelAdd = "label-add" + flagLimitCPU = "limit-cpu" + flagLimitMemory = "limit-memory" + flagMode = "mode" + flagMount = "mount" + flagMountRemove = "mount-rm" + flagMountAdd = "mount-add" + flagName = "name" + flagNetwork = "network" + flagPublish = "publish" + flagPublishRemove = "publish-rm" + flagPublishAdd = "publish-add" + flagReadOnly = "read-only" + flagReplicas = "replicas" + flagReserveCPU = "reserve-cpu" + flagReserveMemory = "reserve-memory" + flagRestartCondition = "restart-condition" + flagRestartDelay = "restart-delay" + flagRestartMaxAttempts = "restart-max-attempts" + flagRestartWindow = "restart-window" + flagRollbackDelay = "rollback-delay" + flagRollbackFailureAction = "rollback-failure-action" + flagRollbackMaxFailureRatio = "rollback-max-failure-ratio" + flagRollbackMonitor = "rollback-monitor" + flagRollbackParallelism = "rollback-parallelism" + flagStopGracePeriod = "stop-grace-period" + flagStopSignal = "stop-signal" + flagTTY = "tty" + flagUpdateDelay = "update-delay" + flagUpdateFailureAction = "update-failure-action" + flagUpdateMaxFailureRatio = "update-max-failure-ratio" + flagUpdateMonitor = "update-monitor" + flagUpdateParallelism = "update-parallelism" + flagUser = "user" + flagWorkdir = "workdir" + flagRegistryAuth = "with-registry-auth" + flagLogDriver = "log-driver" + flagLogOpt = "log-opt" + flagHealthCmd = "health-cmd" + flagHealthInterval = "health-interval" + flagHealthRetries = "health-retries" + flagHealthTimeout = "health-timeout" + flagNoHealthcheck = "no-healthcheck" + flagSecret = "secret" + flagSecretAdd = "secret-add" + flagSecretRemove = "secret-rm" ) diff --git a/command/service/update.go b/command/service/update.go index 0c19c0713e..b529331500 100644 --- a/command/service/update.go +++ b/command/service/update.go @@ -289,6 +289,17 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { updateFloatValue(flagUpdateMaxFailureRatio, &spec.UpdateConfig.MaxFailureRatio) } + if anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio) { + if spec.RollbackConfig == nil { + spec.RollbackConfig = &swarm.UpdateConfig{} + } + updateUint64(flagRollbackParallelism, &spec.RollbackConfig.Parallelism) + updateDuration(flagRollbackDelay, &spec.RollbackConfig.Delay) + updateDuration(flagRollbackMonitor, &spec.RollbackConfig.Monitor) + updateString(flagRollbackFailureAction, &spec.RollbackConfig.FailureAction) + updateFloatValue(flagRollbackMaxFailureRatio, &spec.RollbackConfig.MaxFailureRatio) + } + if flags.Changed(flagEndpointMode) { value, _ := flags.GetString(flagEndpointMode) if spec.EndpointSpec == nil {