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:
Vincent Demeester
2018-04-17 09:53:09 +02:00
parent b77fed9a5f
commit a425bbca33
14 changed files with 83 additions and 48 deletions
@@ -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"