diff --git a/components/engine/integration-cli/daemon.go b/components/engine/integration-cli/daemon.go index 5348b97c00..93bce27f14 100644 --- a/components/engine/integration-cli/daemon.go +++ b/components/engine/integration-cli/daemon.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/pkg/integration/checker" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/tlsconfig" + "github.com/docker/engine-api/types/events" "github.com/docker/go-connections/sockets" "github.com/go-check/check" ) @@ -543,3 +544,50 @@ func (d *Daemon) checkActiveContainerCount(c *check.C) (interface{}, check.Comme } return len(strings.Split(strings.TrimSpace(out), "\n")), check.Commentf("output: %q", string(out)) } + +func (d *Daemon) reloadConfig() error { + if d.cmd == nil || d.cmd.Process == nil { + return fmt.Errorf("daemon is not running") + } + + errCh := make(chan error) + started := make(chan struct{}) + go func() { + _, body, err := sockRequestRawToDaemon("GET", "/events", nil, "", d.sock()) + close(started) + if err != nil { + errCh <- err + } + defer body.Close() + dec := json.NewDecoder(body) + for { + var e events.Message + if err := dec.Decode(&e); err != nil { + errCh <- err + return + } + if e.Type != events.DaemonEventType { + continue + } + if e.Action != "reload" { + continue + } + close(errCh) // notify that we are done + return + } + }() + + <-started + if err := signalDaemonReload(d.cmd.Process.Pid); err != nil { + return fmt.Errorf("error signaling daemon reload: %v", err) + } + select { + case err := <-errCh: + if err != nil { + return fmt.Errorf("error waiting for daemon reload event: %v", err) + } + case <-time.After(30 * time.Second): + return fmt.Errorf("timeout waiting for daemon reload event") + } + return nil +} diff --git a/components/engine/integration-cli/daemon_unix.go b/components/engine/integration-cli/daemon_unix.go index ef85d58f15..6f84fbbdfd 100644 --- a/components/engine/integration-cli/daemon_unix.go +++ b/components/engine/integration-cli/daemon_unix.go @@ -7,3 +7,7 @@ import "syscall" func signalDaemonDump(pid int) { syscall.Kill(pid, syscall.SIGQUIT) } + +func signalDaemonReload(pid int) error { + return syscall.Kill(pid, syscall.SIGHUP) +} diff --git a/components/engine/integration-cli/daemon_windows.go b/components/engine/integration-cli/daemon_windows.go index 671c880a42..c6310975d8 100644 --- a/components/engine/integration-cli/daemon_windows.go +++ b/components/engine/integration-cli/daemon_windows.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "strconv" "syscall" "unsafe" @@ -40,3 +41,7 @@ func signalDaemonDump(pid int) { } pulseEvent(h2, procPulseEvent) } + +func signalDaemonReload(pid int) error { + return fmt.Errorf("daemon reload not supported") +} diff --git a/components/engine/integration-cli/docker_cli_daemon_test.go b/components/engine/integration-cli/docker_cli_daemon_test.go index 0f28cfbe9d..454ef09779 100644 --- a/components/engine/integration-cli/docker_cli_daemon_test.go +++ b/components/engine/integration-cli/docker_cli_daemon_test.go @@ -23,7 +23,6 @@ import ( "github.com/docker/docker/pkg/integration/checker" icmd "github.com/docker/docker/pkg/integration/cmd" "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/testutil/tempfile" "github.com/docker/go-units" "github.com/docker/libnetwork/iptables" "github.com/docker/libtrust" @@ -2352,32 +2351,42 @@ func (s *DockerSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) { testRequires(c, SameHostDaemon, DaemonIsLinux) // daemon config file - tmpfile := tempfile.NewTempFile(c, "config-test", `{ "debug" : false }`) - defer tmpfile.Remove() + daemonConfig := `{ "debug" : false }` + configFile, err := ioutil.TempFile("", "test-daemon-discovery-backend-config-reload-config") + c.Assert(err, checker.IsNil, check.Commentf("could not create temp file for config reload")) + configFilePath := configFile.Name() + defer func() { + configFile.Close() + os.RemoveAll(configFile.Name()) + }() + + _, err = configFile.Write([]byte(daemonConfig)) + c.Assert(err, checker.IsNil) d := NewDaemon(c) // --log-level needs to be set so that d.Start() doesn't add --debug causing // a conflict with the config - err := d.Start("--config-file", tmpfile.Name(), "--log-level=info") + err = d.Start("--config-file", configFilePath, "--log-level=info") c.Assert(err, checker.IsNil) defer d.Stop() // daemon config file - daemonConfig := `{ + daemonConfig = `{ "cluster-store": "consul://consuladdr:consulport/some/path", "cluster-advertise": "192.168.56.100:0", "debug" : false }` - os.Remove(tmpfile.Name()) - configFile, err := os.Create(tmpfile.Name()) + err = configFile.Truncate(0) + c.Assert(err, checker.IsNil) + _, err = configFile.Seek(0, os.SEEK_SET) c.Assert(err, checker.IsNil) - fmt.Fprintf(configFile, "%s", daemonConfig) - configFile.Close() - syscall.Kill(d.cmd.Process.Pid, syscall.SIGHUP) + _, err = configFile.Write([]byte(daemonConfig)) + c.Assert(err, checker.IsNil) - time.Sleep(3 * time.Second) + err = d.reloadConfig() + c.Assert(err, checker.IsNil, check.Commentf("error reloading daemon config")) out, err := d.Cmd("info") c.Assert(err, checker.IsNil)