1package wait_test
2
3import (
4	"bytes"
5	"context"
6	"crypto/tls"
7	"crypto/x509"
8	"fmt"
9	"io"
10	"io/ioutil"
11	"net"
12	"net/http"
13	"os"
14	"testing"
15	"time"
16
17	"github.com/testcontainers/testcontainers-go"
18	"github.com/testcontainers/testcontainers-go/wait"
19)
20
21//
22// https://github.com/testcontainers/testcontainers-go/issues/183
23func ExampleHTTPStrategy() {
24	ctx := context.Background()
25	req := testcontainers.ContainerRequest{
26		Image:        "gogs/gogs:0.11.91",
27		ExposedPorts: []string{"3000/tcp"},
28		WaitingFor:   wait.ForHTTP("/").WithPort("3000/tcp"),
29	}
30
31	gogs, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
32		ContainerRequest: req,
33		Started:          true,
34	})
35	if err != nil {
36		panic(err)
37	}
38
39	defer gogs.Terminate(ctx) // nolint: errcheck
40	// Here you have a running container
41
42}
43
44func TestHTTPStrategyWaitUntilReady(t *testing.T) {
45	workdir, err := os.Getwd()
46	if err != nil {
47		t.Error(err)
48		return
49	}
50
51	capath := workdir + "/testdata/root.pem"
52	cafile, err := ioutil.ReadFile(capath)
53	if err != nil {
54		t.Errorf("can't load ca file: %v", err)
55		return
56	}
57
58	certpool := x509.NewCertPool()
59	if !certpool.AppendCertsFromPEM(cafile) {
60		t.Errorf("the ca file isn't valid")
61		return
62	}
63
64	tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"}
65	dockerReq := testcontainers.ContainerRequest{
66		FromDockerfile: testcontainers.FromDockerfile{
67			Context: workdir + "/testdata",
68		},
69		ExposedPorts: []string{"6443/tcp"},
70		WaitingFor: wait.NewHTTPStrategy("/ping").WithTLS(true, tlsconfig).
71			WithStartupTimeout(time.Second * 10).WithPort("6443/tcp").
72			WithResponseMatcher(func(body io.Reader) bool {
73				data, _ := ioutil.ReadAll(body)
74				return bytes.Equal(data, []byte("pong"))
75			}).
76			WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))),
77	}
78
79	container, err := testcontainers.GenericContainer(context.Background(),
80		testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true})
81	if err != nil {
82		t.Error(err)
83		return
84	}
85	defer container.Terminate(context.Background()) // nolint: errcheck
86
87	host, err := container.Host(context.Background())
88	if err != nil {
89		t.Error(err)
90		return
91	}
92	port, err := container.MappedPort(context.Background(), "6443/tcp")
93	if err != nil {
94		t.Error(err)
95		return
96	}
97	client := http.Client{
98		Transport: &http.Transport{
99			TLSClientConfig: tlsconfig,
100			Proxy:           http.ProxyFromEnvironment,
101			DialContext: (&net.Dialer{
102				Timeout:   time.Second,
103				KeepAlive: 30 * time.Second,
104				DualStack: true,
105			}).DialContext,
106			ForceAttemptHTTP2:     true,
107			MaxIdleConns:          100,
108			IdleConnTimeout:       90 * time.Second,
109			TLSHandshakeTimeout:   10 * time.Second,
110			ExpectContinueTimeout: 1 * time.Second,
111		},
112	}
113	resp, err := client.Get(fmt.Sprintf("https://%s:%s", host, port.Port()))
114	if err != nil {
115		t.Error(err)
116		return
117	}
118	defer resp.Body.Close()
119	if resp.StatusCode != http.StatusOK {
120		t.Errorf("status code isn't ok: %s", resp.Status)
121		return
122	}
123}
124