Browse code

Add typed RestartPolicy

Signed-off-by: Michael Crosby <michael@docker.com>

Michael Crosby authored on 2014/08/05 08:14:43
Showing 3 changed files
... ...
@@ -501,6 +501,7 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
501 501
 		err       error
502 502
 		exitCode  int
503 503
 		failCount int
504
+		exit      bool
504 505
 
505 506
 		policy = container.hostConfig.RestartPolicy
506 507
 	)
... ...
@@ -522,8 +523,8 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
522 522
 		if exitCode, err = container.daemon.Run(container, pipes, callback); err != nil {
523 523
 			failCount++
524 524
 
525
-			if failCount == 100 {
526
-				container.requestedStop = true
525
+			if failCount == policy.MaximumRetryCount {
526
+				exit = true
527 527
 			}
528 528
 
529 529
 			utils.Errorf("Error running container: %s", err)
... ...
@@ -561,7 +562,7 @@ func (container *Container) monitor(callback execdriver.StartCallback) error {
561 561
 			container.daemon.srv.LogEvent("die", container.ID, container.daemon.repositories.ImageName(container.Image))
562 562
 		}
563 563
 
564
-		if (policy == "always" || (policy == "on-failure" && exitCode != 0)) && !container.requestedStop {
564
+		if (policy.Name == "always" || (policy.Name == "on-failure" && exitCode != 0)) && !container.requestedStop || !exit {
565 565
 			container.command.Cmd = copyCmd(&container.command.Cmd)
566 566
 
567 567
 			time.Sleep(1 * time.Second)
... ...
@@ -25,6 +25,11 @@ type DeviceMapping struct {
25 25
 	CgroupPermissions string
26 26
 }
27 27
 
28
+type RestartPolicy struct {
29
+	Name              string
30
+	MaximumRetryCount int
31
+}
32
+
28 33
 type HostConfig struct {
29 34
 	Binds           []string
30 35
 	ContainerIDFile string
... ...
@@ -40,7 +45,7 @@ type HostConfig struct {
40 40
 	NetworkMode     NetworkMode
41 41
 	CapAdd          []string
42 42
 	CapDrop         []string
43
-	RestartPolicy   string
43
+	RestartPolicy   RestartPolicy
44 44
 }
45 45
 
46 46
 func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
... ...
@@ -49,11 +54,12 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
49 49
 		Privileged:      job.GetenvBool("Privileged"),
50 50
 		PublishAllPorts: job.GetenvBool("PublishAllPorts"),
51 51
 		NetworkMode:     NetworkMode(job.Getenv("NetworkMode")),
52
-		RestartPolicy:   job.Getenv("RestartPolicy"),
53 52
 	}
53
+
54 54
 	job.GetenvJson("LxcConf", &hostConfig.LxcConf)
55 55
 	job.GetenvJson("PortBindings", &hostConfig.PortBindings)
56 56
 	job.GetenvJson("Devices", &hostConfig.Devices)
57
+	job.GetenvJson("RestartPolicy", &hostConfig.RestartPolicy)
57 58
 	if Binds := job.GetenvList("Binds"); Binds != nil {
58 59
 		hostConfig.Binds = Binds
59 60
 	}
... ...
@@ -75,5 +81,6 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
75 75
 	if CapDrop := job.GetenvList("CapDrop"); CapDrop != nil {
76 76
 		hostConfig.CapDrop = CapDrop
77 77
 	}
78
+
78 79
 	return hostConfig
79 80
 }
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"io/ioutil"
6 6
 	"path"
7
+	"strconv"
7 8
 	"strings"
8 9
 
9 10
 	"github.com/docker/docker/nat"
... ...
@@ -234,6 +235,11 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
234 234
 		return nil, nil, cmd, fmt.Errorf("--net: invalid net mode: %v", err)
235 235
 	}
236 236
 
237
+	restartPolicy, err := parseRestartPolicy(*flRestartPolicy)
238
+	if err != nil {
239
+		return nil, nil, cmd, err
240
+	}
241
+
237 242
 	config := &Config{
238 243
 		Hostname:        hostname,
239 244
 		Domainname:      domainname,
... ...
@@ -272,7 +278,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
272 272
 		Devices:         deviceMappings,
273 273
 		CapAdd:          flCapAdd.GetAll(),
274 274
 		CapDrop:         flCapDrop.GetAll(),
275
-		RestartPolicy:   *flRestartPolicy,
275
+		RestartPolicy:   restartPolicy,
276 276
 	}
277 277
 
278 278
 	if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
... ...
@@ -287,6 +293,38 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
287 287
 	return config, hostConfig, cmd, nil
288 288
 }
289 289
 
290
+// parseRestartPolicy returns the parsed policy or an error indicating what is incorrect
291
+func parseRestartPolicy(policy string) (RestartPolicy, error) {
292
+	p := RestartPolicy{}
293
+
294
+	if policy == "" {
295
+		return p, nil
296
+	}
297
+
298
+	var (
299
+		parts = strings.Split(policy, ":")
300
+		name  = parts[0]
301
+	)
302
+
303
+	switch name {
304
+	case "no", "on-failure", "always":
305
+		p.Name = name
306
+
307
+		if len(parts) == 2 {
308
+			count, err := strconv.Atoi(parts[1])
309
+			if err != nil {
310
+				return p, err
311
+			}
312
+
313
+			p.MaximumRetryCount = count
314
+		}
315
+	default:
316
+		return p, fmt.Errorf("invalid restart policy %s", name)
317
+	}
318
+
319
+	return p, nil
320
+}
321
+
290 322
 // options will come in the format of name.key=value or name.option
291 323
 func parseDriverOpts(opts opts.ListOpts) (map[string][]string, error) {
292 324
 	out := make(map[string][]string, len(opts.GetAll()))