mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
test: add basic integration tests
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
248
vendor/github.com/moby/buildkit/util/testutil/integration/dockerd.go
generated
vendored
Normal file
248
vendor/github.com/moby/buildkit/util/testutil/integration/dockerd.go
generated
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/buildkit/util/testutil/dockerd"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// InitDockerdWorker registers a dockerd worker with the global registry.
|
||||
func InitDockerdWorker() {
|
||||
Register(&Moby{
|
||||
ID: "dockerd",
|
||||
IsRootless: false,
|
||||
Unsupported: []string{
|
||||
FeatureCacheExport,
|
||||
FeatureCacheImport,
|
||||
FeatureCacheBackendAzblob,
|
||||
FeatureCacheBackendGha,
|
||||
FeatureCacheBackendLocal,
|
||||
FeatureCacheBackendRegistry,
|
||||
FeatureCacheBackendS3,
|
||||
FeatureDirectPush,
|
||||
FeatureImageExporter,
|
||||
FeatureMultiCacheExport,
|
||||
FeatureMultiPlatform,
|
||||
FeatureOCIExporter,
|
||||
FeatureOCILayout,
|
||||
FeatureProvenance,
|
||||
FeatureSBOM,
|
||||
FeatureSecurityMode,
|
||||
FeatureCNINetwork,
|
||||
},
|
||||
})
|
||||
Register(&Moby{
|
||||
ID: "dockerd-containerd",
|
||||
IsRootless: false,
|
||||
ContainerdSnapshotter: true,
|
||||
Unsupported: []string{
|
||||
FeatureSecurityMode,
|
||||
FeatureCNINetwork,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type Moby struct {
|
||||
ID string
|
||||
IsRootless bool
|
||||
|
||||
ContainerdSnapshotter bool
|
||||
|
||||
Unsupported []string
|
||||
}
|
||||
|
||||
func (c Moby) Name() string {
|
||||
return c.ID
|
||||
}
|
||||
|
||||
func (c Moby) Rootless() bool {
|
||||
return c.IsRootless
|
||||
}
|
||||
|
||||
func (c Moby) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl func() error, err error) {
|
||||
if err := requireRoot(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
bkcfg, err := config.LoadFile(cfg.ConfigFile)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to load buildkit config file %s", cfg.ConfigFile)
|
||||
}
|
||||
|
||||
dcfg := dockerd.Config{
|
||||
Features: map[string]bool{
|
||||
"containerd-snapshotter": c.ContainerdSnapshotter,
|
||||
},
|
||||
}
|
||||
if reg, ok := bkcfg.Registries["docker.io"]; ok && len(reg.Mirrors) > 0 {
|
||||
for _, m := range reg.Mirrors {
|
||||
dcfg.Mirrors = append(dcfg.Mirrors, "http://"+m)
|
||||
}
|
||||
}
|
||||
if bkcfg.Entitlements != nil {
|
||||
for _, e := range bkcfg.Entitlements {
|
||||
switch e {
|
||||
case "network.host":
|
||||
dcfg.Builder.Entitlements.NetworkHost = true
|
||||
case "security.insecure":
|
||||
dcfg.Builder.Entitlements.SecurityInsecure = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dcfgdt, err := json.Marshal(dcfg)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "failed to marshal dockerd config")
|
||||
}
|
||||
|
||||
deferF := &multiCloser{}
|
||||
cl = deferF.F()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
deferF.F()()
|
||||
cl = nil
|
||||
}
|
||||
}()
|
||||
|
||||
var proxyGroup errgroup.Group
|
||||
deferF.append(proxyGroup.Wait)
|
||||
|
||||
workDir, err := os.MkdirTemp("", "integration")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
d, err := dockerd.NewDaemon(workDir)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Errorf("new daemon error: %q, %s", err, formatLogs(cfg.Logs))
|
||||
}
|
||||
|
||||
dockerdConfigFile := filepath.Join(workDir, "daemon.json")
|
||||
if err := os.WriteFile(dockerdConfigFile, dcfgdt, 0644); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
dockerdFlags := []string{
|
||||
"--config-file", dockerdConfigFile,
|
||||
"--userland-proxy=false",
|
||||
"--debug",
|
||||
}
|
||||
if s := os.Getenv("BUILDKIT_INTEGRATION_DOCKERD_FLAGS"); s != "" {
|
||||
dockerdFlags = append(dockerdFlags, strings.Split(strings.TrimSpace(s), "\n")...)
|
||||
}
|
||||
|
||||
err = d.StartWithError(cfg.Logs, dockerdFlags...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
deferF.append(d.StopWithError)
|
||||
|
||||
if err := waitUnix(d.Sock(), 5*time.Second, nil); err != nil {
|
||||
return nil, nil, errors.Errorf("dockerd did not start up: %q, %s", err, formatLogs(cfg.Logs))
|
||||
}
|
||||
|
||||
dockerAPI, err := client.NewClientWithOpts(client.WithHost(d.Sock()))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
deferF.append(dockerAPI.Close)
|
||||
|
||||
err = waitForAPI(ctx, dockerAPI, 5*time.Second)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "dockerd client api timed out: %s", formatLogs(cfg.Logs))
|
||||
}
|
||||
|
||||
// Create a file descriptor to be used as a Unix domain socket.
|
||||
// Remove it immediately (the name will still be valid for the socket) so that
|
||||
// we don't leave files all over the users tmp tree.
|
||||
f, err := os.CreateTemp("", "buildkit-integration")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
localPath := f.Name()
|
||||
f.Close()
|
||||
os.Remove(localPath)
|
||||
|
||||
listener, err := net.Listen("unix", localPath)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "dockerd listener error: %s", formatLogs(cfg.Logs))
|
||||
}
|
||||
deferF.append(listener.Close)
|
||||
|
||||
proxyGroup.Go(func() error {
|
||||
for {
|
||||
tmpConn, err := listener.Accept()
|
||||
if err != nil {
|
||||
// Ignore the error from accept which is always a system error.
|
||||
return nil
|
||||
}
|
||||
conn, err := dockerAPI.DialHijack(ctx, "/grpc", "h2c", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proxyGroup.Go(func() error {
|
||||
_, err := io.Copy(conn, tmpConn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tmpConn.Close()
|
||||
})
|
||||
proxyGroup.Go(func() error {
|
||||
_, err := io.Copy(tmpConn, conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return conn.Close()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return backend{
|
||||
address: "unix://" + listener.Addr().String(),
|
||||
dockerAddress: d.Sock(),
|
||||
rootless: c.IsRootless,
|
||||
isDockerd: true,
|
||||
unsupportedFeatures: c.Unsupported,
|
||||
}, cl, nil
|
||||
}
|
||||
|
||||
func waitForAPI(ctx context.Context, apiClient *client.Client, d time.Duration) error {
|
||||
step := 50 * time.Millisecond
|
||||
i := 0
|
||||
for {
|
||||
if _, err := apiClient.Ping(ctx); err == nil {
|
||||
break
|
||||
}
|
||||
i++
|
||||
if time.Duration(i)*step > d {
|
||||
return errors.New("failed to connect to /_ping endpoint")
|
||||
}
|
||||
time.Sleep(step)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsTestDockerd() bool {
|
||||
return os.Getenv("TEST_DOCKERD") == "1"
|
||||
}
|
||||
|
||||
func IsTestDockerdMoby(sb Sandbox) bool {
|
||||
b, err := getBackend(sb)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return b.isDockerd && sb.Name() == "dockerd"
|
||||
}
|
Reference in New Issue
Block a user