diff --git a/hack/dockerfiles/test.Dockerfile b/hack/dockerfiles/test.Dockerfile index ef35330f..b0d826c6 100644 --- a/hack/dockerfiles/test.Dockerfile +++ b/hack/dockerfiles/test.Dockerfile @@ -1,6 +1,7 @@ ARG RUNC_VERSION=74a17296470088de3805e138d3d87c62e613dfc4 ARG CONTAINERD_VERSION=v1.0.0 ARG BUILDKIT_TARGET=standalone +ARG REGISTRY_VERSION=2.6 FROM golang:1.9-alpine AS gobuild-base RUN apk add --no-cache g++ linux-headers @@ -44,10 +45,13 @@ FROM buildkit-base AS buildd-containerd ENV CGO_ENABLED=0 RUN go build -ldflags '-d' -o /usr/bin/buildd-containerd -tags containerd ./cmd/buildd +FROM registry:$REGISTRY_VERSION AS registry + FROM unit-tests AS integration-tests COPY --from=buildctl /usr/bin/buildctl /usr/bin/ COPY --from=buildd-containerd /usr/bin/buildd-containerd /usr/bin COPY --from=buildd-standalone /usr/bin/buildd-standalone /usr/bin +COPY --from=registry /bin/registry /usr/bin FROM gobuild-base AS cross-windows ENV GOOS=windows diff --git a/util/testutil/integration/containerd.go b/util/testutil/integration/containerd.go index 95d8ed36..c5980c13 100644 --- a/util/testutil/integration/containerd.go +++ b/util/testutil/integration/containerd.go @@ -70,7 +70,7 @@ func (c *containerd) New() (sb Sandbox, cl func() error, err error) { } deferF.append(stop) - return &cdsandbox{address: address, sandbox: sandbox{address: builddSock, logs: logs}}, cl, nil + return &cdsandbox{address: address, sandbox: sandbox{address: builddSock, logs: logs, cleanup: deferF}}, cl, nil } type cdsandbox struct { diff --git a/util/testutil/integration/registry.go b/util/testutil/integration/registry.go new file mode 100644 index 00000000..fa772dd2 --- /dev/null +++ b/util/testutil/integration/registry.go @@ -0,0 +1,102 @@ +package integration + +import ( + "bufio" + "context" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "time" + + "github.com/pkg/errors" +) + +func newRegistry() (url string, cl func() error, err error) { + if err := lookupBinary("registry"); err != nil { + return "", nil, err + } + + deferF := &multiCloser{} + cl = deferF.F() + + defer func() { + if err != nil { + deferF.F()() + cl = nil + } + }() + + tmpdir, err := ioutil.TempDir("", "test-registry") + if err != nil { + return "", nil, err + } + deferF.append(func() error { return os.RemoveAll(tmpdir) }) + + template := fmt.Sprintf(`version: 0.1 +loglevel: debug +storage: + filesystem: + rootdirectory: %s +http: + addr: 127.0.0.1:0 +`, filepath.Join(tmpdir, "data")) + + if err := ioutil.WriteFile(filepath.Join(tmpdir, "config.yaml"), []byte(template), 0600); err != nil { + return "", nil, err + } + + cmd := exec.Command("registry", "serve", filepath.Join(tmpdir, "config.yaml")) + rc, err := cmd.StdoutPipe() + if err != nil { + return "", nil, err + } + if stop, err := startCmd(cmd, nil); err != nil { + return "", nil, err + } else { + deferF.append(stop) + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + url, err = detectPort(ctx, rc) + if err != nil { + return "", nil, err + } + + return +} + +func detectPort(ctx context.Context, rc io.ReadCloser) (string, error) { + r := regexp.MustCompile("listening on 127\\.0\\.0\\.1:(\\d+)") + s := bufio.NewScanner(rc) + found := make(chan struct{}) + defer func() { + close(found) + go io.Copy(ioutil.Discard, rc) + }() + + go func() { + select { + case <-ctx.Done(): + select { + case <-found: + return + default: + rc.Close() + } + case <-found: + } + }() + + for s.Scan() { + res := r.FindSubmatch(s.Bytes()) + if len(res) > 1 { + return "localhost:" + string(res[1]), nil + } + } + return "", errors.Errorf("no listening address found") +} diff --git a/util/testutil/integration/run.go b/util/testutil/integration/run.go index 5ed363c3..b53a548d 100644 --- a/util/testutil/integration/run.go +++ b/util/testutil/integration/run.go @@ -16,6 +16,7 @@ type Sandbox interface { Address() string PrintLogs(*testing.T) Cmd(...string) *exec.Cmd + NewRegistry() (string, error) } type Worker interface { diff --git a/util/testutil/integration/standalone.go b/util/testutil/integration/standalone.go index 913e9639..cf49e8b3 100644 --- a/util/testutil/integration/standalone.go +++ b/util/testutil/integration/standalone.go @@ -38,12 +38,16 @@ func (s *standalone) New() (Sandbox, func() error, error) { return nil, nil, err } - return &sandbox{address: builddSock, logs: logs}, stop, nil + deferF := &multiCloser{} + deferF.append(stop) + + return &sandbox{address: builddSock, logs: logs, cleanup: deferF}, deferF.F(), nil } type sandbox struct { address string logs map[string]*bytes.Buffer + cleanup *multiCloser } func (sb *sandbox) Address() string { @@ -60,6 +64,15 @@ func (sb *sandbox) PrintLogs(t *testing.T) { } } +func (sb *sandbox) NewRegistry() (string, error) { + url, cl, err := newRegistry() + if err != nil { + return "", err + } + sb.cleanup.append(cl) + return url, nil +} + func (sb *sandbox) Cmd(args ...string) *exec.Cmd { if len(args) == 1 { if split, err := shlex.Split(args[0]); err == nil {