Skip to content

Commit

Permalink
Merge pull request moby#4432 from profnandaa/windows/integration-tests
Browse files Browse the repository at this point in the history
client/windows integration tests: plumbing work for running on windows
  • Loading branch information
tonistiigi authored Dec 7, 2023
2 parents 6997850 + 68afa16 commit bf84288
Show file tree
Hide file tree
Showing 18 changed files with 293 additions and 116 deletions.
2 changes: 1 addition & 1 deletion cmd/buildkitd/main_containerd_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ func validContainerdSocket(cfg config.ContainerdConfig) bool {
// FIXME(AkihiroSuda): prohibit tcp?
return true
}
socketPath := strings.TrimPrefix(socket, "unix://")
socketPath := strings.TrimPrefix(socket, socketScheme)
if _, err := os.Stat(socketPath); errors.Is(err, os.ErrNotExist) {
// FIXME(AkihiroSuda): add more conditions
bklog.L.Warnf("skipping containerd worker, as %q does not exist", socketPath)
Expand Down
2 changes: 2 additions & 0 deletions cmd/buildkitd/main_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/pkg/errors"
)

const socketScheme = "unix://"

func init() {
syscall.Umask(0)
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/buildkitd/main_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/pkg/errors"
)

const socketScheme = "npipe://"

func listenFD(addr string, tlsConfig *tls.Config) (net.Listener, error) {
return nil, errors.New("listening server on fd not supported on windows")
}
Expand Down
2 changes: 1 addition & 1 deletion util/testutil/integration/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func newSandbox(ctx context.Context, w Worker, mirror string, mv matrixValue) (s

b, closer, err := w.New(ctx, cfg)
if err != nil {
return nil, nil, err
return nil, nil, errors.Wrap(err, "creating worker")
}
deferF.Append(closer)

Expand Down
15 changes: 6 additions & 9 deletions util/testutil/integration/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"fmt"
"io"
"net"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -100,21 +99,19 @@ func StartCmd(cmd *exec.Cmd, logs map[string]*bytes.Buffer) (func() error, error
}, nil
}

func WaitUnix(address string, d time.Duration, cmd *exec.Cmd) error {
address = strings.TrimPrefix(address, "unix://")
addr, err := net.ResolveUnixAddr("unix", address)
if err != nil {
return errors.Wrapf(err, "failed resolving unix addr: %s", address)
}

// WaitSocket will dial a socket opened by a command passed in as cmd.
// On Linux this socket is typically a Unix socket,
// while on Windows this will be a named pipe.
func WaitSocket(address string, d time.Duration, cmd *exec.Cmd) error {
address = strings.TrimPrefix(address, socketScheme)
step := 50 * time.Millisecond
i := 0
for {
if cmd != nil && cmd.ProcessState != nil {
return errors.Errorf("process exited: %s", cmd.String())
}

if conn, err := net.DialUnix("unix", nil, addr); err == nil {
if conn, err := dialPipe(address); err == nil {
conn.Close()
break
}
Expand Down
23 changes: 23 additions & 0 deletions util/testutil/integration/util_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build !windows
// +build !windows

package integration

import (
"net"

"github.com/pkg/errors"
)

var socketScheme = "unix://"

// abstracted function to handle pipe dialing on unix.
// some simplification has been made to discard
// laddr for unix -- left as nil.
func dialPipe(address string) (net.Conn, error) {
addr, err := net.ResolveUnixAddr("unix", address)
if err != nil {
return nil, errors.Wrapf(err, "failed resolving unix addr: %s", address)
}
return net.DialUnix("unix", nil, addr)
}
15 changes: 15 additions & 0 deletions util/testutil/integration/util_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package integration

import (
"net"

"github.com/Microsoft/go-winio"
)

var socketScheme = "npipe://"

// abstracted function to handle pipe dialing on windows.
// some simplification has been made to discard timeout param.
func dialPipe(address string) (net.Conn, error) {
return winio.DialPipe(address, nil)
}
26 changes: 18 additions & 8 deletions util/testutil/workers/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@ func (c *Containerd) New(ctx context.Context, cfg *integration.BackendConfig) (b
if err := integration.LookupBinary(c.Containerd); err != nil {
return nil, nil, err
}

if err := integration.LookupBinary("buildkitd"); err != nil {
return nil, nil, err
}

if err := requireRoot(); err != nil {
return nil, nil, err
}
Expand All @@ -117,6 +119,7 @@ func (c *Containerd) New(ctx context.Context, cfg *integration.BackendConfig) (b
if err != nil {
return nil, nil, err
}

if rootless {
if err := os.Chown(tmpdir, c.UID, c.GID); err != nil {
return nil, nil, err
Expand All @@ -125,7 +128,7 @@ func (c *Containerd) New(ctx context.Context, cfg *integration.BackendConfig) (b

deferF.Append(func() error { return os.RemoveAll(tmpdir) })

address := filepath.Join(tmpdir, "containerd.sock")
address := getContainerdSock(tmpdir)
config := fmt.Sprintf(`root = %q
state = %q
# CRI plugins listens on 10010/tcp for stream server.
Expand All @@ -137,8 +140,11 @@ disabled_plugins = ["cri"]
[debug]
level = "debug"
address = %q
`, filepath.Join(tmpdir, "root"), filepath.Join(tmpdir, "state"), address, filepath.Join(tmpdir, "debug.sock"))
address = %q`,
filepath.Join(tmpdir, "root"),
filepath.Join(tmpdir, "state"),
address, getContainerdDebugSock(tmpdir),
)

var snBuildkitdArgs []string
if c.Snapshotter != "" {
Expand Down Expand Up @@ -185,19 +191,23 @@ disabled_plugins = ["cri"]
if err != nil {
return nil, nil, err
}
if err := integration.WaitUnix(address, 10*time.Second, cmd); err != nil {
if err := integration.WaitSocket(address, 10*time.Second, cmd); err != nil {
ctdStop()
return nil, nil, errors.Wrapf(err, "containerd did not start up: %s", integration.FormatLogs(cfg.Logs))
}
deferF.Append(ctdStop)

buildkitdArgs := append([]string{"buildkitd",
"--oci-worker=false",
// handles only windows case, no effect on unix
address = normalizeAddress(address)
buildkitdArgs := []string{
"buildkitd",
"--containerd-worker-gc=false",
"--containerd-worker=true",
"--containerd-worker-addr", address,
"--containerd-worker-labels=org.mobyproject.buildkit.worker.sandbox=true", // Include use of --containerd-worker-labels to trigger https://github.com/moby/buildkit/pull/603
}, snBuildkitdArgs...)
}
buildkitdArgs = applyBuildkitdPlatformFlags(buildkitdArgs)
buildkitdArgs = append(buildkitdArgs, snBuildkitdArgs...)

if runtime.GOOS != "windows" && c.Snapshotter != "native" {
c.ExtraEnv = append(c.ExtraEnv, "BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF=true")
Expand Down Expand Up @@ -266,7 +276,7 @@ func runStargzSnapshotter(cfg *integration.BackendConfig) (address string, cl fu
if err != nil {
return "", nil, err
}
if err = integration.WaitUnix(address, 10*time.Second, cmd); err != nil {
if err = integration.WaitSocket(address, 10*time.Second, cmd); err != nil {
snStop()
return "", nil, errors.Wrapf(err, "containerd-stargz-grpc did not start up: %s", integration.FormatLogs(cfg.Logs))
}
Expand Down
2 changes: 1 addition & 1 deletion util/testutil/workers/dockerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (c Moby) New(ctx context.Context, cfg *integration.BackendConfig) (b integr
}
deferF.Append(d.StopWithError)

if err := integration.WaitUnix(d.Sock(), 5*time.Second, nil); err != nil {
if err := integration.WaitSocket(d.Sock(), 5*time.Second, nil); err != nil {
return nil, nil, errors.Errorf("dockerd did not start up: %q, %s", err, integration.FormatLogs(cfg.Logs))
}

Expand Down
23 changes: 0 additions & 23 deletions util/testutil/workers/sysprocattr_unix.go

This file was deleted.

21 changes: 0 additions & 21 deletions util/testutil/workers/sysprocattr_windows.go

This file was deleted.

77 changes: 36 additions & 41 deletions util/testutil/workers/util.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
package workers

import (
"bufio"
"bytes"
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/moby/buildkit/util/testutil/integration"
"github.com/pkg/errors"
)

func requireRoot() error {
if os.Getuid() != 0 {
return errors.Wrap(integration.ErrRequirements, "requires root")
}
return nil
func withOTELSocketPath(socketPath string) integration.ConfigUpdater {
return otelSocketPath(socketPath)
}

type otelSocketPath string

func (osp otelSocketPath) UpdateConfigFile(in string) string {
return fmt.Sprintf(`%s
[otel]
socketPath = %q
`, in, osp)
}

func runBuildkitd(ctx context.Context, conf *integration.BackendConfig, args []string, logs map[string]*bytes.Buffer, uid, gid int, extraEnv []string) (address string, cl func() error, err error) {
func runBuildkitd(
ctx context.Context,
conf *integration.BackendConfig,
args []string,
logs map[string]*bytes.Buffer,
uid, gid int,
extraEnv []string,
) (address string, cl func() error, err error) {
deferF := &integration.MultiCloser{}
cl = deferF.F()

Expand All @@ -37,31 +48,39 @@ func runBuildkitd(ctx context.Context, conf *integration.BackendConfig, args []s
if err != nil {
return "", nil, err
}
if err := os.Chown(tmpdir, uid, gid); err != nil {

if err := chown(tmpdir, uid, gid); err != nil {
return "", nil, err
}

if err := os.MkdirAll(filepath.Join(tmpdir, "tmp"), 0711); err != nil {
return "", nil, err
}
if err := os.Chown(filepath.Join(tmpdir, "tmp"), uid, gid); err != nil {

if err := chown(filepath.Join(tmpdir, "tmp"), uid, gid); err != nil {
return "", nil, err
}
deferF.Append(func() error { return os.RemoveAll(tmpdir) })

cfgfile, err := integration.WriteConfig(append(conf.DaemonConfig, withOTELSocketPath(getTraceSocketPath(tmpdir))))
cfgfile, err := integration.WriteConfig(
append(conf.DaemonConfig, withOTELSocketPath(getTraceSocketPath(tmpdir))))
if err != nil {
return "", nil, err
}
deferF.Append(func() error {
return os.RemoveAll(filepath.Dir(cfgfile))
})
args = append(args, "--config="+cfgfile)

args = append(args, "--config="+cfgfile)
address = getBuildkitdAddr(tmpdir)

args = append(args, "--root", tmpdir, "--addr", address, "--debug")
cmd := exec.Command(args[0], args[1:]...) //nolint:gosec // test utility
cmd.Env = append(os.Environ(), "BUILDKIT_DEBUG_EXEC_OUTPUT=1", "BUILDKIT_DEBUG_PANIC_ON_ERROR=1", "TMPDIR="+filepath.Join(tmpdir, "tmp"))
cmd.Env = append(
os.Environ(),
"BUILDKIT_DEBUG_EXEC_OUTPUT=1",
"BUILDKIT_DEBUG_PANIC_ON_ERROR=1",
"TMPDIR="+filepath.Join(tmpdir, "tmp"))
cmd.Env = append(cmd.Env, extraEnv...)
cmd.SysProcAttr = getSysProcAttr()

Expand All @@ -71,38 +90,14 @@ func runBuildkitd(ctx context.Context, conf *integration.BackendConfig, args []s
}
deferF.Append(stop)

if err := integration.WaitUnix(address, 15*time.Second, cmd); err != nil {
if err := integration.WaitSocket(address, 15*time.Second, cmd); err != nil {
return "", nil, err
}

// separated out since it's not required in windows
deferF.Append(func() error {
f, err := os.Open("/proc/self/mountinfo")
if err != nil {
return errors.Wrap(err, "failed to open mountinfo")
}
defer f.Close()
s := bufio.NewScanner(f)
for s.Scan() {
if strings.Contains(s.Text(), tmpdir) {
return errors.Errorf("leaked mountpoint for %s", tmpdir)
}
}
return s.Err()
return mountInfo(tmpdir)
})

return address, cl, err
}

func withOTELSocketPath(socketPath string) integration.ConfigUpdater {
return otelSocketPath(socketPath)
}

type otelSocketPath string

func (osp otelSocketPath) UpdateConfigFile(in string) string {
return fmt.Sprintf(`%s
[otel]
socketPath = %q
`, in, osp)
}
Loading

0 comments on commit bf84288

Please sign in to comment.