diff --git a/cli/command/service/opts.go b/cli/command/service/opts.go index e1d328c487..ae1789515d 100644 --- a/cli/command/service/opts.go +++ b/cli/command/service/opts.go @@ -25,56 +25,6 @@ type int64Value interface { Value() int64 } -// PositiveDurationOpt is an option type for time.Duration that uses a pointer. -// It bahave similarly to DurationOpt but only allows positive duration values. -type PositiveDurationOpt struct { - DurationOpt -} - -// Set a new value on the option. Setting a negative duration value will cause -// an error to be returned. -func (d *PositiveDurationOpt) Set(s string) error { - err := d.DurationOpt.Set(s) - if err != nil { - return err - } - if *d.DurationOpt.value < 0 { - return errors.Errorf("duration cannot be negative") - } - return nil -} - -// DurationOpt is an option type for time.Duration that uses a pointer. This -// allows us to get nil values outside, instead of defaulting to 0 -type DurationOpt struct { - value *time.Duration -} - -// Set a new value on the option -func (d *DurationOpt) Set(s string) error { - v, err := time.ParseDuration(s) - d.value = &v - return err -} - -// Type returns the type of this option, which will be displayed in `--help` output -func (d *DurationOpt) Type() string { - return "duration" -} - -// String returns a string repr of this option -func (d *DurationOpt) String() string { - if d.value != nil { - return d.value.String() - } - return "" -} - -// Value returns the time.Duration -func (d *DurationOpt) Value() *time.Duration { - return d.value -} - // Uint64Opt represents a uint64. type Uint64Opt struct { value *uint64 @@ -293,9 +243,9 @@ func (r *resourceOptions) ToResourceRequirements() *swarm.ResourceRequirements { type restartPolicyOptions struct { condition string - delay DurationOpt + delay opts.DurationOpt maxAttempts Uint64Opt - window DurationOpt + window opts.DurationOpt } func defaultRestartPolicy() *swarm.RestartPolicy { @@ -444,10 +394,10 @@ func (ldo *logDriverOptions) toLogDriver() *swarm.Driver { type healthCheckOptions struct { cmd string - interval PositiveDurationOpt - timeout PositiveDurationOpt + interval opts.PositiveDurationOpt + timeout opts.PositiveDurationOpt retries int - startPeriod PositiveDurationOpt + startPeriod opts.PositiveDurationOpt noHealthcheck bool } @@ -529,7 +479,7 @@ type serviceOptions struct { hosts opts.ListOpts resources resourceOptions - stopGrace DurationOpt + stopGrace opts.DurationOpt replicas Uint64Opt mode string diff --git a/cli/command/service/opts_test.go b/cli/command/service/opts_test.go index 8d814f75c8..6bf00ef6bb 100644 --- a/cli/command/service/opts_test.go +++ b/cli/command/service/opts_test.go @@ -31,27 +31,6 @@ func TestNanoCPUsSetAndValue(t *testing.T) { assert.Equal(t, int64(350000000), cpus.Value()) } -func TestDurationOptString(t *testing.T) { - dur := time.Duration(300 * 10e8) - duration := DurationOpt{value: &dur} - assert.Equal(t, "5m0s", duration.String()) -} - -func TestDurationOptSetAndValue(t *testing.T) { - var duration DurationOpt - assert.NoError(t, duration.Set("300s")) - assert.Equal(t, time.Duration(300*10e8), *duration.Value()) - assert.NoError(t, duration.Set("-300s")) - assert.Equal(t, time.Duration(-300*10e8), *duration.Value()) -} - -func TestPositiveDurationOptSetAndValue(t *testing.T) { - var duration PositiveDurationOpt - assert.NoError(t, duration.Set("300s")) - assert.Equal(t, time.Duration(300*10e8), *duration.Value()) - assert.EqualError(t, duration.Set("-300s"), "duration cannot be negative") -} - func TestUint64OptString(t *testing.T) { value := uint64(2345678) opt := Uint64Opt{value: &value} @@ -71,9 +50,9 @@ func TestHealthCheckOptionsToHealthConfig(t *testing.T) { dur := time.Second opt := healthCheckOptions{ cmd: "curl", - interval: PositiveDurationOpt{DurationOpt{value: &dur}}, - timeout: PositiveDurationOpt{DurationOpt{value: &dur}}, - startPeriod: PositiveDurationOpt{DurationOpt{value: &dur}}, + interval: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, + timeout: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, + startPeriod: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, retries: 10, } config, err := opt.toHealthConfig() diff --git a/cli/command/service/update.go b/cli/command/service/update.go index ef5452fd3c..0894da94f7 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -253,7 +253,7 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags updateDurationOpt := func(flag string, field **time.Duration) { if flags.Changed(flag) { - val := *flags.Lookup(flag).Value.(*DurationOpt).Value() + val := *flags.Lookup(flag).Value.(*opts.DurationOpt).Value() *field = &val } } @@ -960,15 +960,15 @@ func updateHealthcheck(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec) containerSpec.Healthcheck.Test = nil } if flags.Changed(flagHealthInterval) { - val := *flags.Lookup(flagHealthInterval).Value.(*PositiveDurationOpt).Value() + val := *flags.Lookup(flagHealthInterval).Value.(*opts.PositiveDurationOpt).Value() containerSpec.Healthcheck.Interval = val } if flags.Changed(flagHealthTimeout) { - val := *flags.Lookup(flagHealthTimeout).Value.(*PositiveDurationOpt).Value() + val := *flags.Lookup(flagHealthTimeout).Value.(*opts.PositiveDurationOpt).Value() containerSpec.Healthcheck.Timeout = val } if flags.Changed(flagHealthStartPeriod) { - val := *flags.Lookup(flagHealthStartPeriod).Value.(*PositiveDurationOpt).Value() + val := *flags.Lookup(flagHealthStartPeriod).Value.(*opts.PositiveDurationOpt).Value() containerSpec.Healthcheck.StartPeriod = val } if flags.Changed(flagHealthRetries) { diff --git a/opts/duration.go b/opts/duration.go new file mode 100644 index 0000000000..5dc6eeaa73 --- /dev/null +++ b/opts/duration.go @@ -0,0 +1,64 @@ +package opts + +import ( + "time" + + "github.com/pkg/errors" +) + +// PositiveDurationOpt is an option type for time.Duration that uses a pointer. +// It behave similarly to DurationOpt but only allows positive duration values. +type PositiveDurationOpt struct { + DurationOpt +} + +// Set a new value on the option. Setting a negative duration value will cause +// an error to be returned. +func (d *PositiveDurationOpt) Set(s string) error { + err := d.DurationOpt.Set(s) + if err != nil { + return err + } + if *d.DurationOpt.value < 0 { + return errors.Errorf("duration cannot be negative") + } + return nil +} + +// DurationOpt is an option type for time.Duration that uses a pointer. This +// allows us to get nil values outside, instead of defaulting to 0 +type DurationOpt struct { + value *time.Duration +} + +// NewDurationOpt creates a DurationOpt with the specified duration +func NewDurationOpt(value *time.Duration) *DurationOpt { + return &DurationOpt{ + value: value, + } +} + +// Set a new value on the option +func (d *DurationOpt) Set(s string) error { + v, err := time.ParseDuration(s) + d.value = &v + return err +} + +// Type returns the type of this option, which will be displayed in `--help` output +func (d *DurationOpt) Type() string { + return "duration" +} + +// String returns a string repr of this option +func (d *DurationOpt) String() string { + if d.value != nil { + return d.value.String() + } + return "" +} + +// Value returns the time.Duration +func (d *DurationOpt) Value() *time.Duration { + return d.value +} diff --git a/opts/duration_test.go b/opts/duration_test.go new file mode 100644 index 0000000000..f766a1c74c --- /dev/null +++ b/opts/duration_test.go @@ -0,0 +1,29 @@ +package opts + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDurationOptString(t *testing.T) { + dur := time.Duration(300 * 10e8) + duration := DurationOpt{value: &dur} + assert.Equal(t, "5m0s", duration.String()) +} + +func TestDurationOptSetAndValue(t *testing.T) { + var duration DurationOpt + assert.NoError(t, duration.Set("300s")) + assert.Equal(t, time.Duration(300*10e8), *duration.Value()) + assert.NoError(t, duration.Set("-300s")) + assert.Equal(t, time.Duration(-300*10e8), *duration.Value()) +} + +func TestPositiveDurationOptSetAndValue(t *testing.T) { + var duration PositiveDurationOpt + assert.NoError(t, duration.Set("300s")) + assert.Equal(t, time.Duration(300*10e8), *duration.Value()) + assert.EqualError(t, duration.Set("-300s"), "duration cannot be negative") +}