Move fakecontext, fakegit and fakestorage to internal/test
Signed-off-by: Vincent Demeester <vincent@sbr.pm> Upstream-commit: 062564084a22f71cf5807ae5dfad7d29afb12e04 Component: engine
This commit is contained in:
@@ -15,11 +15,11 @@ import (
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/integration-cli/environment"
|
||||
testdaemon "github.com/docker/docker/internal/test/daemon"
|
||||
ienv "github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/docker/internal/test/fakestorage"
|
||||
"github.com/docker/docker/internal/test/fixtures/plugin"
|
||||
"github.com/docker/docker/internal/test/registry"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
"github.com/gotestyourself/gotestyourself/icmd"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
package fakecontext // import "github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
type testingT interface {
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(string, ...interface{})
|
||||
}
|
||||
|
||||
// New creates a fake build context
|
||||
func New(t testingT, dir string, modifiers ...func(*Fake) error) *Fake {
|
||||
fakeContext := &Fake{Dir: dir}
|
||||
if dir == "" {
|
||||
if err := newDir(fakeContext); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, modifier := range modifiers {
|
||||
if err := modifier(fakeContext); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return fakeContext
|
||||
}
|
||||
|
||||
func newDir(fake *Fake) error {
|
||||
tmp, err := ioutil.TempDir("", "fake-context")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Chmod(tmp, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
fake.Dir = tmp
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithFile adds the specified file (with content) in the build context
|
||||
func WithFile(name, content string) func(*Fake) error {
|
||||
return func(ctx *Fake) error {
|
||||
return ctx.Add(name, content)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDockerfile adds the specified content as Dockerfile in the build context
|
||||
func WithDockerfile(content string) func(*Fake) error {
|
||||
return WithFile("Dockerfile", content)
|
||||
}
|
||||
|
||||
// WithFiles adds the specified files in the build context, content is a string
|
||||
func WithFiles(files map[string]string) func(*Fake) error {
|
||||
return func(fakeContext *Fake) error {
|
||||
for file, content := range files {
|
||||
if err := fakeContext.Add(file, content); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBinaryFiles adds the specified files in the build context, content is binary
|
||||
func WithBinaryFiles(files map[string]*bytes.Buffer) func(*Fake) error {
|
||||
return func(fakeContext *Fake) error {
|
||||
for file, content := range files {
|
||||
if err := fakeContext.Add(file, string(content.Bytes())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fake creates directories that can be used as a build context
|
||||
type Fake struct {
|
||||
Dir string
|
||||
}
|
||||
|
||||
// Add a file at a path, creating directories where necessary
|
||||
func (f *Fake) Add(file, content string) error {
|
||||
return f.addFile(file, []byte(content))
|
||||
}
|
||||
|
||||
func (f *Fake) addFile(file string, content []byte) error {
|
||||
fp := filepath.Join(f.Dir, filepath.FromSlash(file))
|
||||
dirpath := filepath.Dir(fp)
|
||||
if dirpath != "." {
|
||||
if err := os.MkdirAll(dirpath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return ioutil.WriteFile(fp, content, 0644)
|
||||
|
||||
}
|
||||
|
||||
// Delete a file at a path
|
||||
func (f *Fake) Delete(file string) error {
|
||||
fp := filepath.Join(f.Dir, filepath.FromSlash(file))
|
||||
return os.RemoveAll(fp)
|
||||
}
|
||||
|
||||
// Close deletes the context
|
||||
func (f *Fake) Close() error {
|
||||
return os.RemoveAll(f.Dir)
|
||||
}
|
||||
|
||||
// AsTarReader returns a ReadCloser with the contents of Dir as a tar archive.
|
||||
func (f *Fake) AsTarReader(t testingT) io.ReadCloser {
|
||||
reader, err := archive.TarWithOptions(f.Dir, &archive.TarOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create tar from %s: %s", f.Dir, err)
|
||||
}
|
||||
return reader
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
package fakegit // import "github.com/docker/docker/integration-cli/cli/build/fakegit"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
type testingT interface {
|
||||
assert.TestingT
|
||||
logT
|
||||
skipT
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(string, ...interface{})
|
||||
}
|
||||
|
||||
type logT interface {
|
||||
Logf(string, ...interface{})
|
||||
}
|
||||
|
||||
type skipT interface {
|
||||
Skip(reason string)
|
||||
}
|
||||
|
||||
type gitServer interface {
|
||||
URL() string
|
||||
Close() error
|
||||
}
|
||||
|
||||
type localGitServer struct {
|
||||
*httptest.Server
|
||||
}
|
||||
|
||||
func (r *localGitServer) Close() error {
|
||||
r.Server.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *localGitServer) URL() string {
|
||||
return r.Server.URL
|
||||
}
|
||||
|
||||
// FakeGit is a fake git server
|
||||
type FakeGit struct {
|
||||
root string
|
||||
server gitServer
|
||||
RepoURL string
|
||||
}
|
||||
|
||||
// Close closes the server, implements Closer interface
|
||||
func (g *FakeGit) Close() {
|
||||
g.server.Close()
|
||||
os.RemoveAll(g.root)
|
||||
}
|
||||
|
||||
// New create a fake git server that can be used for git related tests
|
||||
func New(c testingT, name string, files map[string]string, enforceLocalServer bool) *FakeGit {
|
||||
ctx := fakecontext.New(c, "", fakecontext.WithFiles(files))
|
||||
defer ctx.Close()
|
||||
curdir, err := os.Getwd()
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
defer os.Chdir(curdir)
|
||||
|
||||
if output, err := exec.Command("git", "init", ctx.Dir).CombinedOutput(); err != nil {
|
||||
c.Fatalf("error trying to init repo: %s (%s)", err, output)
|
||||
}
|
||||
err = os.Chdir(ctx.Dir)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
if output, err := exec.Command("git", "config", "user.name", "Fake User").CombinedOutput(); err != nil {
|
||||
c.Fatalf("error trying to set 'user.name': %s (%s)", err, output)
|
||||
}
|
||||
if output, err := exec.Command("git", "config", "user.email", "fake.user@example.com").CombinedOutput(); err != nil {
|
||||
c.Fatalf("error trying to set 'user.email': %s (%s)", err, output)
|
||||
}
|
||||
if output, err := exec.Command("git", "add", "*").CombinedOutput(); err != nil {
|
||||
c.Fatalf("error trying to add files to repo: %s (%s)", err, output)
|
||||
}
|
||||
if output, err := exec.Command("git", "commit", "-a", "-m", "Initial commit").CombinedOutput(); err != nil {
|
||||
c.Fatalf("error trying to commit to repo: %s (%s)", err, output)
|
||||
}
|
||||
|
||||
root, err := ioutil.TempDir("", "docker-test-git-repo")
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
repoPath := filepath.Join(root, name+".git")
|
||||
if output, err := exec.Command("git", "clone", "--bare", ctx.Dir, repoPath).CombinedOutput(); err != nil {
|
||||
os.RemoveAll(root)
|
||||
c.Fatalf("error trying to clone --bare: %s (%s)", err, output)
|
||||
}
|
||||
err = os.Chdir(repoPath)
|
||||
if err != nil {
|
||||
os.RemoveAll(root)
|
||||
c.Fatal(err)
|
||||
}
|
||||
if output, err := exec.Command("git", "update-server-info").CombinedOutput(); err != nil {
|
||||
os.RemoveAll(root)
|
||||
c.Fatalf("error trying to git update-server-info: %s (%s)", err, output)
|
||||
}
|
||||
err = os.Chdir(curdir)
|
||||
if err != nil {
|
||||
os.RemoveAll(root)
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
||||
var server gitServer
|
||||
if !enforceLocalServer {
|
||||
// use fakeStorage server, which might be local or remote (at test daemon)
|
||||
server = fakestorage.New(c, root)
|
||||
} else {
|
||||
// always start a local http server on CLI test machine
|
||||
httpServer := httptest.NewServer(http.FileServer(http.Dir(root)))
|
||||
server = &localGitServer{httpServer}
|
||||
}
|
||||
return &FakeGit{
|
||||
root: root,
|
||||
server: server,
|
||||
RepoURL: fmt.Sprintf("%s/%s.git", server.URL(), name),
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package fakestorage // import "github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
)
|
||||
|
||||
var ensureHTTPServerOnce sync.Once
|
||||
|
||||
func ensureHTTPServerImage(t testingT) {
|
||||
var doIt bool
|
||||
ensureHTTPServerOnce.Do(func() {
|
||||
doIt = true
|
||||
})
|
||||
|
||||
if !doIt {
|
||||
return
|
||||
}
|
||||
|
||||
defer testEnv.ProtectImage(t, "httpserver:latest")
|
||||
|
||||
tmp, err := ioutil.TempDir("", "docker-http-server-test")
|
||||
if err != nil {
|
||||
t.Fatalf("could not build http server: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
goos := testEnv.OSType
|
||||
if goos == "" {
|
||||
goos = "linux"
|
||||
}
|
||||
goarch := os.Getenv("DOCKER_ENGINE_GOARCH")
|
||||
if goarch == "" {
|
||||
goarch = "amd64"
|
||||
}
|
||||
|
||||
cpCmd, lookErr := exec.LookPath("cp")
|
||||
if lookErr != nil {
|
||||
t.Fatalf("could not build http server: %v", lookErr)
|
||||
}
|
||||
|
||||
if _, err = os.Stat("../contrib/httpserver/httpserver"); os.IsNotExist(err) {
|
||||
goCmd, lookErr := exec.LookPath("go")
|
||||
if lookErr != nil {
|
||||
t.Fatalf("could not build http server: %v", lookErr)
|
||||
}
|
||||
|
||||
cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
|
||||
cmd.Env = append(os.Environ(), []string{
|
||||
"CGO_ENABLED=0",
|
||||
"GOOS=" + goos,
|
||||
"GOARCH=" + goarch,
|
||||
}...)
|
||||
var out []byte
|
||||
if out, err = cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("could not build http server: %s", string(out))
|
||||
}
|
||||
} else {
|
||||
if out, err := exec.Command(cpCmd, "../contrib/httpserver/httpserver", filepath.Join(tmp, "httpserver")).CombinedOutput(); err != nil {
|
||||
t.Fatalf("could not copy http server: %v", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
if out, err := exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
|
||||
t.Fatalf("could not build http server: %v", string(out))
|
||||
}
|
||||
|
||||
cli.DockerCmd(t, "build", "-q", "-t", "httpserver", tmp)
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
package fakestorage // import "github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/internal/test/environment"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
type testingT interface {
|
||||
assert.TestingT
|
||||
logT
|
||||
skipT
|
||||
Fatal(args ...interface{})
|
||||
Fatalf(string, ...interface{})
|
||||
}
|
||||
|
||||
type logT interface {
|
||||
Logf(string, ...interface{})
|
||||
}
|
||||
|
||||
type skipT interface {
|
||||
Skip(reason string)
|
||||
}
|
||||
|
||||
// Fake is a static file server. It might be running locally or remotely
|
||||
// on test host.
|
||||
type Fake interface {
|
||||
Close() error
|
||||
URL() string
|
||||
CtxDir() string
|
||||
}
|
||||
|
||||
// SetTestEnvironment sets a static test environment
|
||||
// TODO: decouple this package from environment
|
||||
func SetTestEnvironment(env *environment.Execution) {
|
||||
testEnv = env
|
||||
}
|
||||
|
||||
// New returns a static file server that will be use as build context.
|
||||
func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake {
|
||||
if testEnv == nil {
|
||||
t.Fatal("fakstorage package requires SetTestEnvironment() to be called before use.")
|
||||
}
|
||||
ctx := fakecontext.New(t, dir, modifiers...)
|
||||
switch {
|
||||
case testEnv.IsRemoteDaemon() && strings.HasPrefix(request.DaemonHost(), "unix:///"):
|
||||
t.Skip(fmt.Sprintf("e2e run : daemon is remote but docker host points to a unix socket"))
|
||||
case testEnv.IsLocalDaemon():
|
||||
return newLocalFakeStorage(ctx)
|
||||
default:
|
||||
return newRemoteFileServer(t, ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// localFileStorage is a file storage on the running machine
|
||||
type localFileStorage struct {
|
||||
*fakecontext.Fake
|
||||
*httptest.Server
|
||||
}
|
||||
|
||||
func (s *localFileStorage) URL() string {
|
||||
return s.Server.URL
|
||||
}
|
||||
|
||||
func (s *localFileStorage) CtxDir() string {
|
||||
return s.Fake.Dir
|
||||
}
|
||||
|
||||
func (s *localFileStorage) Close() error {
|
||||
defer s.Server.Close()
|
||||
return s.Fake.Close()
|
||||
}
|
||||
|
||||
func newLocalFakeStorage(ctx *fakecontext.Fake) *localFileStorage {
|
||||
handler := http.FileServer(http.Dir(ctx.Dir))
|
||||
server := httptest.NewServer(handler)
|
||||
return &localFileStorage{
|
||||
Fake: ctx,
|
||||
Server: server,
|
||||
}
|
||||
}
|
||||
|
||||
// remoteFileServer is a containerized static file server started on the remote
|
||||
// testing machine to be used in URL-accepting docker build functionality.
|
||||
type remoteFileServer struct {
|
||||
host string // hostname/port web server is listening to on docker host e.g. 0.0.0.0:43712
|
||||
container string
|
||||
image string
|
||||
ctx *fakecontext.Fake
|
||||
}
|
||||
|
||||
func (f *remoteFileServer) URL() string {
|
||||
u := url.URL{
|
||||
Scheme: "http",
|
||||
Host: f.host}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func (f *remoteFileServer) CtxDir() string {
|
||||
return f.ctx.Dir
|
||||
}
|
||||
|
||||
func (f *remoteFileServer) Close() error {
|
||||
defer func() {
|
||||
if f.ctx != nil {
|
||||
f.ctx.Close()
|
||||
}
|
||||
if f.image != "" {
|
||||
if err := cli.Docker(cli.Args("rmi", "-f", f.image)).Error; err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if f.container == "" {
|
||||
return nil
|
||||
}
|
||||
return cli.Docker(cli.Args("rm", "-fv", f.container)).Error
|
||||
}
|
||||
|
||||
func newRemoteFileServer(t testingT, ctx *fakecontext.Fake) *remoteFileServer {
|
||||
var (
|
||||
image = fmt.Sprintf("fileserver-img-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
|
||||
container = fmt.Sprintf("fileserver-cnt-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10)))
|
||||
)
|
||||
|
||||
ensureHTTPServerImage(t)
|
||||
|
||||
// Build the image
|
||||
if err := ctx.Add("Dockerfile", `FROM httpserver
|
||||
COPY . /static`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cli.BuildCmd(t, image, build.WithoutCache, build.WithExternalBuildContext(ctx))
|
||||
|
||||
// Start the container
|
||||
cli.DockerCmd(t, "run", "-d", "-P", "--name", container, image)
|
||||
|
||||
// Find out the system assigned port
|
||||
out := cli.DockerCmd(t, "port", container, "80/tcp").Combined()
|
||||
fileserverHostPort := strings.Trim(out, "\n")
|
||||
_, port, err := net.SplitHostPort(fileserverHostPort)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse file server host:port: %v", err)
|
||||
}
|
||||
|
||||
dockerHostURL, err := url.Parse(request.DaemonHost())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse daemon host URL: %v", err)
|
||||
}
|
||||
host, _, err := net.SplitHostPort(dockerHostURL.Host)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse docker daemon host:port: %v", err)
|
||||
}
|
||||
|
||||
return &remoteFileServer{
|
||||
container: container,
|
||||
image: image,
|
||||
host: fmt.Sprintf("%s:%s", host, port),
|
||||
ctx: ctx}
|
||||
}
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakegit"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakegit"
|
||||
"github.com/docker/docker/internal/test/fakestorage"
|
||||
"github.com/go-check/check"
|
||||
"github.com/gotestyourself/gotestyourself/assert"
|
||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakegit"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakegit"
|
||||
"github.com/docker/docker/internal/test/fakestorage"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/go-check/check"
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/go-check/check"
|
||||
"github.com/gotestyourself/gotestyourself/icmd"
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/go-check/check"
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/internal/test/fakecontext"
|
||||
"github.com/docker/docker/internal/testutil"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
|
||||
Reference in New Issue
Block a user