runtime_test.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. package docker
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/dotcloud/docker"
  6. "github.com/dotcloud/docker/engine"
  7. "github.com/dotcloud/docker/nat"
  8. "github.com/dotcloud/docker/runconfig"
  9. "github.com/dotcloud/docker/sysinit"
  10. "github.com/dotcloud/docker/utils"
  11. "io"
  12. "log"
  13. "net"
  14. "net/url"
  15. "os"
  16. "path/filepath"
  17. "runtime"
  18. "strconv"
  19. "strings"
  20. "syscall"
  21. "testing"
  22. "time"
  23. )
  24. const (
  25. unitTestImageName = "docker-test-image"
  26. unitTestImageID = "83599e29c455eb719f77d799bc7c51521b9551972f5a850d7ad265bc1b5292f6" // 1.0
  27. unitTestImageIDShort = "83599e29c455"
  28. unitTestNetworkBridge = "testdockbr0"
  29. unitTestStoreBase = "/var/lib/docker/unit-tests"
  30. testDaemonAddr = "127.0.0.1:4270"
  31. testDaemonProto = "tcp"
  32. )
  33. var (
  34. // FIXME: globalRuntime is deprecated by globalEngine. All tests should be converted.
  35. globalRuntime *docker.Runtime
  36. globalEngine *engine.Engine
  37. startFds int
  38. startGoroutines int
  39. )
  40. // FIXME: nuke() is deprecated by Runtime.Nuke()
  41. func nuke(runtime *docker.Runtime) error {
  42. return runtime.Nuke()
  43. }
  44. // FIXME: cleanup and nuke are redundant.
  45. func cleanup(eng *engine.Engine, t *testing.T) error {
  46. runtime := mkRuntimeFromEngine(eng, t)
  47. for _, container := range runtime.List() {
  48. container.Kill()
  49. runtime.Destroy(container)
  50. }
  51. job := eng.Job("images")
  52. images, err := job.Stdout.AddTable()
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. if err := job.Run(); err != nil {
  57. t.Fatal(err)
  58. }
  59. for _, image := range images.Data {
  60. if image.Get("Id") != unitTestImageID {
  61. eng.Job("image_delete", image.Get("Id")).Run()
  62. }
  63. }
  64. return nil
  65. }
  66. func layerArchive(tarfile string) (io.Reader, error) {
  67. // FIXME: need to close f somewhere
  68. f, err := os.Open(tarfile)
  69. if err != nil {
  70. return nil, err
  71. }
  72. return f, nil
  73. }
  74. func init() {
  75. // Always use the same driver (vfs) for all integration tests.
  76. // To test other drivers, we need a dedicated driver validation suite.
  77. os.Setenv("DOCKER_DRIVER", "vfs")
  78. os.Setenv("TEST", "1")
  79. // Hack to run sys init during unit testing
  80. if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
  81. sysinit.SysInit()
  82. return
  83. }
  84. if uid := syscall.Geteuid(); uid != 0 {
  85. log.Fatal("docker tests need to be run as root")
  86. }
  87. // Copy dockerinit into our current testing directory, if provided (so we can test a separate dockerinit binary)
  88. if dockerinit := os.Getenv("TEST_DOCKERINIT_PATH"); dockerinit != "" {
  89. src, err := os.Open(dockerinit)
  90. if err != nil {
  91. log.Fatalf("Unable to open TEST_DOCKERINIT_PATH: %s\n", err)
  92. }
  93. defer src.Close()
  94. dst, err := os.OpenFile(filepath.Join(filepath.Dir(utils.SelfPath()), "dockerinit"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0555)
  95. if err != nil {
  96. log.Fatalf("Unable to create dockerinit in test directory: %s\n", err)
  97. }
  98. defer dst.Close()
  99. if _, err := io.Copy(dst, src); err != nil {
  100. log.Fatalf("Unable to copy dockerinit to TEST_DOCKERINIT_PATH: %s\n", err)
  101. }
  102. dst.Close()
  103. src.Close()
  104. }
  105. // Setup the base runtime, which will be duplicated for each test.
  106. // (no tests are run directly in the base)
  107. setupBaseImage()
  108. // Create the "global runtime" with a long-running daemon for integration tests
  109. spawnGlobalDaemon()
  110. startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine()
  111. }
  112. func setupBaseImage() {
  113. eng, err := engine.New(unitTestStoreBase)
  114. if err != nil {
  115. log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err)
  116. }
  117. job := eng.Job("initserver")
  118. job.Setenv("Root", unitTestStoreBase)
  119. job.SetenvBool("Autorestart", false)
  120. job.Setenv("BridgeIface", unitTestNetworkBridge)
  121. if err := job.Run(); err != nil {
  122. log.Fatalf("Unable to create a runtime for tests: %s", err)
  123. }
  124. job = eng.Job("inspect", unitTestImageName, "image")
  125. img, _ := job.Stdout.AddEnv()
  126. // If the unit test is not found, try to download it.
  127. if err := job.Run(); err != nil || img.Get("id") != unitTestImageID {
  128. // Retrieve the Image
  129. job = eng.Job("pull", unitTestImageName)
  130. job.Stdout.Add(utils.NopWriteCloser(os.Stdout))
  131. if err := job.Run(); err != nil {
  132. log.Fatalf("Unable to pull the test image: %s", err)
  133. }
  134. }
  135. }
  136. func spawnGlobalDaemon() {
  137. if globalRuntime != nil {
  138. utils.Debugf("Global runtime already exists. Skipping.")
  139. return
  140. }
  141. t := log.New(os.Stderr, "", 0)
  142. eng := NewTestEngine(t)
  143. globalEngine = eng
  144. globalRuntime = mkRuntimeFromEngine(eng, t)
  145. // Spawn a Daemon
  146. go func() {
  147. utils.Debugf("Spawning global daemon for integration tests")
  148. listenURL := &url.URL{
  149. Scheme: testDaemonProto,
  150. Host: testDaemonAddr,
  151. }
  152. job := eng.Job("serveapi", listenURL.String())
  153. job.SetenvBool("Logging", true)
  154. if err := job.Run(); err != nil {
  155. log.Fatalf("Unable to spawn the test daemon: %s", err)
  156. }
  157. }()
  158. // Give some time to ListenAndServer to actually start
  159. // FIXME: use inmem transports instead of tcp
  160. time.Sleep(time.Second)
  161. }
  162. // FIXME: test that ImagePull(json=true) send correct json output
  163. func GetTestImage(runtime *docker.Runtime) *docker.Image {
  164. imgs, err := runtime.Graph().Map()
  165. if err != nil {
  166. log.Fatalf("Unable to get the test image: %s", err)
  167. }
  168. for _, image := range imgs {
  169. if image.ID == unitTestImageID {
  170. return image
  171. }
  172. }
  173. log.Fatalf("Test image %v not found in %s: %s", unitTestImageID, runtime.Graph().Root, imgs)
  174. return nil
  175. }
  176. func TestRuntimeCreate(t *testing.T) {
  177. runtime := mkRuntime(t)
  178. defer nuke(runtime)
  179. // Make sure we start we 0 containers
  180. if len(runtime.List()) != 0 {
  181. t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
  182. }
  183. container, _, err := runtime.Create(&runconfig.Config{
  184. Image: GetTestImage(runtime).ID,
  185. Cmd: []string{"ls", "-al"},
  186. },
  187. "",
  188. )
  189. if err != nil {
  190. t.Fatal(err)
  191. }
  192. defer func() {
  193. if err := runtime.Destroy(container); err != nil {
  194. t.Error(err)
  195. }
  196. }()
  197. // Make sure we can find the newly created container with List()
  198. if len(runtime.List()) != 1 {
  199. t.Errorf("Expected 1 container, %v found", len(runtime.List()))
  200. }
  201. // Make sure the container List() returns is the right one
  202. if runtime.List()[0].ID != container.ID {
  203. t.Errorf("Unexpected container %v returned by List", runtime.List()[0])
  204. }
  205. // Make sure we can get the container with Get()
  206. if runtime.Get(container.ID) == nil {
  207. t.Errorf("Unable to get newly created container")
  208. }
  209. // Make sure it is the right container
  210. if runtime.Get(container.ID) != container {
  211. t.Errorf("Get() returned the wrong container")
  212. }
  213. // Make sure Exists returns it as existing
  214. if !runtime.Exists(container.ID) {
  215. t.Errorf("Exists() returned false for a newly created container")
  216. }
  217. // Test that conflict error displays correct details
  218. testContainer, _, _ := runtime.Create(
  219. &runconfig.Config{
  220. Image: GetTestImage(runtime).ID,
  221. Cmd: []string{"ls", "-al"},
  222. },
  223. "conflictname",
  224. )
  225. if _, _, err := runtime.Create(&runconfig.Config{Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}}, testContainer.Name); err == nil || !strings.Contains(err.Error(), utils.TruncateID(testContainer.ID)) {
  226. t.Fatalf("Name conflict error doesn't include the correct short id. Message was: %s", err.Error())
  227. }
  228. // Make sure create with bad parameters returns an error
  229. if _, _, err = runtime.Create(&runconfig.Config{Image: GetTestImage(runtime).ID}, ""); err == nil {
  230. t.Fatal("Builder.Create should throw an error when Cmd is missing")
  231. }
  232. if _, _, err := runtime.Create(
  233. &runconfig.Config{
  234. Image: GetTestImage(runtime).ID,
  235. Cmd: []string{},
  236. },
  237. "",
  238. ); err == nil {
  239. t.Fatal("Builder.Create should throw an error when Cmd is empty")
  240. }
  241. config := &runconfig.Config{
  242. Image: GetTestImage(runtime).ID,
  243. Cmd: []string{"/bin/ls"},
  244. PortSpecs: []string{"80"},
  245. }
  246. container, _, err = runtime.Create(config, "")
  247. _, err = runtime.Commit(container, "testrepo", "testtag", "", "", config)
  248. if err != nil {
  249. t.Error(err)
  250. }
  251. // test expose 80:8000
  252. container, warnings, err := runtime.Create(&runconfig.Config{
  253. Image: GetTestImage(runtime).ID,
  254. Cmd: []string{"ls", "-al"},
  255. PortSpecs: []string{"80:8000"},
  256. },
  257. "",
  258. )
  259. if err != nil {
  260. t.Fatal(err)
  261. }
  262. if warnings == nil || len(warnings) != 1 {
  263. t.Error("Expected a warning, got none")
  264. }
  265. }
  266. func TestDestroy(t *testing.T) {
  267. runtime := mkRuntime(t)
  268. defer nuke(runtime)
  269. container, _, err := runtime.Create(&runconfig.Config{
  270. Image: GetTestImage(runtime).ID,
  271. Cmd: []string{"ls", "-al"},
  272. }, "")
  273. if err != nil {
  274. t.Fatal(err)
  275. }
  276. // Destroy
  277. if err := runtime.Destroy(container); err != nil {
  278. t.Error(err)
  279. }
  280. // Make sure runtime.Exists() behaves correctly
  281. if runtime.Exists("test_destroy") {
  282. t.Errorf("Exists() returned true")
  283. }
  284. // Make sure runtime.List() doesn't list the destroyed container
  285. if len(runtime.List()) != 0 {
  286. t.Errorf("Expected 0 container, %v found", len(runtime.List()))
  287. }
  288. // Make sure runtime.Get() refuses to return the unexisting container
  289. if runtime.Get(container.ID) != nil {
  290. t.Errorf("Unable to get newly created container")
  291. }
  292. // Test double destroy
  293. if err := runtime.Destroy(container); err == nil {
  294. // It should have failed
  295. t.Errorf("Double destroy did not fail")
  296. }
  297. }
  298. func TestGet(t *testing.T) {
  299. runtime := mkRuntime(t)
  300. defer nuke(runtime)
  301. container1, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t)
  302. defer runtime.Destroy(container1)
  303. container2, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t)
  304. defer runtime.Destroy(container2)
  305. container3, _, _ := mkContainer(runtime, []string{"_", "ls", "-al"}, t)
  306. defer runtime.Destroy(container3)
  307. if runtime.Get(container1.ID) != container1 {
  308. t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.ID), container1)
  309. }
  310. if runtime.Get(container2.ID) != container2 {
  311. t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.ID), container2)
  312. }
  313. if runtime.Get(container3.ID) != container3 {
  314. t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.ID), container3)
  315. }
  316. }
  317. func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *docker.Container, string) {
  318. var (
  319. err error
  320. id string
  321. strPort string
  322. eng = NewTestEngine(t)
  323. runtime = mkRuntimeFromEngine(eng, t)
  324. port = 5554
  325. p nat.Port
  326. )
  327. defer func() {
  328. if err != nil {
  329. runtime.Nuke()
  330. }
  331. }()
  332. for {
  333. port += 1
  334. strPort = strconv.Itoa(port)
  335. var cmd string
  336. if proto == "tcp" {
  337. cmd = "socat TCP-LISTEN:" + strPort + ",reuseaddr,fork EXEC:/bin/cat"
  338. } else if proto == "udp" {
  339. cmd = "socat UDP-RECVFROM:" + strPort + ",fork EXEC:/bin/cat"
  340. } else {
  341. t.Fatal(fmt.Errorf("Unknown protocol %v", proto))
  342. }
  343. ep := make(map[nat.Port]struct{}, 1)
  344. p = nat.Port(fmt.Sprintf("%s/%s", strPort, proto))
  345. ep[p] = struct{}{}
  346. jobCreate := eng.Job("create")
  347. jobCreate.Setenv("Image", unitTestImageID)
  348. jobCreate.SetenvList("Cmd", []string{"sh", "-c", cmd})
  349. jobCreate.SetenvList("PortSpecs", []string{fmt.Sprintf("%s/%s", strPort, proto)})
  350. jobCreate.SetenvJson("ExposedPorts", ep)
  351. jobCreate.Stdout.AddString(&id)
  352. if err := jobCreate.Run(); err != nil {
  353. t.Fatal(err)
  354. }
  355. // FIXME: this relies on the undocumented behavior of runtime.Create
  356. // which will return a nil error AND container if the exposed ports
  357. // are invalid. That behavior should be fixed!
  358. if id != "" {
  359. break
  360. }
  361. t.Logf("Port %v already in use, trying another one", strPort)
  362. }
  363. jobStart := eng.Job("start", id)
  364. portBindings := make(map[nat.Port][]nat.PortBinding)
  365. portBindings[p] = []nat.PortBinding{
  366. {},
  367. }
  368. if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil {
  369. t.Fatal(err)
  370. }
  371. if err := jobStart.Run(); err != nil {
  372. t.Fatal(err)
  373. }
  374. container := runtime.Get(id)
  375. if container == nil {
  376. t.Fatalf("Couldn't fetch test container %s", id)
  377. }
  378. setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
  379. for !container.State.IsRunning() {
  380. time.Sleep(10 * time.Millisecond)
  381. }
  382. })
  383. // Even if the state is running, lets give some time to lxc to spawn the process
  384. container.WaitTimeout(500 * time.Millisecond)
  385. strPort = container.NetworkSettings.Ports[p][0].HostPort
  386. return runtime, container, strPort
  387. }
  388. // Run a container with a TCP port allocated, and test that it can receive connections on localhost
  389. func TestAllocateTCPPortLocalhost(t *testing.T) {
  390. runtime, container, port := startEchoServerContainer(t, "tcp")
  391. defer nuke(runtime)
  392. defer container.Kill()
  393. for i := 0; i != 10; i++ {
  394. conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", port))
  395. if err != nil {
  396. t.Fatal(err)
  397. }
  398. defer conn.Close()
  399. input := bytes.NewBufferString("well hello there\n")
  400. _, err = conn.Write(input.Bytes())
  401. if err != nil {
  402. t.Fatal(err)
  403. }
  404. buf := make([]byte, 16)
  405. read := 0
  406. conn.SetReadDeadline(time.Now().Add(3 * time.Second))
  407. read, err = conn.Read(buf)
  408. if err != nil {
  409. if err, ok := err.(*net.OpError); ok {
  410. if err.Err == syscall.ECONNRESET {
  411. t.Logf("Connection reset by the proxy, socat is probably not listening yet, trying again in a sec")
  412. conn.Close()
  413. time.Sleep(time.Second)
  414. continue
  415. }
  416. if err.Timeout() {
  417. t.Log("Timeout, trying again")
  418. conn.Close()
  419. continue
  420. }
  421. }
  422. t.Fatal(err)
  423. }
  424. output := string(buf[:read])
  425. if !strings.Contains(output, "well hello there") {
  426. t.Fatal(fmt.Errorf("[%v] doesn't contain [well hello there]", output))
  427. } else {
  428. return
  429. }
  430. }
  431. t.Fatal("No reply from the container")
  432. }
  433. // Run a container with an UDP port allocated, and test that it can receive connections on localhost
  434. func TestAllocateUDPPortLocalhost(t *testing.T) {
  435. runtime, container, port := startEchoServerContainer(t, "udp")
  436. defer nuke(runtime)
  437. defer container.Kill()
  438. conn, err := net.Dial("udp", fmt.Sprintf("localhost:%v", port))
  439. if err != nil {
  440. t.Fatal(err)
  441. }
  442. defer conn.Close()
  443. input := bytes.NewBufferString("well hello there\n")
  444. buf := make([]byte, 16)
  445. // Try for a minute, for some reason the select in socat may take ages
  446. // to return even though everything on the path seems fine (i.e: the
  447. // UDPProxy forwards the traffic correctly and you can see the packets
  448. // on the interface from within the container).
  449. for i := 0; i != 120; i++ {
  450. _, err := conn.Write(input.Bytes())
  451. if err != nil {
  452. t.Fatal(err)
  453. }
  454. conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
  455. read, err := conn.Read(buf)
  456. if err == nil {
  457. output := string(buf[:read])
  458. if strings.Contains(output, "well hello there") {
  459. return
  460. }
  461. }
  462. }
  463. t.Fatal("No reply from the container")
  464. }
  465. func TestRestore(t *testing.T) {
  466. eng := NewTestEngine(t)
  467. runtime1 := mkRuntimeFromEngine(eng, t)
  468. defer runtime1.Nuke()
  469. // Create a container with one instance of docker
  470. container1, _, _ := mkContainer(runtime1, []string{"_", "ls", "-al"}, t)
  471. defer runtime1.Destroy(container1)
  472. // Create a second container meant to be killed
  473. container2, _, _ := mkContainer(runtime1, []string{"-i", "_", "/bin/cat"}, t)
  474. defer runtime1.Destroy(container2)
  475. // Start the container non blocking
  476. if err := container2.Start(); err != nil {
  477. t.Fatal(err)
  478. }
  479. if !container2.State.IsRunning() {
  480. t.Fatalf("Container %v should appear as running but isn't", container2.ID)
  481. }
  482. // Simulate a crash/manual quit of dockerd: process dies, states stays 'Running'
  483. cStdin, _ := container2.StdinPipe()
  484. cStdin.Close()
  485. if err := container2.WaitTimeout(2 * time.Second); err != nil {
  486. t.Fatal(err)
  487. }
  488. container2.State.SetRunning(42)
  489. container2.ToDisk()
  490. if len(runtime1.List()) != 2 {
  491. t.Errorf("Expected 2 container, %v found", len(runtime1.List()))
  492. }
  493. if err := container1.Run(); err != nil {
  494. t.Fatal(err)
  495. }
  496. if !container2.State.IsRunning() {
  497. t.Fatalf("Container %v should appear as running but isn't", container2.ID)
  498. }
  499. // Here are are simulating a docker restart - that is, reloading all containers
  500. // from scratch
  501. root := eng.Root()
  502. eng, err := engine.New(root)
  503. if err != nil {
  504. t.Fatal(err)
  505. }
  506. job := eng.Job("initserver")
  507. job.Setenv("Root", eng.Root())
  508. job.SetenvBool("Autorestart", false)
  509. if err := job.Run(); err != nil {
  510. t.Fatal(err)
  511. }
  512. runtime2 := mkRuntimeFromEngine(eng, t)
  513. if len(runtime2.List()) != 2 {
  514. t.Errorf("Expected 2 container, %v found", len(runtime2.List()))
  515. }
  516. runningCount := 0
  517. for _, c := range runtime2.List() {
  518. if c.State.IsRunning() {
  519. t.Errorf("Running container found: %v (%v)", c.ID, c.Path)
  520. runningCount++
  521. }
  522. }
  523. if runningCount != 0 {
  524. t.Fatalf("Expected 0 container alive, %d found", runningCount)
  525. }
  526. container3 := runtime2.Get(container1.ID)
  527. if container3 == nil {
  528. t.Fatal("Unable to Get container")
  529. }
  530. if err := container3.Run(); err != nil {
  531. t.Fatal(err)
  532. }
  533. container2.State.SetStopped(0)
  534. }
  535. func TestReloadContainerLinks(t *testing.T) {
  536. // FIXME: here we don't use NewTestEngine because it calls initserver with Autorestart=false,
  537. // and we want to set it to true.
  538. root, err := newTestDirectory(unitTestStoreBase)
  539. if err != nil {
  540. t.Fatal(err)
  541. }
  542. eng, err := engine.New(root)
  543. if err != nil {
  544. t.Fatal(err)
  545. }
  546. job := eng.Job("initserver")
  547. job.Setenv("Root", eng.Root())
  548. job.SetenvBool("Autorestart", true)
  549. if err := job.Run(); err != nil {
  550. t.Fatal(err)
  551. }
  552. runtime1 := mkRuntimeFromEngine(eng, t)
  553. defer nuke(runtime1)
  554. // Create a container with one instance of docker
  555. container1, _, _ := mkContainer(runtime1, []string{"-i", "_", "/bin/sh"}, t)
  556. defer runtime1.Destroy(container1)
  557. // Create a second container meant to be killed
  558. container2, _, _ := mkContainer(runtime1, []string{"-i", "_", "/bin/cat"}, t)
  559. defer runtime1.Destroy(container2)
  560. // Start the container non blocking
  561. if err := container2.Start(); err != nil {
  562. t.Fatal(err)
  563. }
  564. // Add a link to container 2
  565. // FIXME @shykes: setting hostConfig.Links seems redundant with calling RegisterLink().
  566. // Why do we need it @crosbymichael?
  567. // container1.hostConfig.Links = []string{"/" + container2.ID + ":first"}
  568. if err := runtime1.RegisterLink(container1, container2, "first"); err != nil {
  569. t.Fatal(err)
  570. }
  571. if err := container1.Start(); err != nil {
  572. t.Fatal(err)
  573. }
  574. if !container2.State.IsRunning() {
  575. t.Fatalf("Container %v should appear as running but isn't", container2.ID)
  576. }
  577. if !container1.State.IsRunning() {
  578. t.Fatalf("Container %s should appear as running but isn't", container1.ID)
  579. }
  580. if len(runtime1.List()) != 2 {
  581. t.Errorf("Expected 2 container, %v found", len(runtime1.List()))
  582. }
  583. // Here are are simulating a docker restart - that is, reloading all containers
  584. // from scratch
  585. eng, err = engine.New(root)
  586. if err != nil {
  587. t.Fatal(err)
  588. }
  589. job = eng.Job("initserver")
  590. job.Setenv("Root", eng.Root())
  591. job.SetenvBool("Autorestart", false)
  592. if err := job.Run(); err != nil {
  593. t.Fatal(err)
  594. }
  595. runtime2 := mkRuntimeFromEngine(eng, t)
  596. if len(runtime2.List()) != 2 {
  597. t.Errorf("Expected 2 container, %v found", len(runtime2.List()))
  598. }
  599. runningCount := 0
  600. for _, c := range runtime2.List() {
  601. if c.State.IsRunning() {
  602. runningCount++
  603. }
  604. }
  605. if runningCount != 2 {
  606. t.Fatalf("Expected 2 container alive, %d found", runningCount)
  607. }
  608. // FIXME: we no longer test if containers were registered in the right order,
  609. // because there is no public
  610. // Make sure container 2 ( the child of container 1 ) was registered and started first
  611. // with the runtime
  612. //
  613. containers := runtime2.List()
  614. if len(containers) == 0 {
  615. t.Fatalf("Runtime has no containers")
  616. }
  617. first := containers[0]
  618. if first.ID != container2.ID {
  619. t.Fatalf("Container 2 %s should be registered first in the runtime", container2.ID)
  620. }
  621. // Verify that the link is still registered in the runtime
  622. if c := runtime2.Get(container1.Name); c == nil {
  623. t.Fatal("Named container is no longer registered after restart")
  624. }
  625. }
  626. func TestDefaultContainerName(t *testing.T) {
  627. eng := NewTestEngine(t)
  628. runtime := mkRuntimeFromEngine(eng, t)
  629. defer nuke(runtime)
  630. config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
  631. if err != nil {
  632. t.Fatal(err)
  633. }
  634. container := runtime.Get(createNamedTestContainer(eng, config, t, "some_name"))
  635. containerID := container.ID
  636. if container.Name != "/some_name" {
  637. t.Fatalf("Expect /some_name got %s", container.Name)
  638. }
  639. if c := runtime.Get("/some_name"); c == nil {
  640. t.Fatalf("Couldn't retrieve test container as /some_name")
  641. } else if c.ID != containerID {
  642. t.Fatalf("Container /some_name has ID %s instead of %s", c.ID, containerID)
  643. }
  644. }
  645. func TestRandomContainerName(t *testing.T) {
  646. eng := NewTestEngine(t)
  647. runtime := mkRuntimeFromEngine(eng, t)
  648. defer nuke(runtime)
  649. config, _, _, err := runconfig.Parse([]string{GetTestImage(runtime).ID, "echo test"}, nil)
  650. if err != nil {
  651. t.Fatal(err)
  652. }
  653. container := runtime.Get(createTestContainer(eng, config, t))
  654. containerID := container.ID
  655. if container.Name == "" {
  656. t.Fatalf("Expected not empty container name")
  657. }
  658. if c := runtime.Get(container.Name); c == nil {
  659. log.Fatalf("Could not lookup container %s by its name", container.Name)
  660. } else if c.ID != containerID {
  661. log.Fatalf("Looking up container name %s returned id %s instead of %s", container.Name, c.ID, containerID)
  662. }
  663. }
  664. func TestContainerNameValidation(t *testing.T) {
  665. eng := NewTestEngine(t)
  666. runtime := mkRuntimeFromEngine(eng, t)
  667. defer nuke(runtime)
  668. for _, test := range []struct {
  669. Name string
  670. Valid bool
  671. }{
  672. {"abc-123_AAA.1", true},
  673. {"\000asdf", false},
  674. } {
  675. config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
  676. if err != nil {
  677. if !test.Valid {
  678. continue
  679. }
  680. t.Fatal(err)
  681. }
  682. var shortID string
  683. job := eng.Job("create", test.Name)
  684. if err := job.ImportEnv(config); err != nil {
  685. t.Fatal(err)
  686. }
  687. job.Stdout.AddString(&shortID)
  688. if err := job.Run(); err != nil {
  689. if !test.Valid {
  690. continue
  691. }
  692. t.Fatal(err)
  693. }
  694. container := runtime.Get(shortID)
  695. if container.Name != "/"+test.Name {
  696. t.Fatalf("Expect /%s got %s", test.Name, container.Name)
  697. }
  698. if c := runtime.Get("/" + test.Name); c == nil {
  699. t.Fatalf("Couldn't retrieve test container as /%s", test.Name)
  700. } else if c.ID != container.ID {
  701. t.Fatalf("Container /%s has ID %s instead of %s", test.Name, c.ID, container.ID)
  702. }
  703. }
  704. }
  705. func TestLinkChildContainer(t *testing.T) {
  706. eng := NewTestEngine(t)
  707. runtime := mkRuntimeFromEngine(eng, t)
  708. defer nuke(runtime)
  709. config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
  710. if err != nil {
  711. t.Fatal(err)
  712. }
  713. container := runtime.Get(createNamedTestContainer(eng, config, t, "/webapp"))
  714. webapp, err := runtime.GetByName("/webapp")
  715. if err != nil {
  716. t.Fatal(err)
  717. }
  718. if webapp.ID != container.ID {
  719. t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
  720. }
  721. config, _, _, err = runconfig.Parse([]string{GetTestImage(runtime).ID, "echo test"}, nil)
  722. if err != nil {
  723. t.Fatal(err)
  724. }
  725. childContainer := runtime.Get(createTestContainer(eng, config, t))
  726. if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil {
  727. t.Fatal(err)
  728. }
  729. // Get the child by it's new name
  730. db, err := runtime.GetByName("/webapp/db")
  731. if err != nil {
  732. t.Fatal(err)
  733. }
  734. if db.ID != childContainer.ID {
  735. t.Fatalf("Expect db id to match container id: %s != %s", db.ID, childContainer.ID)
  736. }
  737. }
  738. func TestGetAllChildren(t *testing.T) {
  739. eng := NewTestEngine(t)
  740. runtime := mkRuntimeFromEngine(eng, t)
  741. defer nuke(runtime)
  742. config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
  743. if err != nil {
  744. t.Fatal(err)
  745. }
  746. container := runtime.Get(createNamedTestContainer(eng, config, t, "/webapp"))
  747. webapp, err := runtime.GetByName("/webapp")
  748. if err != nil {
  749. t.Fatal(err)
  750. }
  751. if webapp.ID != container.ID {
  752. t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
  753. }
  754. config, _, _, err = runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
  755. if err != nil {
  756. t.Fatal(err)
  757. }
  758. childContainer := runtime.Get(createTestContainer(eng, config, t))
  759. if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil {
  760. t.Fatal(err)
  761. }
  762. children, err := runtime.Children("/webapp")
  763. if err != nil {
  764. t.Fatal(err)
  765. }
  766. if children == nil {
  767. t.Fatal("Children should not be nil")
  768. }
  769. if len(children) == 0 {
  770. t.Fatal("Children should not be empty")
  771. }
  772. for key, value := range children {
  773. if key != "/webapp/db" {
  774. t.Fatalf("Expected /webapp/db got %s", key)
  775. }
  776. if value.ID != childContainer.ID {
  777. t.Fatalf("Expected id %s got %s", childContainer.ID, value.ID)
  778. }
  779. }
  780. }
  781. func TestDestroyWithInitLayer(t *testing.T) {
  782. runtime := mkRuntime(t)
  783. defer nuke(runtime)
  784. container, _, err := runtime.Create(&runconfig.Config{
  785. Image: GetTestImage(runtime).ID,
  786. Cmd: []string{"ls", "-al"},
  787. }, "")
  788. if err != nil {
  789. t.Fatal(err)
  790. }
  791. // Destroy
  792. if err := runtime.Destroy(container); err != nil {
  793. t.Fatal(err)
  794. }
  795. // Make sure runtime.Exists() behaves correctly
  796. if runtime.Exists("test_destroy") {
  797. t.Fatalf("Exists() returned true")
  798. }
  799. // Make sure runtime.List() doesn't list the destroyed container
  800. if len(runtime.List()) != 0 {
  801. t.Fatalf("Expected 0 container, %v found", len(runtime.List()))
  802. }
  803. driver := runtime.Graph().Driver()
  804. // Make sure that the container does not exist in the driver
  805. if _, err := driver.Get(container.ID); err == nil {
  806. t.Fatal("Conttainer should not exist in the driver")
  807. }
  808. // Make sure that the init layer is removed from the driver
  809. if _, err := driver.Get(fmt.Sprintf("%s-init", container.ID)); err == nil {
  810. t.Fatal("Container's init layer should not exist in the driver")
  811. }
  812. }