github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/internal/test/fakestorage/storage.go (about) 1 package fakestorage // import "github.com/docker/docker/internal/test/fakestorage" 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "net/url" 11 "os" 12 "strings" 13 14 "github.com/docker/docker/api/types" 15 containertypes "github.com/docker/docker/api/types/container" 16 "github.com/docker/docker/client" 17 "github.com/docker/docker/integration-cli/request" 18 "github.com/docker/docker/internal/test/environment" 19 "github.com/docker/docker/internal/test/fakecontext" 20 "github.com/docker/docker/internal/testutil" 21 "github.com/docker/go-connections/nat" 22 "github.com/gotestyourself/gotestyourself/assert" 23 ) 24 25 var testEnv *environment.Execution 26 27 type testingT interface { 28 assert.TestingT 29 logT 30 skipT 31 Fatal(args ...interface{}) 32 Fatalf(string, ...interface{}) 33 } 34 35 type logT interface { 36 Logf(string, ...interface{}) 37 } 38 39 type skipT interface { 40 Skip(reason string) 41 } 42 43 // Fake is a static file server. It might be running locally or remotely 44 // on test host. 45 type Fake interface { 46 Close() error 47 URL() string 48 CtxDir() string 49 } 50 51 // SetTestEnvironment sets a static test environment 52 // TODO: decouple this package from environment 53 func SetTestEnvironment(env *environment.Execution) { 54 testEnv = env 55 } 56 57 // New returns a static file server that will be use as build context. 58 func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake { 59 if testEnv == nil { 60 t.Fatal("fakstorage package requires SetTestEnvironment() to be called before use.") 61 } 62 ctx := fakecontext.New(t, dir, modifiers...) 63 switch { 64 case testEnv.IsRemoteDaemon() && strings.HasPrefix(request.DaemonHost(), "unix:///"): 65 t.Skip(fmt.Sprintf("e2e run : daemon is remote but docker host points to a unix socket")) 66 case testEnv.IsLocalDaemon(): 67 return newLocalFakeStorage(ctx) 68 default: 69 return newRemoteFileServer(t, ctx, testEnv.APIClient()) 70 } 71 return nil 72 } 73 74 // localFileStorage is a file storage on the running machine 75 type localFileStorage struct { 76 *fakecontext.Fake 77 *httptest.Server 78 } 79 80 func (s *localFileStorage) URL() string { 81 return s.Server.URL 82 } 83 84 func (s *localFileStorage) CtxDir() string { 85 return s.Fake.Dir 86 } 87 88 func (s *localFileStorage) Close() error { 89 defer s.Server.Close() 90 return s.Fake.Close() 91 } 92 93 func newLocalFakeStorage(ctx *fakecontext.Fake) *localFileStorage { 94 handler := http.FileServer(http.Dir(ctx.Dir)) 95 server := httptest.NewServer(handler) 96 return &localFileStorage{ 97 Fake: ctx, 98 Server: server, 99 } 100 } 101 102 // remoteFileServer is a containerized static file server started on the remote 103 // testing machine to be used in URL-accepting docker build functionality. 104 type remoteFileServer struct { 105 host string // hostname/port web server is listening to on docker host e.g. 0.0.0.0:43712 106 container string 107 image string 108 client client.APIClient 109 ctx *fakecontext.Fake 110 } 111 112 func (f *remoteFileServer) URL() string { 113 u := url.URL{ 114 Scheme: "http", 115 Host: f.host} 116 return u.String() 117 } 118 119 func (f *remoteFileServer) CtxDir() string { 120 return f.ctx.Dir 121 } 122 123 func (f *remoteFileServer) Close() error { 124 defer func() { 125 if f.ctx != nil { 126 f.ctx.Close() 127 } 128 if f.image != "" { 129 if _, err := f.client.ImageRemove(context.Background(), f.image, types.ImageRemoveOptions{ 130 Force: true, 131 }); err != nil { 132 fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err) 133 } 134 } 135 if err := f.client.Close(); err != nil { 136 fmt.Fprintf(os.Stderr, "Error closing remote file server : %v\n", err) 137 } 138 }() 139 if f.container == "" { 140 return nil 141 } 142 return f.client.ContainerRemove(context.Background(), f.container, types.ContainerRemoveOptions{ 143 Force: true, 144 RemoveVolumes: true, 145 }) 146 } 147 148 func newRemoteFileServer(t testingT, ctx *fakecontext.Fake, c client.APIClient) *remoteFileServer { 149 var ( 150 image = fmt.Sprintf("fileserver-img-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10))) 151 container = fmt.Sprintf("fileserver-cnt-%s", strings.ToLower(testutil.GenerateRandomAlphaOnlyString(10))) 152 ) 153 154 ensureHTTPServerImage(t) 155 156 // Build the image 157 if err := ctx.Add("Dockerfile", `FROM httpserver 158 COPY . /static`); err != nil { 159 t.Fatal(err) 160 } 161 resp, err := c.ImageBuild(context.Background(), ctx.AsTarReader(t), types.ImageBuildOptions{ 162 NoCache: true, 163 Tags: []string{image}, 164 }) 165 assert.NilError(t, err) 166 _, err = io.Copy(ioutil.Discard, resp.Body) 167 assert.NilError(t, err) 168 169 // Start the container 170 b, err := c.ContainerCreate(context.Background(), &containertypes.Config{ 171 Image: image, 172 }, &containertypes.HostConfig{}, nil, container) 173 assert.NilError(t, err) 174 err = c.ContainerStart(context.Background(), b.ID, types.ContainerStartOptions{}) 175 assert.NilError(t, err) 176 177 // Find out the system assigned port 178 i, err := c.ContainerInspect(context.Background(), b.ID) 179 assert.NilError(t, err) 180 newP, err := nat.NewPort("tcp", "80") 181 assert.NilError(t, err) 182 ports, exists := i.NetworkSettings.Ports[newP] 183 if !exists || len(ports) != 1 { 184 t.Fatalf("unable to find port 80/tcp for %s", container) 185 } 186 host := ports[0].HostIP 187 port := ports[0].HostPort 188 189 return &remoteFileServer{ 190 container: container, 191 image: image, 192 host: fmt.Sprintf("%s:%s", host, port), 193 ctx: ctx, 194 client: c, 195 } 196 }