13 "github.com/docker/docker/integration-cli/cli"
14 "github.com/docker/docker/integration-cli/cli/build"
15 "github.com/docker/docker/integration-cli/cli/build/fakecontext"
16 "github.com/docker/docker/integration-cli/environment"
17 "github.com/docker/docker/integration-cli/request"
18 "github.com/docker/docker/pkg/stringutils"
22 testEnv *environment.Execution
26 // EnsureTestEnvIsLoaded make sure the test environment is loaded for this package
27 func EnsureTestEnvIsLoaded(t testingT) {
37 testEnv, err = environment.New()
39 t.Fatalf("error loading testenv : %v", err)
43 type testingT interface {
45 Fatal(args ...interface{})
46 Fatalf(string, ...interface{})
50 Logf(string, ...interface{})
53 // Fake is a static file server. It might be running locally or remotely
61 // New returns a static file server that will be use as build context.
62 func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake {
63 ctx := fakecontext.New(t, dir, modifiers...)
64 if testEnv.LocalDaemon() {
65 return newLocalFakeStorage(t, ctx)
67 return newRemoteFileServer(t, ctx)
70 // localFileStorage is a file storage on the running machine
71 type localFileStorage struct {
76 func (s *localFileStorage) URL() string {
80 func (s *localFileStorage) CtxDir() string {
84 func (s *localFileStorage) Close() error {
85 defer s.Server.Close()
89 func newLocalFakeStorage(t testingT, ctx *fakecontext.Fake) *localFileStorage {
90 handler := http.FileServer(http.Dir(ctx.Dir))
91 server := httptest.NewServer(handler)
92 return &localFileStorage{
98 // remoteFileServer is a containerized static file server started on the remote
99 // testing machine to be used in URL-accepting docker build functionality.
100 type remoteFileServer struct {
101 host string // hostname/port web server is listening to on docker host e.g. 0.0.0.0:43712
104 ctx *fakecontext.Fake
107 func (f *remoteFileServer) URL() string {
114 func (f *remoteFileServer) CtxDir() string {
118 func (f *remoteFileServer) Close() error {
124 if err := cli.Docker(cli.Args("rmi", "-f", f.image)).Error; err != nil {
125 fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err)
129 if f.container == "" {
132 return cli.Docker(cli.Args("rm", "-fv", f.container)).Error
135 func newRemoteFileServer(t testingT, ctx *fakecontext.Fake) *remoteFileServer {
137 image = fmt.Sprintf("fileserver-img-%s", strings.ToLower(stringutils.GenerateRandomAlphaOnlyString(10)))
138 container = fmt.Sprintf("fileserver-cnt-%s", strings.ToLower(stringutils.GenerateRandomAlphaOnlyString(10)))
141 ensureHTTPServerImage(t)
144 if err := ctx.Add("Dockerfile", `FROM httpserver
145 COPY . /static`); err != nil {
148 cli.BuildCmd(t, image, build.WithoutCache, build.WithExternalBuildContext(ctx))
150 // Start the container
151 cli.DockerCmd(t, "run", "-d", "-P", "--name", container, image)
153 // Find out the system assigned port
154 out := cli.DockerCmd(t, "port", container, "80/tcp").Combined()
155 fileserverHostPort := strings.Trim(out, "\n")
156 _, port, err := net.SplitHostPort(fileserverHostPort)
158 t.Fatalf("unable to parse file server host:port: %v", err)
161 dockerHostURL, err := url.Parse(request.DaemonHost())
163 t.Fatalf("unable to parse daemon host URL: %v", err)
166 host, _, err := net.SplitHostPort(dockerHostURL.Host)
168 t.Fatalf("unable to parse docker daemon host:port: %v", err)
171 return &remoteFileServer{
172 container: container,
174 host: fmt.Sprintf("%s:%s", host, port),