check_test.go 8.9 KB

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