github.com/afbjorklund/moby@v20.10.5+incompatible/integration-cli/check_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "io/ioutil" 8 "net/http/httptest" 9 "os" 10 "path" 11 "path/filepath" 12 "strconv" 13 "sync" 14 "syscall" 15 "testing" 16 "time" 17 18 "github.com/docker/docker/integration-cli/cli" 19 "github.com/docker/docker/integration-cli/daemon" 20 "github.com/docker/docker/integration-cli/environment" 21 "github.com/docker/docker/internal/test/suite" 22 "github.com/docker/docker/pkg/reexec" 23 testdaemon "github.com/docker/docker/testutil/daemon" 24 ienv "github.com/docker/docker/testutil/environment" 25 "github.com/docker/docker/testutil/fakestorage" 26 "github.com/docker/docker/testutil/fixtures/plugin" 27 "github.com/docker/docker/testutil/registry" 28 "gotest.tools/v3/assert" 29 ) 30 31 const ( 32 // the private registry to use for tests 33 privateRegistryURL = registry.DefaultURL 34 35 // path to containerd's ctr binary 36 ctrBinary = "ctr" 37 38 // the docker daemon binary to use 39 dockerdBinary = "dockerd" 40 ) 41 42 var ( 43 testEnv *environment.Execution 44 45 // the docker client binary to use 46 dockerBinary = "" 47 48 testEnvOnce sync.Once 49 ) 50 51 func init() { 52 var err error 53 54 reexec.Init() // This is required for external graphdriver tests 55 56 testEnv, err = environment.New() 57 if err != nil { 58 fmt.Println(err) 59 os.Exit(1) 60 } 61 } 62 63 func TestMain(m *testing.M) { 64 flag.Parse() 65 66 // Global set up 67 dockerBinary = testEnv.DockerBinary() 68 err := ienv.EnsureFrozenImagesLinux(&testEnv.Execution) 69 if err != nil { 70 fmt.Println(err) 71 os.Exit(1) 72 } 73 74 testEnv.Print() 75 os.Exit(m.Run()) 76 } 77 78 func ensureTestEnvSetup(t *testing.T) { 79 testEnvOnce.Do(func() { 80 cli.SetTestEnvironment(testEnv) 81 fakestorage.SetTestEnvironment(&testEnv.Execution) 82 ienv.ProtectAll(t, &testEnv.Execution) 83 }) 84 } 85 86 func TestDockerSuite(t *testing.T) { 87 ensureTestEnvSetup(t) 88 suite.Run(t, &DockerSuite{}) 89 } 90 91 func TestDockerRegistrySuite(t *testing.T) { 92 ensureTestEnvSetup(t) 93 suite.Run(t, &DockerRegistrySuite{ds: &DockerSuite{}}) 94 } 95 96 func TestDockerSchema1RegistrySuite(t *testing.T) { 97 ensureTestEnvSetup(t) 98 suite.Run(t, &DockerSchema1RegistrySuite{ds: &DockerSuite{}}) 99 } 100 101 func TestDockerRegistryAuthHtpasswdSuite(t *testing.T) { 102 ensureTestEnvSetup(t) 103 suite.Run(t, &DockerRegistryAuthHtpasswdSuite{ds: &DockerSuite{}}) 104 } 105 106 func TestDockerRegistryAuthTokenSuite(t *testing.T) { 107 ensureTestEnvSetup(t) 108 suite.Run(t, &DockerRegistryAuthTokenSuite{ds: &DockerSuite{}}) 109 } 110 111 func TestDockerDaemonSuite(t *testing.T) { 112 ensureTestEnvSetup(t) 113 suite.Run(t, &DockerDaemonSuite{ds: &DockerSuite{}}) 114 } 115 116 func TestDockerSwarmSuite(t *testing.T) { 117 ensureTestEnvSetup(t) 118 suite.Run(t, &DockerSwarmSuite{ds: &DockerSuite{}}) 119 } 120 121 func TestDockerPluginSuite(t *testing.T) { 122 ensureTestEnvSetup(t) 123 suite.Run(t, &DockerPluginSuite{ds: &DockerSuite{}}) 124 } 125 126 func TestDockerExternalVolumeSuite(t *testing.T) { 127 ensureTestEnvSetup(t) 128 testRequires(t, DaemonIsLinux) 129 suite.Run(t, &DockerExternalVolumeSuite{ds: &DockerSuite{}}) 130 } 131 132 func TestDockerNetworkSuite(t *testing.T) { 133 ensureTestEnvSetup(t) 134 testRequires(t, DaemonIsLinux) 135 suite.Run(t, &DockerNetworkSuite{ds: &DockerSuite{}}) 136 } 137 138 func TestDockerHubPullSuite(t *testing.T) { 139 ensureTestEnvSetup(t) 140 // FIXME. Temporarily turning this off for Windows as GH16039 was breaking 141 // Windows to Linux CI @icecrime 142 testRequires(t, DaemonIsLinux) 143 suite.Run(t, newDockerHubPullSuite()) 144 } 145 146 type DockerSuite struct { 147 } 148 149 func (s *DockerSuite) OnTimeout(c *testing.T) { 150 if testEnv.IsRemoteDaemon() { 151 return 152 } 153 path := filepath.Join(os.Getenv("DEST"), "docker.pid") 154 b, err := ioutil.ReadFile(path) 155 if err != nil { 156 c.Fatalf("Failed to get daemon PID from %s\n", path) 157 } 158 159 rawPid, err := strconv.ParseInt(string(b), 10, 32) 160 if err != nil { 161 c.Fatalf("Failed to parse pid from %s: %s\n", path, err) 162 } 163 164 daemonPid := int(rawPid) 165 if daemonPid > 0 { 166 testdaemon.SignalDaemonDump(daemonPid) 167 } 168 } 169 170 func (s *DockerSuite) TearDownTest(c *testing.T) { 171 testEnv.Clean(c) 172 } 173 174 type DockerRegistrySuite struct { 175 ds *DockerSuite 176 reg *registry.V2 177 d *daemon.Daemon 178 } 179 180 func (s *DockerRegistrySuite) OnTimeout(c *testing.T) { 181 s.d.DumpStackAndQuit() 182 } 183 184 func (s *DockerRegistrySuite) SetUpTest(c *testing.T) { 185 testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) 186 s.reg = registry.NewV2(c) 187 s.reg.WaitReady(c) 188 s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 189 } 190 191 func (s *DockerRegistrySuite) TearDownTest(c *testing.T) { 192 if s.reg != nil { 193 s.reg.Close() 194 } 195 if s.d != nil { 196 s.d.Stop(c) 197 } 198 s.ds.TearDownTest(c) 199 } 200 201 type DockerSchema1RegistrySuite struct { 202 ds *DockerSuite 203 reg *registry.V2 204 d *daemon.Daemon 205 } 206 207 func (s *DockerSchema1RegistrySuite) OnTimeout(c *testing.T) { 208 s.d.DumpStackAndQuit() 209 } 210 211 func (s *DockerSchema1RegistrySuite) SetUpTest(c *testing.T) { 212 testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64, testEnv.IsLocalDaemon) 213 s.reg = registry.NewV2(c, registry.Schema1) 214 s.reg.WaitReady(c) 215 s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 216 } 217 218 func (s *DockerSchema1RegistrySuite) TearDownTest(c *testing.T) { 219 if s.reg != nil { 220 s.reg.Close() 221 } 222 if s.d != nil { 223 s.d.Stop(c) 224 } 225 s.ds.TearDownTest(c) 226 } 227 228 type DockerRegistryAuthHtpasswdSuite struct { 229 ds *DockerSuite 230 reg *registry.V2 231 d *daemon.Daemon 232 } 233 234 func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *testing.T) { 235 s.d.DumpStackAndQuit() 236 } 237 238 func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *testing.T) { 239 testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) 240 s.reg = registry.NewV2(c, registry.Htpasswd) 241 s.reg.WaitReady(c) 242 s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 243 } 244 245 func (s *DockerRegistryAuthHtpasswdSuite) TearDownTest(c *testing.T) { 246 if s.reg != nil { 247 out, err := s.d.Cmd("logout", privateRegistryURL) 248 assert.NilError(c, err, out) 249 s.reg.Close() 250 } 251 if s.d != nil { 252 s.d.Stop(c) 253 } 254 s.ds.TearDownTest(c) 255 } 256 257 type DockerRegistryAuthTokenSuite struct { 258 ds *DockerSuite 259 reg *registry.V2 260 d *daemon.Daemon 261 } 262 263 func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *testing.T) { 264 s.d.DumpStackAndQuit() 265 } 266 267 func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *testing.T) { 268 testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) 269 s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 270 } 271 272 func (s *DockerRegistryAuthTokenSuite) TearDownTest(c *testing.T) { 273 if s.reg != nil { 274 out, err := s.d.Cmd("logout", privateRegistryURL) 275 assert.NilError(c, err, out) 276 s.reg.Close() 277 } 278 if s.d != nil { 279 s.d.Stop(c) 280 } 281 s.ds.TearDownTest(c) 282 } 283 284 func (s *DockerRegistryAuthTokenSuite) setupRegistryWithTokenService(c *testing.T, tokenURL string) { 285 if s == nil { 286 c.Fatal("registry suite isn't initialized") 287 } 288 s.reg = registry.NewV2(c, registry.Token(tokenURL)) 289 s.reg.WaitReady(c) 290 } 291 292 type DockerDaemonSuite struct { 293 ds *DockerSuite 294 d *daemon.Daemon 295 } 296 297 func (s *DockerDaemonSuite) OnTimeout(c *testing.T) { 298 s.d.DumpStackAndQuit() 299 } 300 301 func (s *DockerDaemonSuite) SetUpTest(c *testing.T) { 302 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 303 s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) 304 } 305 306 func (s *DockerDaemonSuite) TearDownTest(c *testing.T) { 307 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 308 if s.d != nil { 309 s.d.Stop(c) 310 } 311 s.ds.TearDownTest(c) 312 } 313 314 func (s *DockerDaemonSuite) TearDownSuite(c *testing.T) { 315 filepath.Walk(testdaemon.SockRoot, func(path string, fi os.FileInfo, err error) error { 316 if err != nil { 317 // ignore errors here 318 // not cleaning up sockets is not really an error 319 return nil 320 } 321 if fi.Mode() == os.ModeSocket { 322 syscall.Unlink(path) 323 } 324 return nil 325 }) 326 os.RemoveAll(testdaemon.SockRoot) 327 } 328 329 const defaultSwarmPort = 2477 330 331 type DockerSwarmSuite struct { 332 server *httptest.Server 333 ds *DockerSuite 334 daemonsLock sync.Mutex // protect access to daemons and portIndex 335 daemons []*daemon.Daemon 336 portIndex int 337 } 338 339 func (s *DockerSwarmSuite) OnTimeout(c *testing.T) { 340 s.daemonsLock.Lock() 341 defer s.daemonsLock.Unlock() 342 for _, d := range s.daemons { 343 d.DumpStackAndQuit() 344 } 345 } 346 347 func (s *DockerSwarmSuite) SetUpTest(c *testing.T) { 348 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) 349 } 350 351 func (s *DockerSwarmSuite) AddDaemon(c *testing.T, joinSwarm, manager bool) *daemon.Daemon { 352 c.Helper() 353 d := daemon.New(c, dockerBinary, dockerdBinary, 354 testdaemon.WithEnvironment(testEnv.Execution), 355 testdaemon.WithSwarmPort(defaultSwarmPort+s.portIndex), 356 ) 357 if joinSwarm { 358 if len(s.daemons) > 0 { 359 d.StartAndSwarmJoin(c, s.daemons[0].Daemon, manager) 360 } else { 361 d.StartAndSwarmInit(c) 362 } 363 } else { 364 d.StartNodeWithBusybox(c) 365 } 366 367 s.daemonsLock.Lock() 368 s.portIndex++ 369 s.daemons = append(s.daemons, d) 370 s.daemonsLock.Unlock() 371 372 return d 373 } 374 375 func (s *DockerSwarmSuite) TearDownTest(c *testing.T) { 376 testRequires(c, DaemonIsLinux) 377 s.daemonsLock.Lock() 378 for _, d := range s.daemons { 379 if d != nil { 380 d.Stop(c) 381 d.Cleanup(c) 382 } 383 } 384 s.daemons = nil 385 s.portIndex = 0 386 s.daemonsLock.Unlock() 387 s.ds.TearDownTest(c) 388 } 389 390 type DockerPluginSuite struct { 391 ds *DockerSuite 392 registry *registry.V2 393 } 394 395 func (ps *DockerPluginSuite) registryHost() string { 396 return privateRegistryURL 397 } 398 399 func (ps *DockerPluginSuite) getPluginRepo() string { 400 return path.Join(ps.registryHost(), "plugin", "basic") 401 } 402 func (ps *DockerPluginSuite) getPluginRepoWithTag() string { 403 return ps.getPluginRepo() + ":" + "latest" 404 } 405 406 func (ps *DockerPluginSuite) SetUpSuite(c *testing.T) { 407 testRequires(c, DaemonIsLinux, RegistryHosting) 408 ps.registry = registry.NewV2(c) 409 ps.registry.WaitReady(c) 410 411 ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) 412 defer cancel() 413 414 err := plugin.CreateInRegistry(ctx, ps.getPluginRepo(), nil) 415 assert.NilError(c, err, "failed to create plugin") 416 } 417 418 func (ps *DockerPluginSuite) TearDownSuite(c *testing.T) { 419 if ps.registry != nil { 420 ps.registry.Close() 421 } 422 } 423 424 func (ps *DockerPluginSuite) TearDownTest(c *testing.T) { 425 ps.ds.TearDownTest(c) 426 } 427 428 func (ps *DockerPluginSuite) OnTimeout(c *testing.T) { 429 ps.ds.OnTimeout(c) 430 }