Skip to content
This repository has been archived by the owner on Jun 16, 2021. It is now read-only.

Commit

Permalink
Merge pull request #465 from gitlawr/add_stop_grace_period
Browse files Browse the repository at this point in the history
add 'stop_grace_period'
  • Loading branch information
Vincent Demeester authored May 11, 2017
2 parents 1a928db + 81e0786 commit 56b0613
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 60 deletions.
3 changes: 0 additions & 3 deletions cli/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ func RestartCommand(factory app.ProjectFactory) cli.Command {
cli.IntFlag{
Name: "timeout,t",
Usage: "Specify a shutdown timeout in seconds.",
Value: 10,
},
},
}
Expand All @@ -244,7 +243,6 @@ func StopCommand(factory app.ProjectFactory) cli.Command {
cli.IntFlag{
Name: "timeout,t",
Usage: "Specify a shutdown timeout in seconds.",
Value: 10,
},
},
}
Expand Down Expand Up @@ -283,7 +281,6 @@ func ScaleCommand(factory app.ProjectFactory) cli.Command {
cli.IntFlag{
Name: "timeout,t",
Usage: "Specify a shutdown timeout in seconds.",
Value: 10,
},
},
}
Expand Down
1 change: 1 addition & 0 deletions config/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ var servicesSchemaDataV2 = `{
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"stdin_open": {"type": "boolean"},
"stop_grace_period": {"type": "string"},
"stop_signal": {"type": "string"},
"tmpfs": {"$ref": "#/definitions/string_or_list"},
"tty": {"type": "boolean"},
Expand Down
115 changes: 58 additions & 57 deletions config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,63 +85,64 @@ type Log struct {

// ServiceConfig holds version 2 of libcompose service configuration
type ServiceConfig struct {
Build yaml.Build `yaml:"build,omitempty"`
CapAdd []string `yaml:"cap_add,omitempty"`
CapDrop []string `yaml:"cap_drop,omitempty"`
CPUSet string `yaml:"cpuset,omitempty"`
CPUShares yaml.StringorInt `yaml:"cpu_shares,omitempty"`
CPUQuota yaml.StringorInt `yaml:"cpu_quota,omitempty"`
Command yaml.Command `yaml:"command,flow,omitempty"`
CgroupParent string `yaml:"cgroup_parent,omitempty"`
ContainerName string `yaml:"container_name,omitempty"`
Devices []string `yaml:"devices,omitempty"`
DependsOn []string `yaml:"depends_on,omitempty"`
DNS yaml.Stringorslice `yaml:"dns,omitempty"`
DNSOpts []string `yaml:"dns_opt,omitempty"`
DNSSearch yaml.Stringorslice `yaml:"dns_search,omitempty"`
DomainName string `yaml:"domainname,omitempty"`
Entrypoint yaml.Command `yaml:"entrypoint,flow,omitempty"`
EnvFile yaml.Stringorslice `yaml:"env_file,omitempty"`
Environment yaml.MaporEqualSlice `yaml:"environment,omitempty"`
Expose []string `yaml:"expose,omitempty"`
Extends yaml.MaporEqualSlice `yaml:"extends,omitempty"`
ExternalLinks []string `yaml:"external_links,omitempty"`
ExtraHosts []string `yaml:"extra_hosts,omitempty"`
GroupAdd []string `yaml:"group_add,omitempty"`
Image string `yaml:"image,omitempty"`
Isolation string `yaml:"isolation,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
Ipc string `yaml:"ipc,omitempty"`
Labels yaml.SliceorMap `yaml:"labels,omitempty"`
Links yaml.MaporColonSlice `yaml:"links,omitempty"`
Logging Log `yaml:"logging,omitempty"`
MacAddress string `yaml:"mac_address,omitempty"`
MemLimit yaml.MemStringorInt `yaml:"mem_limit,omitempty"`
MemReservation yaml.MemStringorInt `yaml:"mem_reservation,omitempty"`
MemSwapLimit yaml.MemStringorInt `yaml:"memswap_limit,omitempty"`
MemSwappiness yaml.MemStringorInt `yaml:"mem_swappiness,omitempty"`
NetworkMode string `yaml:"network_mode,omitempty"`
Networks *yaml.Networks `yaml:"networks,omitempty"`
OomKillDisable bool `yaml:"oom_kill_disable,omitempty"`
OomScoreAdj yaml.StringorInt `yaml:"oom_score_adj,omitempty"`
Pid string `yaml:"pid,omitempty"`
Ports []string `yaml:"ports,omitempty"`
Privileged bool `yaml:"privileged,omitempty"`
SecurityOpt []string `yaml:"security_opt,omitempty"`
ShmSize yaml.MemStringorInt `yaml:"shm_size,omitempty"`
StopSignal string `yaml:"stop_signal,omitempty"`
Tmpfs yaml.Stringorslice `yaml:"tmpfs,omitempty"`
VolumeDriver string `yaml:"volume_driver,omitempty"`
Volumes *yaml.Volumes `yaml:"volumes,omitempty"`
VolumesFrom []string `yaml:"volumes_from,omitempty"`
Uts string `yaml:"uts,omitempty"`
Restart string `yaml:"restart,omitempty"`
ReadOnly bool `yaml:"read_only,omitempty"`
StdinOpen bool `yaml:"stdin_open,omitempty"`
Tty bool `yaml:"tty,omitempty"`
User string `yaml:"user,omitempty"`
WorkingDir string `yaml:"working_dir,omitempty"`
Ulimits yaml.Ulimits `yaml:"ulimits,omitempty"`
Build yaml.Build `yaml:"build,omitempty"`
CapAdd []string `yaml:"cap_add,omitempty"`
CapDrop []string `yaml:"cap_drop,omitempty"`
CPUSet string `yaml:"cpuset,omitempty"`
CPUShares yaml.StringorInt `yaml:"cpu_shares,omitempty"`
CPUQuota yaml.StringorInt `yaml:"cpu_quota,omitempty"`
Command yaml.Command `yaml:"command,flow,omitempty"`
CgroupParent string `yaml:"cgroup_parent,omitempty"`
ContainerName string `yaml:"container_name,omitempty"`
Devices []string `yaml:"devices,omitempty"`
DependsOn []string `yaml:"depends_on,omitempty"`
DNS yaml.Stringorslice `yaml:"dns,omitempty"`
DNSOpts []string `yaml:"dns_opt,omitempty"`
DNSSearch yaml.Stringorslice `yaml:"dns_search,omitempty"`
DomainName string `yaml:"domainname,omitempty"`
Entrypoint yaml.Command `yaml:"entrypoint,flow,omitempty"`
EnvFile yaml.Stringorslice `yaml:"env_file,omitempty"`
Environment yaml.MaporEqualSlice `yaml:"environment,omitempty"`
Expose []string `yaml:"expose,omitempty"`
Extends yaml.MaporEqualSlice `yaml:"extends,omitempty"`
ExternalLinks []string `yaml:"external_links,omitempty"`
ExtraHosts []string `yaml:"extra_hosts,omitempty"`
GroupAdd []string `yaml:"group_add,omitempty"`
Image string `yaml:"image,omitempty"`
Isolation string `yaml:"isolation,omitempty"`
Hostname string `yaml:"hostname,omitempty"`
Ipc string `yaml:"ipc,omitempty"`
Labels yaml.SliceorMap `yaml:"labels,omitempty"`
Links yaml.MaporColonSlice `yaml:"links,omitempty"`
Logging Log `yaml:"logging,omitempty"`
MacAddress string `yaml:"mac_address,omitempty"`
MemLimit yaml.MemStringorInt `yaml:"mem_limit,omitempty"`
MemReservation yaml.MemStringorInt `yaml:"mem_reservation,omitempty"`
MemSwapLimit yaml.MemStringorInt `yaml:"memswap_limit,omitempty"`
MemSwappiness yaml.MemStringorInt `yaml:"mem_swappiness,omitempty"`
NetworkMode string `yaml:"network_mode,omitempty"`
Networks *yaml.Networks `yaml:"networks,omitempty"`
OomKillDisable bool `yaml:"oom_kill_disable,omitempty"`
OomScoreAdj yaml.StringorInt `yaml:"oom_score_adj,omitempty"`
Pid string `yaml:"pid,omitempty"`
Ports []string `yaml:"ports,omitempty"`
Privileged bool `yaml:"privileged,omitempty"`
SecurityOpt []string `yaml:"security_opt,omitempty"`
ShmSize yaml.MemStringorInt `yaml:"shm_size,omitempty"`
StopGracePeriod string `yaml:"stop_grace_period,omitempty"`
StopSignal string `yaml:"stop_signal,omitempty"`
Tmpfs yaml.Stringorslice `yaml:"tmpfs,omitempty"`
VolumeDriver string `yaml:"volume_driver,omitempty"`
Volumes *yaml.Volumes `yaml:"volumes,omitempty"`
VolumesFrom []string `yaml:"volumes_from,omitempty"`
Uts string `yaml:"uts,omitempty"`
Restart string `yaml:"restart,omitempty"`
ReadOnly bool `yaml:"read_only,omitempty"`
StdinOpen bool `yaml:"stdin_open,omitempty"`
Tty bool `yaml:"tty,omitempty"`
User string `yaml:"user,omitempty"`
WorkingDir string `yaml:"working_dir,omitempty"`
Ulimits yaml.Ulimits `yaml:"ulimits,omitempty"`
}

// VolumeConfig holds v2 volume configuration
Expand Down
1 change: 1 addition & 0 deletions docker/service/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ func Convert(c *config.ServiceConfig, ctx project.Context, clientFactory compose
Volumes: toMap(Filter(vols, isVolume)),
MacAddress: c.MacAddress,
StopSignal: c.StopSignal,
StopTimeout: utils.DurationStrToSecondsInt(c.StopGracePeriod),
}

ulimits := []*units.Ulimit{}
Expand Down
11 changes: 11 additions & 0 deletions docker/service/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ func TestOomScoreAdj(t *testing.T) {
assert.Equal(t, 500, hostCfg.OomScoreAdj)
}

func TestStopGracePeriod(t *testing.T) {
ctx := &ctx.Context{}
sc := &config.ServiceConfig{
StopGracePeriod: "5s",
}
cfg, _, err := Convert(sc, ctx.Context, nil)
assert.Nil(t, err)

assert.Equal(t, 5, *cfg.StopTimeout)
}

func TestStopSignal(t *testing.T) {
ctx := &ctx.Context{}
sc := &config.ServiceConfig{
Expand Down
19 changes: 19 additions & 0 deletions docker/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,15 @@ func (s *Service) eachContainer(ctx context.Context, containers []*container.Con

// Stop implements Service.Stop. It stops any containers related to the service.
func (s *Service) Stop(ctx context.Context, timeout int) error {
timeout = s.stopTimeout(timeout)
return s.collectContainersAndDo(ctx, func(c *container.Container) error {
return c.Stop(ctx, timeout)
})
}

// Restart implements Service.Restart. It restarts any containers related to the service.
func (s *Service) Restart(ctx context.Context, timeout int) error {
timeout = s.stopTimeout(timeout)
return s.collectContainersAndDo(ctx, func(c *container.Container) error {
return c.Restart(ctx, timeout)
})
Expand Down Expand Up @@ -587,6 +589,7 @@ func (s *Service) Scale(ctx context.Context, scale int, timeout int) error {
for _, c := range containers {
foundCount++
if foundCount > scale {
timeout = s.stopTimeout(timeout)
if err := c.Stop(ctx, timeout); err != nil {
return err
}
Expand Down Expand Up @@ -728,3 +731,19 @@ func (s *Service) specificiesHostPort() bool {

return false
}

//take in timeout flag from cli as parameter
//return timeout if it is set,
//else return stop_grace_period if it is set,
//else return default 10s
func (s *Service) stopTimeout(timeout int) int {
DEFAULTTIMEOUT := 10
if timeout != 0 {
return timeout
}
configTimeout := utils.DurationStrToSecondsInt(s.Config().StopGracePeriod)
if configTimeout != nil {
return *configTimeout
}
return DEFAULTTIMEOUT
}
16 changes: 16 additions & 0 deletions utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package utils
import (
"encoding/json"
"sync"
"time"

"github.com/Sirupsen/logrus"

Expand Down Expand Up @@ -160,3 +161,18 @@ func ConvertKeysToStrings(item interface{}) interface{} {
return item
}
}

// DurationStrToSecondsInt converts duration string to *int in seconds
func DurationStrToSecondsInt(s string) *int {
if s == "" {
return nil
}
duration, err := time.ParseDuration(s)
if err != nil {
logrus.Errorf("Failed to parse duration:%v", s)
return nil
}
r := (int)(duration.Seconds())
return &r

}

0 comments on commit 56b0613

Please sign in to comment.