| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | 
							- /*
 
-    Copyright 2020 Docker Compose CLI authors
 
-    Licensed under the Apache License, Version 2.0 (the "License");
 
-    you may not use this file except in compliance with the License.
 
-    You may obtain a copy of the License at
 
-        http://www.apache.org/licenses/LICENSE-2.0
 
-    Unless required by applicable law or agreed to in writing, software
 
-    distributed under the License is distributed on an "AS IS" BASIS,
 
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-    See the License for the specific language governing permissions and
 
-    limitations under the License.
 
- */
 
- package e2e
 
- import (
 
- 	"encoding/json"
 
- 	"fmt"
 
- 	"net"
 
- 	"net/http"
 
- 	"os"
 
- 	"testing"
 
- 	"time"
 
- 	"github.com/stretchr/testify/require"
 
- 	"gotest.tools/v3/icmd"
 
- )
 
- func TestPause(t *testing.T) {
 
- 	if _, ok := os.LookupEnv("CI"); ok {
 
- 		t.Skip("Skipping test on CI... flaky")
 
- 	}
 
- 	cli := NewParallelCLI(t, WithEnv(
 
- 		"COMPOSE_PROJECT_NAME=e2e-pause",
 
- 		"COMPOSE_FILE=./fixtures/pause/compose.yaml"))
 
- 	cleanup := func() {
 
- 		cli.RunDockerComposeCmd(t, "down", "-v", "--remove-orphans", "-t", "0")
 
- 	}
 
- 	cleanup()
 
- 	t.Cleanup(cleanup)
 
- 	// launch both services and verify that they are accessible
 
- 	cli.RunDockerComposeCmd(t, "up", "-d")
 
- 	urls := map[string]string{
 
- 		"a": urlForService(t, cli, "a", 80),
 
- 		"b": urlForService(t, cli, "b", 80),
 
- 	}
 
- 	for _, url := range urls {
 
- 		HTTPGetWithRetry(t, url, http.StatusOK, 50*time.Millisecond, 20*time.Second)
 
- 	}
 
- 	// pause a and verify that it can no longer be hit but b still can
 
- 	cli.RunDockerComposeCmd(t, "pause", "a")
 
- 	httpClient := http.Client{Timeout: 250 * time.Millisecond}
 
- 	resp, err := httpClient.Get(urls["a"])
 
- 	if resp != nil {
 
- 		_ = resp.Body.Close()
 
- 	}
 
- 	require.Error(t, err, "a should no longer respond")
 
- 	require.True(t, err.(net.Error).Timeout(), "Error should have indicated a timeout")
 
- 	HTTPGetWithRetry(t, urls["b"], http.StatusOK, 50*time.Millisecond, 5*time.Second)
 
- 	// unpause a and verify that both containers work again
 
- 	cli.RunDockerComposeCmd(t, "unpause", "a")
 
- 	for _, url := range urls {
 
- 		HTTPGetWithRetry(t, url, http.StatusOK, 50*time.Millisecond, 5*time.Second)
 
- 	}
 
- }
 
- func TestPauseServiceNotRunning(t *testing.T) {
 
- 	cli := NewParallelCLI(t, WithEnv(
 
- 		"COMPOSE_PROJECT_NAME=e2e-pause-svc-not-running",
 
- 		"COMPOSE_FILE=./fixtures/pause/compose.yaml"))
 
- 	cleanup := func() {
 
- 		cli.RunDockerComposeCmd(t, "down", "-v", "--remove-orphans", "-t", "0")
 
- 	}
 
- 	cleanup()
 
- 	t.Cleanup(cleanup)
 
- 	// pause a and verify that it can no longer be hit but b still can
 
- 	res := cli.RunDockerComposeCmdNoCheck(t, "pause", "a")
 
- 	// TODO: `docker pause` errors in this case, should Compose be consistent?
 
- 	res.Assert(t, icmd.Expected{ExitCode: 0})
 
- }
 
- func TestPauseServiceAlreadyPaused(t *testing.T) {
 
- 	cli := NewParallelCLI(t, WithEnv(
 
- 		"COMPOSE_PROJECT_NAME=e2e-pause-svc-already-paused",
 
- 		"COMPOSE_FILE=./fixtures/pause/compose.yaml"))
 
- 	cleanup := func() {
 
- 		cli.RunDockerComposeCmd(t, "down", "-v", "--remove-orphans", "-t", "0")
 
- 	}
 
- 	cleanup()
 
- 	t.Cleanup(cleanup)
 
- 	// launch a and wait for it to come up
 
- 	cli.RunDockerComposeCmd(t, "up", "-d", "a")
 
- 	HTTPGetWithRetry(t, urlForService(t, cli, "a", 80), http.StatusOK, 50*time.Millisecond, 10*time.Second)
 
- 	// pause a twice - first time should pass, second time fail
 
- 	cli.RunDockerComposeCmd(t, "pause", "a")
 
- 	res := cli.RunDockerComposeCmdNoCheck(t, "pause", "a")
 
- 	res.Assert(t, icmd.Expected{ExitCode: 1, Err: "already paused"})
 
- }
 
- func TestPauseServiceDoesNotExist(t *testing.T) {
 
- 	cli := NewParallelCLI(t, WithEnv(
 
- 		"COMPOSE_PROJECT_NAME=e2e-pause-svc-not-exist",
 
- 		"COMPOSE_FILE=./fixtures/pause/compose.yaml"))
 
- 	cleanup := func() {
 
- 		cli.RunDockerComposeCmd(t, "down", "-v", "--remove-orphans", "-t", "0")
 
- 	}
 
- 	cleanup()
 
- 	t.Cleanup(cleanup)
 
- 	// pause a and verify that it can no longer be hit but b still can
 
- 	res := cli.RunDockerComposeCmdNoCheck(t, "pause", "does_not_exist")
 
- 	// TODO: `compose down does_not_exist` and similar error, this should too
 
- 	res.Assert(t, icmd.Expected{ExitCode: 0})
 
- }
 
- func urlForService(t testing.TB, cli *CLI, service string, targetPort int) string {
 
- 	t.Helper()
 
- 	return fmt.Sprintf(
 
- 		"http://localhost:%d",
 
- 		publishedPortForService(t, cli, service, targetPort),
 
- 	)
 
- }
 
- func publishedPortForService(t testing.TB, cli *CLI, service string, targetPort int) int {
 
- 	t.Helper()
 
- 	res := cli.RunDockerComposeCmd(t, "ps", "--format=json", service)
 
- 	var psOut []struct {
 
- 		Publishers []struct {
 
- 			TargetPort    int
 
- 			PublishedPort int
 
- 		}
 
- 	}
 
- 	require.NoError(t, json.Unmarshal([]byte(res.Stdout()), &psOut),
 
- 		"Failed to parse `%s` output", res.Cmd.String())
 
- 	require.Len(t, psOut, 1, "Expected exactly 1 service")
 
- 	svc := psOut[0]
 
- 	for _, pp := range svc.Publishers {
 
- 		if pp.TargetPort == targetPort {
 
- 			return pp.PublishedPort
 
- 		}
 
- 	}
 
- 	require.Failf(t, "No published port for target port",
 
- 		"Target port: %d\nService: %s", targetPort, res.Combined())
 
- 	return -1
 
- }
 
 
  |