Browse code

Fixes #10457-Pause-and-unpause-accept-multi-containers

Applied multi parameters to pause and unpause.
Created a new test file dedicated for pause commands.
Created a new utility function to get a slice of paused containers.
Updated documentation

Signed-off-by: André Martins <martins@noironetworks.com>

André Martins authored on 2015/01/31 09:23:47
Showing 7 changed files
... ...
@@ -786,8 +786,8 @@ func (cli *DockerCli) CmdStart(args ...string) error {
786 786
 }
787 787
 
788 788
 func (cli *DockerCli) CmdUnpause(args ...string) error {
789
-	cmd := cli.Subcmd("unpause", "CONTAINER", "Unpause all processes within a container", true)
790
-	cmd.Require(flag.Exact, 1)
789
+	cmd := cli.Subcmd("unpause", "CONTAINER [CONTAINER...]", "Unpause all processes within a container", true)
790
+	cmd.Require(flag.Min, 1)
791 791
 	utils.ParseFlags(cmd, args, false)
792 792
 
793 793
 	var encounteredError error
... ...
@@ -803,8 +803,8 @@ func (cli *DockerCli) CmdUnpause(args ...string) error {
803 803
 }
804 804
 
805 805
 func (cli *DockerCli) CmdPause(args ...string) error {
806
-	cmd := cli.Subcmd("pause", "CONTAINER", "Pause all processes within a container", true)
807
-	cmd.Require(flag.Exact, 1)
806
+	cmd := cli.Subcmd("pause", "CONTAINER [CONTAINER...]", "Pause all processes within a container", true)
807
+	cmd.Require(flag.Min, 1)
808 808
 	utils.ParseFlags(cmd, args, false)
809 809
 
810 810
 	var encounteredError error
... ...
@@ -6,7 +6,7 @@ docker-pause - Pause all processes within a container
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker pause**
9
-CONTAINER
9
+CONTAINER [CONTAINER...]
10 10
 
11 11
 # DESCRIPTION
12 12
 
... ...
@@ -6,7 +6,7 @@ docker-unpause - Unpause all processes within a container
6 6
 
7 7
 # SYNOPSIS
8 8
 **docker unpause**
9
-CONTAINER
9
+CONTAINER [CONTAINER...]
10 10
 
11 11
 # DESCRIPTION
12 12
 
... ...
@@ -1359,7 +1359,7 @@ nano-second part of the timestamp will be padded with zero when necessary.
1359 1359
 
1360 1360
 ## pause
1361 1361
 
1362
-    Usage: docker pause CONTAINER
1362
+    Usage: docker pause CONTAINER [CONTAINER...]
1363 1363
 
1364 1364
     Pause all processes within a container
1365 1365
 
... ...
@@ -1396,22 +1396,6 @@ just a specific mapping:
1396 1396
     $ sudo docker port test 7890
1397 1397
     0.0.0.0:4321
1398 1398
 
1399
-## pause
1400
-
1401
-    Usage: docker pause CONTAINER
1402
-
1403
-    Pause all processes within a container
1404
-
1405
-The `docker pause` command uses the cgroups freezer to suspend all processes in
1406
-a container.  Traditionally when suspending a process the `SIGSTOP` signal is
1407
-used, which is observable by the process being suspended. With the cgroups freezer
1408
-the process is unaware, and unable to capture, that it is being suspended,
1409
-and subsequently resumed.
1410
-
1411
-See the
1412
-[cgroups freezer documentation](https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt)
1413
-for further details.
1414
-
1415 1399
 ## rename
1416 1400
 
1417 1401
     Usage: docker rename OLD_NAME NEW_NAME
... ...
@@ -2081,7 +2065,7 @@ them to [*Share Images via Repositories*](
2081 2081
 
2082 2082
 ## unpause
2083 2083
 
2084
-    Usage: docker unpause CONTAINER
2084
+    Usage: docker unpause CONTAINER [CONTAINER...]
2085 2085
 
2086 2086
     Unpause all processes within a container
2087 2087
 
... ...
@@ -30,41 +30,6 @@ func TestEventsUntag(t *testing.T) {
30 30
 	logDone("events - untags are logged")
31 31
 }
32 32
 
33
-func TestEventsPause(t *testing.T) {
34
-	name := "testeventpause"
35
-	out, _, _ := dockerCmd(t, "images", "-q")
36
-	image := strings.Split(out, "\n")[0]
37
-	dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
38
-	dockerCmd(t, "pause", name)
39
-	dockerCmd(t, "unpause", name)
40
-
41
-	defer deleteAllContainers()
42
-
43
-	eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
44
-	out, _, _ = runCommandWithOutput(eventsCmd)
45
-	events := strings.Split(out, "\n")
46
-	if len(events) <= 1 {
47
-		t.Fatalf("Missing expected event")
48
-	}
49
-
50
-	pauseEvent := strings.Fields(events[len(events)-3])
51
-	unpauseEvent := strings.Fields(events[len(events)-2])
52
-
53
-	if pauseEvent[len(pauseEvent)-1] != "pause" {
54
-		t.Fatalf("event should be pause, not %#v", pauseEvent)
55
-	}
56
-	if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
57
-		t.Fatalf("event should be unpause, not %#v", unpauseEvent)
58
-	}
59
-
60
-	waitCmd := exec.Command(dockerBinary, "wait", name)
61
-	if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
62
-		t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
63
-	}
64
-
65
-	logDone("events - pause/unpause is logged")
66
-}
67
-
68 33
 func TestEventsContainerFailStartDie(t *testing.T) {
69 34
 	defer deleteAllContainers()
70 35
 
71 36
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os/exec"
5
+	"strings"
6
+	"testing"
7
+	"time"
8
+)
9
+
10
+func TestPause(t *testing.T) {
11
+	defer deleteAllContainers()
12
+	defer unpauseAllContainers()
13
+
14
+	name := "testeventpause"
15
+	out, _, _ := dockerCmd(t, "images", "-q")
16
+	image := strings.Split(out, "\n")[0]
17
+	dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
18
+
19
+	dockerCmd(t, "pause", name)
20
+	pausedContainers, err := getSliceOfPausedContainers()
21
+	if err != nil {
22
+		t.Fatalf("error thrown while checking if containers were paused: %v", err)
23
+	}
24
+	if len(pausedContainers) != 1 {
25
+		t.Fatalf("there should be one paused container and not", len(pausedContainers))
26
+	}
27
+
28
+	dockerCmd(t, "unpause", name)
29
+
30
+	eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
31
+	out, _, _ = runCommandWithOutput(eventsCmd)
32
+	events := strings.Split(out, "\n")
33
+	if len(events) <= 1 {
34
+		t.Fatalf("Missing expected event")
35
+	}
36
+
37
+	pauseEvent := strings.Fields(events[len(events)-3])
38
+	unpauseEvent := strings.Fields(events[len(events)-2])
39
+
40
+	if pauseEvent[len(pauseEvent)-1] != "pause" {
41
+		t.Fatalf("event should be pause, not %#v", pauseEvent)
42
+	}
43
+	if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
44
+		t.Fatalf("event should be unpause, not %#v", unpauseEvent)
45
+	}
46
+
47
+	waitCmd := exec.Command(dockerBinary, "wait", name)
48
+	if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
49
+		t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
50
+	}
51
+
52
+	logDone("pause - pause/unpause is logged")
53
+}
54
+
55
+func TestPauseMultipleContainers(t *testing.T) {
56
+	defer deleteAllContainers()
57
+	defer unpauseAllContainers()
58
+
59
+	containers := []string{
60
+		"testpausewithmorecontainers1",
61
+		"testpausewithmorecontainers2",
62
+	}
63
+	out, _, _ := dockerCmd(t, "images", "-q")
64
+	image := strings.Split(out, "\n")[0]
65
+	for _, name := range containers {
66
+		dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
67
+	}
68
+	dockerCmd(t, append([]string{"pause"}, containers...)...)
69
+	pausedContainers, err := getSliceOfPausedContainers()
70
+	if err != nil {
71
+		t.Fatalf("error thrown while checking if containers were paused: %v", err)
72
+	}
73
+	if len(pausedContainers) != len(containers) {
74
+		t.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
75
+	}
76
+
77
+	dockerCmd(t, append([]string{"unpause"}, containers...)...)
78
+
79
+	eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
80
+	out, _, _ = runCommandWithOutput(eventsCmd)
81
+	events := strings.Split(out, "\n")
82
+	if len(events) <= len(containers)*3-2 {
83
+		t.Fatalf("Missing expected event")
84
+	}
85
+
86
+	pauseEvents := make([][]string, len(containers))
87
+	unpauseEvents := make([][]string, len(containers))
88
+	for i := range containers {
89
+		pauseEvents[i] = strings.Fields(events[len(events)-len(containers)*2-1+i])
90
+		unpauseEvents[i] = strings.Fields(events[len(events)-len(containers)-1+i])
91
+	}
92
+
93
+	for _, pauseEvent := range pauseEvents {
94
+		if pauseEvent[len(pauseEvent)-1] != "pause" {
95
+			t.Fatalf("event should be pause, not %#v", pauseEvent)
96
+		}
97
+	}
98
+	for _, unpauseEvent := range unpauseEvents {
99
+		if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
100
+			t.Fatalf("event should be unpause, not %#v", unpauseEvent)
101
+		}
102
+	}
103
+
104
+	for _, name := range containers {
105
+		waitCmd := exec.Command(dockerBinary, "wait", name)
106
+		if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
107
+			t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
108
+		}
109
+	}
110
+
111
+	logDone("pause - multi pause/unpause is logged")
112
+}
... ...
@@ -380,6 +380,16 @@ func getPausedContainers() (string, error) {
380 380
 	return out, err
381 381
 }
382 382
 
383
+func getSliceOfPausedContainers() ([]string, error) {
384
+	out, err := getPausedContainers()
385
+	if err == nil {
386
+		slice := strings.Split(strings.TrimSpace(out), "\n")
387
+		return slice, err
388
+	} else {
389
+		return []string{out}, err
390
+	}
391
+}
392
+
383 393
 func unpauseContainer(container string) error {
384 394
 	unpauseCmd := exec.Command(dockerBinary, "unpause", container)
385 395
 	exitCode, err := runCommand(unpauseCmd)