github.com/ctmnz/docker@v1.6.0-rc3/integration-cli/docker_cli_daemon_test.go (about)

     1  // +build daemon
     2  
     3  package main
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/docker/libtrust"
    17  )
    18  
    19  func TestDaemonRestartWithRunningContainersPorts(t *testing.T) {
    20  	d := NewDaemon(t)
    21  	if err := d.StartWithBusybox(); err != nil {
    22  		t.Fatalf("Could not start daemon with busybox: %v", err)
    23  	}
    24  	defer d.Stop()
    25  
    26  	if out, err := d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil {
    27  		t.Fatalf("Could not run top1: err=%v\n%s", err, out)
    28  	}
    29  	// --restart=no by default
    30  	if out, err := d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil {
    31  		t.Fatalf("Could not run top2: err=%v\n%s", err, out)
    32  	}
    33  
    34  	testRun := func(m map[string]bool, prefix string) {
    35  		var format string
    36  		for c, shouldRun := range m {
    37  			out, err := d.Cmd("ps")
    38  			if err != nil {
    39  				t.Fatalf("Could not run ps: err=%v\n%q", err, out)
    40  			}
    41  			if shouldRun {
    42  				format = "%scontainer %q is not running"
    43  			} else {
    44  				format = "%scontainer %q is running"
    45  			}
    46  			if shouldRun != strings.Contains(out, c) {
    47  				t.Fatalf(format, prefix, c)
    48  			}
    49  		}
    50  	}
    51  
    52  	testRun(map[string]bool{"top1": true, "top2": true}, "")
    53  
    54  	if err := d.Restart(); err != nil {
    55  		t.Fatalf("Could not restart daemon: %v", err)
    56  	}
    57  
    58  	testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ")
    59  
    60  	logDone("daemon - running containers on daemon restart")
    61  }
    62  
    63  func TestDaemonRestartWithVolumesRefs(t *testing.T) {
    64  	d := NewDaemon(t)
    65  	if err := d.StartWithBusybox(); err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	defer d.Stop()
    69  
    70  	if out, err := d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil {
    71  		t.Fatal(err, out)
    72  	}
    73  	if err := d.Restart(); err != nil {
    74  		t.Fatal(err)
    75  	}
    76  	if _, err := d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	if out, err := d.Cmd("rm", "-fv", "volrestarttest2"); err != nil {
    80  		t.Fatal(err, out)
    81  	}
    82  	v, err := d.Cmd("inspect", "--format", "{{ json .Volumes }}", "volrestarttest1")
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	volumes := make(map[string]string)
    87  	json.Unmarshal([]byte(v), &volumes)
    88  	if _, err := os.Stat(volumes["/foo"]); err != nil {
    89  		t.Fatalf("Expected volume to exist: %s - %s", volumes["/foo"], err)
    90  	}
    91  
    92  	logDone("daemon - volume refs are restored")
    93  }
    94  
    95  func TestDaemonStartIptablesFalse(t *testing.T) {
    96  	d := NewDaemon(t)
    97  	if err := d.Start("--iptables=false"); err != nil {
    98  		t.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err)
    99  	}
   100  	d.Stop()
   101  
   102  	logDone("daemon - started daemon with iptables=false")
   103  }
   104  
   105  // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and
   106  // no longer has an IP associated, we should gracefully handle that case and associate
   107  // an IP with it rather than fail daemon start
   108  func TestDaemonStartBridgeWithoutIPAssociation(t *testing.T) {
   109  	d := NewDaemon(t)
   110  	// rather than depending on brctl commands to verify docker0 is created and up
   111  	// let's start the daemon and stop it, and then make a modification to run the
   112  	// actual test
   113  	if err := d.Start(); err != nil {
   114  		t.Fatalf("Could not start daemon: %v", err)
   115  	}
   116  	if err := d.Stop(); err != nil {
   117  		t.Fatalf("Could not stop daemon: %v", err)
   118  	}
   119  
   120  	// now we will remove the ip from docker0 and then try starting the daemon
   121  	ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0")
   122  	stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd)
   123  	if err != nil {
   124  		t.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr)
   125  	}
   126  
   127  	if err := d.Start(); err != nil {
   128  		warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix"
   129  		t.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning)
   130  	}
   131  
   132  	// cleanup - stop the daemon if test passed
   133  	if err := d.Stop(); err != nil {
   134  		t.Fatalf("Could not stop daemon: %v", err)
   135  	}
   136  
   137  	logDone("daemon - successful daemon start when bridge has no IP association")
   138  }
   139  
   140  func TestDaemonIptablesClean(t *testing.T) {
   141  	defer deleteAllContainers()
   142  
   143  	d := NewDaemon(t)
   144  	if err := d.StartWithBusybox(); err != nil {
   145  		t.Fatalf("Could not start daemon with busybox: %v", err)
   146  	}
   147  	defer d.Stop()
   148  
   149  	if out, err := d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
   150  		t.Fatalf("Could not run top: %s, %v", out, err)
   151  	}
   152  
   153  	// get output from iptables with container running
   154  	ipTablesSearchString := "tcp dpt:80"
   155  	ipTablesCmd := exec.Command("iptables", "-nvL")
   156  	out, _, err := runCommandWithOutput(ipTablesCmd)
   157  	if err != nil {
   158  		t.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
   159  	}
   160  
   161  	if !strings.Contains(out, ipTablesSearchString) {
   162  		t.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
   163  	}
   164  
   165  	if err := d.Stop(); err != nil {
   166  		t.Fatalf("Could not stop daemon: %v", err)
   167  	}
   168  
   169  	// get output from iptables after restart
   170  	ipTablesCmd = exec.Command("iptables", "-nvL")
   171  	out, _, err = runCommandWithOutput(ipTablesCmd)
   172  	if err != nil {
   173  		t.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
   174  	}
   175  
   176  	if strings.Contains(out, ipTablesSearchString) {
   177  		t.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out)
   178  	}
   179  
   180  	logDone("daemon - run,iptables - iptables rules cleaned after daemon restart")
   181  }
   182  
   183  func TestDaemonIptablesCreate(t *testing.T) {
   184  	defer deleteAllContainers()
   185  
   186  	d := NewDaemon(t)
   187  	if err := d.StartWithBusybox(); err != nil {
   188  		t.Fatalf("Could not start daemon with busybox: %v", err)
   189  	}
   190  	defer d.Stop()
   191  
   192  	if out, err := d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil {
   193  		t.Fatalf("Could not run top: %s, %v", out, err)
   194  	}
   195  
   196  	// get output from iptables with container running
   197  	ipTablesSearchString := "tcp dpt:80"
   198  	ipTablesCmd := exec.Command("iptables", "-nvL")
   199  	out, _, err := runCommandWithOutput(ipTablesCmd)
   200  	if err != nil {
   201  		t.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
   202  	}
   203  
   204  	if !strings.Contains(out, ipTablesSearchString) {
   205  		t.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
   206  	}
   207  
   208  	if err := d.Restart(); err != nil {
   209  		t.Fatalf("Could not restart daemon: %v", err)
   210  	}
   211  
   212  	// make sure the container is not running
   213  	runningOut, err := d.Cmd("inspect", "--format='{{.State.Running}}'", "top")
   214  	if err != nil {
   215  		t.Fatalf("Could not inspect on container: %s, %v", out, err)
   216  	}
   217  	if strings.TrimSpace(runningOut) != "true" {
   218  		t.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut))
   219  	}
   220  
   221  	// get output from iptables after restart
   222  	ipTablesCmd = exec.Command("iptables", "-nvL")
   223  	out, _, err = runCommandWithOutput(ipTablesCmd)
   224  	if err != nil {
   225  		t.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
   226  	}
   227  
   228  	if !strings.Contains(out, ipTablesSearchString) {
   229  		t.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out)
   230  	}
   231  
   232  	logDone("daemon - run,iptables - iptables rules for always restarted container created after daemon restart")
   233  }
   234  
   235  func TestDaemonLoggingLevel(t *testing.T) {
   236  	d := NewDaemon(t)
   237  
   238  	if err := d.Start("--log-level=bogus"); err == nil {
   239  		t.Fatal("Daemon should not have been able to start")
   240  	}
   241  
   242  	d = NewDaemon(t)
   243  	if err := d.Start("--log-level=debug"); err != nil {
   244  		t.Fatal(err)
   245  	}
   246  	d.Stop()
   247  	content, _ := ioutil.ReadFile(d.logFile.Name())
   248  	if !strings.Contains(string(content), `level=debug`) {
   249  		t.Fatalf(`Missing level="debug" in log file:\n%s`, string(content))
   250  	}
   251  
   252  	d = NewDaemon(t)
   253  	if err := d.Start("--log-level=fatal"); err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	d.Stop()
   257  	content, _ = ioutil.ReadFile(d.logFile.Name())
   258  	if strings.Contains(string(content), `level=debug`) {
   259  		t.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content))
   260  	}
   261  
   262  	d = NewDaemon(t)
   263  	if err := d.Start("-D"); err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	d.Stop()
   267  	content, _ = ioutil.ReadFile(d.logFile.Name())
   268  	if !strings.Contains(string(content), `level=debug`) {
   269  		t.Fatalf(`Missing level="debug" in log file using -D:\n%s`, string(content))
   270  	}
   271  
   272  	d = NewDaemon(t)
   273  	if err := d.Start("--debug"); err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	d.Stop()
   277  	content, _ = ioutil.ReadFile(d.logFile.Name())
   278  	if !strings.Contains(string(content), `level=debug`) {
   279  		t.Fatalf(`Missing level="debug" in log file using --debug:\n%s`, string(content))
   280  	}
   281  
   282  	d = NewDaemon(t)
   283  	if err := d.Start("--debug", "--log-level=fatal"); err != nil {
   284  		t.Fatal(err)
   285  	}
   286  	d.Stop()
   287  	content, _ = ioutil.ReadFile(d.logFile.Name())
   288  	if !strings.Contains(string(content), `level=debug`) {
   289  		t.Fatalf(`Missing level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
   290  	}
   291  
   292  	logDone("daemon - Logging Level")
   293  }
   294  
   295  func TestDaemonAllocatesListeningPort(t *testing.T) {
   296  	listeningPorts := [][]string{
   297  		{"0.0.0.0", "0.0.0.0", "5678"},
   298  		{"127.0.0.1", "127.0.0.1", "1234"},
   299  		{"localhost", "127.0.0.1", "1235"},
   300  	}
   301  
   302  	cmdArgs := []string{}
   303  	for _, hostDirective := range listeningPorts {
   304  		cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2]))
   305  	}
   306  
   307  	d := NewDaemon(t)
   308  	if err := d.StartWithBusybox(cmdArgs...); err != nil {
   309  		t.Fatalf("Could not start daemon with busybox: %v", err)
   310  	}
   311  	defer d.Stop()
   312  
   313  	for _, hostDirective := range listeningPorts {
   314  		output, err := d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true")
   315  		if err == nil {
   316  			t.Fatalf("Container should not start, expected port already allocated error: %q", output)
   317  		} else if !strings.Contains(output, "port is already allocated") {
   318  			t.Fatalf("Expected port is already allocated error: %q", output)
   319  		}
   320  	}
   321  
   322  	logDone("daemon - daemon listening port is allocated")
   323  }
   324  
   325  // #9629
   326  func TestDaemonVolumesBindsRefs(t *testing.T) {
   327  	d := NewDaemon(t)
   328  
   329  	if err := d.StartWithBusybox(); err != nil {
   330  		t.Fatal(err)
   331  	}
   332  
   333  	tmp, err := ioutil.TempDir(os.TempDir(), "")
   334  	if err != nil {
   335  		t.Fatal(err)
   336  	}
   337  	defer os.RemoveAll(tmp)
   338  
   339  	if err := ioutil.WriteFile(tmp+"/test", []byte("testing"), 0655); err != nil {
   340  		t.Fatal(err)
   341  	}
   342  
   343  	if out, err := d.Cmd("create", "-v", tmp+":/foo", "--name=voltest", "busybox"); err != nil {
   344  		t.Fatal(err, out)
   345  	}
   346  
   347  	if err := d.Restart(); err != nil {
   348  		t.Fatal(err)
   349  	}
   350  
   351  	if out, err := d.Cmd("run", "--volumes-from=voltest", "--name=consumer", "busybox", "/bin/sh", "-c", "[ -f /foo/test ]"); err != nil {
   352  		t.Fatal(err, out)
   353  	}
   354  
   355  	logDone("daemon - bind refs in data-containers survive daemon restart")
   356  }
   357  
   358  func TestDaemonKeyGeneration(t *testing.T) {
   359  	// TODO: skip or update for Windows daemon
   360  	os.Remove("/etc/docker/key.json")
   361  	d := NewDaemon(t)
   362  	if err := d.Start(); err != nil {
   363  		t.Fatalf("Could not start daemon: %v", err)
   364  	}
   365  	d.Stop()
   366  
   367  	k, err := libtrust.LoadKeyFile("/etc/docker/key.json")
   368  	if err != nil {
   369  		t.Fatalf("Error opening key file")
   370  	}
   371  	kid := k.KeyID()
   372  	// Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF)
   373  	if len(kid) != 59 {
   374  		t.Fatalf("Bad key ID: %s", kid)
   375  	}
   376  
   377  	logDone("daemon - key generation")
   378  }
   379  
   380  func TestDaemonKeyMigration(t *testing.T) {
   381  	// TODO: skip or update for Windows daemon
   382  	os.Remove("/etc/docker/key.json")
   383  	k1, err := libtrust.GenerateECP256PrivateKey()
   384  	if err != nil {
   385  		t.Fatalf("Error generating private key: %s", err)
   386  	}
   387  	if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil {
   388  		t.Fatalf("Error creating .docker directory: %s", err)
   389  	}
   390  	if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil {
   391  		t.Fatalf("Error saving private key: %s", err)
   392  	}
   393  
   394  	d := NewDaemon(t)
   395  	if err := d.Start(); err != nil {
   396  		t.Fatalf("Could not start daemon: %v", err)
   397  	}
   398  	d.Stop()
   399  
   400  	k2, err := libtrust.LoadKeyFile("/etc/docker/key.json")
   401  	if err != nil {
   402  		t.Fatalf("Error opening key file")
   403  	}
   404  	if k1.KeyID() != k2.KeyID() {
   405  		t.Fatalf("Key not migrated")
   406  	}
   407  
   408  	logDone("daemon - key migration")
   409  }
   410  
   411  // Simulate an older daemon (pre 1.3) coming up with volumes specified in containers
   412  //	without corresponding volume json
   413  func TestDaemonUpgradeWithVolumes(t *testing.T) {
   414  	d := NewDaemon(t)
   415  
   416  	graphDir := filepath.Join(os.TempDir(), "docker-test")
   417  	defer os.RemoveAll(graphDir)
   418  	if err := d.StartWithBusybox("-g", graphDir); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  
   422  	tmpDir := filepath.Join(os.TempDir(), "test")
   423  	defer os.RemoveAll(tmpDir)
   424  
   425  	if out, err := d.Cmd("create", "-v", tmpDir+":/foo", "--name=test", "busybox"); err != nil {
   426  		t.Fatal(err, out)
   427  	}
   428  
   429  	if err := d.Stop(); err != nil {
   430  		t.Fatal(err)
   431  	}
   432  
   433  	// Remove this since we're expecting the daemon to re-create it too
   434  	if err := os.RemoveAll(tmpDir); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	configDir := filepath.Join(graphDir, "volumes")
   439  
   440  	if err := os.RemoveAll(configDir); err != nil {
   441  		t.Fatal(err)
   442  	}
   443  
   444  	if err := d.Start("-g", graphDir); err != nil {
   445  		t.Fatal(err)
   446  	}
   447  
   448  	if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
   449  		t.Fatalf("expected volume path %s to exist but it does not", tmpDir)
   450  	}
   451  
   452  	dir, err := ioutil.ReadDir(configDir)
   453  	if err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	if len(dir) == 0 {
   457  		t.Fatalf("expected volumes config dir to contain data for new volume")
   458  	}
   459  
   460  	// Now with just removing the volume config and not the volume data
   461  	if err := d.Stop(); err != nil {
   462  		t.Fatal(err)
   463  	}
   464  
   465  	if err := os.RemoveAll(configDir); err != nil {
   466  		t.Fatal(err)
   467  	}
   468  
   469  	if err := d.Start("-g", graphDir); err != nil {
   470  		t.Fatal(err)
   471  	}
   472  
   473  	dir, err = ioutil.ReadDir(configDir)
   474  	if err != nil {
   475  		t.Fatal(err)
   476  	}
   477  
   478  	if len(dir) == 0 {
   479  		t.Fatalf("expected volumes config dir to contain data for new volume")
   480  	}
   481  
   482  	logDone("daemon - volumes from old(pre 1.3) daemon work")
   483  }
   484  
   485  // GH#11320 - verify that the daemon exits on failure properly
   486  // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means
   487  // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required
   488  func TestDaemonExitOnFailure(t *testing.T) {
   489  	d := NewDaemon(t)
   490  	defer d.Stop()
   491  
   492  	//attempt to start daemon with incorrect flags (we know -b and --bip conflict)
   493  	if err := d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil {
   494  		//verify we got the right error
   495  		if !strings.Contains(err.Error(), "Daemon exited and never started") {
   496  			t.Fatalf("Expected daemon not to start, got %v", err)
   497  		}
   498  		// look in the log and make sure we got the message that daemon is shutting down
   499  		runCmd := exec.Command("grep", "Shutting down daemon due to", d.LogfileName())
   500  		if out, _, err := runCommandWithOutput(runCmd); err != nil {
   501  			t.Fatalf("Expected 'shutting down daemon due to error' message; but doesn't exist in log: %q, err: %v", out, err)
   502  		}
   503  	} else {
   504  		//if we didn't get an error and the daemon is running, this is a failure
   505  		d.Stop()
   506  		t.Fatal("Conflicting options should cause the daemon to error out with a failure")
   507  	}
   508  
   509  	logDone("daemon - verify no start on daemon init errors")
   510  }
   511  
   512  func TestDaemonUlimitDefaults(t *testing.T) {
   513  	testRequires(t, NativeExecDriver)
   514  	d := NewDaemon(t)
   515  
   516  	if err := d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil {
   517  		t.Fatal(err)
   518  	}
   519  
   520  	out, err := d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)")
   521  	if err != nil {
   522  		t.Fatal(out, err)
   523  	}
   524  
   525  	outArr := strings.Split(out, "\n")
   526  	if len(outArr) < 2 {
   527  		t.Fatal("got unexpected output: %s", out)
   528  	}
   529  	nofile := strings.TrimSpace(outArr[0])
   530  	nproc := strings.TrimSpace(outArr[1])
   531  
   532  	if nofile != "42" {
   533  		t.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile)
   534  	}
   535  	if nproc != "2048" {
   536  		t.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc)
   537  	}
   538  
   539  	// Now restart daemon with a new default
   540  	if err := d.Restart("--default-ulimit", "nofile=43"); err != nil {
   541  		t.Fatal(err)
   542  	}
   543  
   544  	out, err = d.Cmd("start", "-a", "test")
   545  	if err != nil {
   546  		t.Fatal(err)
   547  	}
   548  
   549  	outArr = strings.Split(out, "\n")
   550  	if len(outArr) < 2 {
   551  		t.Fatal("got unexpected output: %s", out)
   552  	}
   553  	nofile = strings.TrimSpace(outArr[0])
   554  	nproc = strings.TrimSpace(outArr[1])
   555  
   556  	if nofile != "43" {
   557  		t.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile)
   558  	}
   559  	if nproc != "2048" {
   560  		t.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc)
   561  	}
   562  
   563  	logDone("daemon - default ulimits are applied")
   564  }
   565  
   566  // #11315
   567  func TestDaemonRestartRenameContainer(t *testing.T) {
   568  	d := NewDaemon(t)
   569  	if err := d.StartWithBusybox(); err != nil {
   570  		t.Fatal(err)
   571  	}
   572  
   573  	if out, err := d.Cmd("run", "--name=test", "busybox"); err != nil {
   574  		t.Fatal(err, out)
   575  	}
   576  
   577  	if out, err := d.Cmd("rename", "test", "test2"); err != nil {
   578  		t.Fatal(err, out)
   579  	}
   580  
   581  	if err := d.Restart(); err != nil {
   582  		t.Fatal(err)
   583  	}
   584  
   585  	if out, err := d.Cmd("start", "test2"); err != nil {
   586  		t.Fatal(err, out)
   587  	}
   588  
   589  	logDone("daemon - rename persists through daemon restart")
   590  }
   591  
   592  func TestDaemonLoggingDriverDefault(t *testing.T) {
   593  	d := NewDaemon(t)
   594  
   595  	if err := d.StartWithBusybox(); err != nil {
   596  		t.Fatal(err)
   597  	}
   598  	defer d.Stop()
   599  
   600  	out, err := d.Cmd("run", "-d", "busybox", "echo", "testline")
   601  	if err != nil {
   602  		t.Fatal(out, err)
   603  	}
   604  	id := strings.TrimSpace(out)
   605  
   606  	if out, err := d.Cmd("wait", id); err != nil {
   607  		t.Fatal(out, err)
   608  	}
   609  	logPath := filepath.Join(d.folder, "graph", "containers", id, id+"-json.log")
   610  
   611  	if _, err := os.Stat(logPath); err != nil {
   612  		t.Fatal(err)
   613  	}
   614  	f, err := os.Open(logPath)
   615  	if err != nil {
   616  		t.Fatal(err)
   617  	}
   618  	var res struct {
   619  		Log    string    `json:log`
   620  		Stream string    `json:stream`
   621  		Time   time.Time `json:time`
   622  	}
   623  	if err := json.NewDecoder(f).Decode(&res); err != nil {
   624  		t.Fatal(err)
   625  	}
   626  	if res.Log != "testline\n" {
   627  		t.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n")
   628  	}
   629  	if res.Stream != "stdout" {
   630  		t.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout")
   631  	}
   632  	if !time.Now().After(res.Time) {
   633  		t.Fatalf("Log time %v in future", res.Time)
   634  	}
   635  	logDone("daemon - default 'json-file' logging driver")
   636  }
   637  
   638  func TestDaemonLoggingDriverDefaultOverride(t *testing.T) {
   639  	d := NewDaemon(t)
   640  
   641  	if err := d.StartWithBusybox(); err != nil {
   642  		t.Fatal(err)
   643  	}
   644  	defer d.Stop()
   645  
   646  	out, err := d.Cmd("run", "-d", "--log-driver=none", "busybox", "echo", "testline")
   647  	if err != nil {
   648  		t.Fatal(out, err)
   649  	}
   650  	id := strings.TrimSpace(out)
   651  
   652  	if out, err := d.Cmd("wait", id); err != nil {
   653  		t.Fatal(out, err)
   654  	}
   655  	logPath := filepath.Join(d.folder, "graph", "containers", id, id+"-json.log")
   656  
   657  	if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) {
   658  		t.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err)
   659  	}
   660  	logDone("daemon - default logging driver override in run")
   661  }
   662  
   663  func TestDaemonLoggingDriverNone(t *testing.T) {
   664  	d := NewDaemon(t)
   665  
   666  	if err := d.StartWithBusybox("--log-driver=none"); err != nil {
   667  		t.Fatal(err)
   668  	}
   669  	defer d.Stop()
   670  
   671  	out, err := d.Cmd("run", "-d", "busybox", "echo", "testline")
   672  	if err != nil {
   673  		t.Fatal(out, err)
   674  	}
   675  	id := strings.TrimSpace(out)
   676  	if out, err := d.Cmd("wait", id); err != nil {
   677  		t.Fatal(out, err)
   678  	}
   679  
   680  	logPath := filepath.Join(d.folder, "graph", "containers", id, id+"-json.log")
   681  
   682  	if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) {
   683  		t.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err)
   684  	}
   685  	logDone("daemon - 'none' logging driver")
   686  }
   687  
   688  func TestDaemonLoggingDriverNoneOverride(t *testing.T) {
   689  	d := NewDaemon(t)
   690  
   691  	if err := d.StartWithBusybox("--log-driver=none"); err != nil {
   692  		t.Fatal(err)
   693  	}
   694  	defer d.Stop()
   695  
   696  	out, err := d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "echo", "testline")
   697  	if err != nil {
   698  		t.Fatal(out, err)
   699  	}
   700  	id := strings.TrimSpace(out)
   701  
   702  	if out, err := d.Cmd("wait", id); err != nil {
   703  		t.Fatal(out, err)
   704  	}
   705  	logPath := filepath.Join(d.folder, "graph", "containers", id, id+"-json.log")
   706  
   707  	if _, err := os.Stat(logPath); err != nil {
   708  		t.Fatal(err)
   709  	}
   710  	f, err := os.Open(logPath)
   711  	if err != nil {
   712  		t.Fatal(err)
   713  	}
   714  	var res struct {
   715  		Log    string    `json:log`
   716  		Stream string    `json:stream`
   717  		Time   time.Time `json:time`
   718  	}
   719  	if err := json.NewDecoder(f).Decode(&res); err != nil {
   720  		t.Fatal(err)
   721  	}
   722  	if res.Log != "testline\n" {
   723  		t.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n")
   724  	}
   725  	if res.Stream != "stdout" {
   726  		t.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout")
   727  	}
   728  	if !time.Now().After(res.Time) {
   729  		t.Fatalf("Log time %v in future", res.Time)
   730  	}
   731  	logDone("daemon - 'none' logging driver override in run")
   732  }
   733  
   734  func TestDaemonLoggingDriverNoneLogsError(t *testing.T) {
   735  	d := NewDaemon(t)
   736  
   737  	if err := d.StartWithBusybox("--log-driver=none"); err != nil {
   738  		t.Fatal(err)
   739  	}
   740  	defer d.Stop()
   741  
   742  	out, err := d.Cmd("run", "-d", "busybox", "echo", "testline")
   743  	if err != nil {
   744  		t.Fatal(out, err)
   745  	}
   746  	id := strings.TrimSpace(out)
   747  	out, err = d.Cmd("logs", id)
   748  	if err == nil {
   749  		t.Fatalf("Logs should fail with \"none\" driver")
   750  	}
   751  	if !strings.Contains(out, `\"logs\" command is supported only for \"json-file\" logging driver`) {
   752  		t.Fatalf("There should be error about non-json-file driver, got %s", out)
   753  	}
   754  	logDone("daemon - logs not available for non-json-file drivers")
   755  }
   756  
   757  func TestDaemonDots(t *testing.T) {
   758  	defer deleteAllContainers()
   759  	d := NewDaemon(t)
   760  	if err := d.StartWithBusybox(); err != nil {
   761  		t.Fatal(err)
   762  	}
   763  
   764  	// Now create 4 containers
   765  	if _, err := d.Cmd("create", "busybox"); err != nil {
   766  		t.Fatalf("Error creating container: %q", err)
   767  	}
   768  	if _, err := d.Cmd("create", "busybox"); err != nil {
   769  		t.Fatalf("Error creating container: %q", err)
   770  	}
   771  	if _, err := d.Cmd("create", "busybox"); err != nil {
   772  		t.Fatalf("Error creating container: %q", err)
   773  	}
   774  	if _, err := d.Cmd("create", "busybox"); err != nil {
   775  		t.Fatalf("Error creating container: %q", err)
   776  	}
   777  
   778  	d.Stop()
   779  
   780  	d.Start("--log-level=debug")
   781  	d.Stop()
   782  	content, _ := ioutil.ReadFile(d.logFile.Name())
   783  	if strings.Contains(string(content), "....") {
   784  		t.Fatalf("Debug level should not have ....\n%s", string(content))
   785  	}
   786  
   787  	d.Start("--log-level=error")
   788  	d.Stop()
   789  	content, _ = ioutil.ReadFile(d.logFile.Name())
   790  	if strings.Contains(string(content), "....") {
   791  		t.Fatalf("Error level should not have ....\n%s", string(content))
   792  	}
   793  
   794  	d.Start("--log-level=info")
   795  	d.Stop()
   796  	content, _ = ioutil.ReadFile(d.logFile.Name())
   797  	if !strings.Contains(string(content), "....") {
   798  		t.Fatalf("Info level should have ....\n%s", string(content))
   799  	}
   800  
   801  	logDone("daemon - test dots on INFO")
   802  }
   803  
   804  func TestDaemonUnixSockCleanedUp(t *testing.T) {
   805  	d := NewDaemon(t)
   806  	dir, err := ioutil.TempDir("", "socket-cleanup-test")
   807  	if err != nil {
   808  		t.Fatal(err)
   809  	}
   810  	defer os.RemoveAll(dir)
   811  
   812  	sockPath := filepath.Join(dir, "docker.sock")
   813  	if err := d.Start("--host", "unix://"+sockPath); err != nil {
   814  		t.Fatal(err)
   815  	}
   816  
   817  	if _, err := os.Stat(sockPath); err != nil {
   818  		t.Fatal("socket does not exist")
   819  	}
   820  
   821  	if err := d.Stop(); err != nil {
   822  		t.Fatal(err)
   823  	}
   824  
   825  	if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) {
   826  		t.Fatal("unix socket is not cleaned up")
   827  	}
   828  
   829  	logDone("daemon - unix socket is cleaned up")
   830  }