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>
| ... | ... |
@@ -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 |
| ... | ... |
@@ -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) |