浏览代码

Update resolve.conf in containers on file creation.

NetworkManager updates resolve.conf by replacing the current file
with an updated one. This change enables docker to listen for these
events.

Signed-off-by: Sami Wagiaalla <swagiaal@redhat.com>
Sami Wagiaalla 10 年之前
父节点
当前提交
11c7c9710a
共有 2 个文件被更改,包括 52 次插入3 次删除
  1. 4 2
      daemon/daemon.go
  2. 48 1
      integration-cli/docker_cli_run_test.go

+ 4 - 2
daemon/daemon.go

@@ -440,7 +440,9 @@ func (daemon *Daemon) setupResolvconfWatcher() error {
 		for {
 			select {
 			case event := <-watcher.Events:
-				if event.Op&fsnotify.Write == fsnotify.Write {
+				if event.Name == "/etc/resolv.conf" &&
+					(event.Op&fsnotify.Write == fsnotify.Write ||
+						event.Op&fsnotify.Create == fsnotify.Create) {
 					// verify a real change happened before we go further--a file write may have happened
 					// without an actual change to the file
 					updatedResolvConf, newResolvConfHash, err := resolvconf.GetIfChanged()
@@ -473,7 +475,7 @@ func (daemon *Daemon) setupResolvconfWatcher() error {
 		}
 	}()
 
-	if err := watcher.Add("/etc/resolv.conf"); err != nil {
+	if err := watcher.Add("/etc"); err != nil {
 		return err
 	}
 	return nil

+ 48 - 1
integration-cli/docker_cli_run_test.go

@@ -1598,6 +1598,14 @@ func TestRunResolvconfUpdater(t *testing.T) {
 		t.Fatal(err)
 	}
 
+	// This test case is meant to test monitoring resolv.conf when it is
+	// a regular file not a bind mount. So we unmount resolv.conf and replace
+	// it with a file containing the original settings.
+	cmd := exec.Command("umount", "/etc/resolv.conf")
+	if _, err = runCommand(cmd); err != nil {
+		t.Fatal(err)
+	}
+
 	//cleanup
 	defer func() {
 		deleteAllContainers()
@@ -1607,7 +1615,7 @@ func TestRunResolvconfUpdater(t *testing.T) {
 	}()
 
 	//1. test that a non-running container gets an updated resolv.conf
-	cmd := exec.Command(dockerBinary, "run", "--name='first'", "busybox", "true")
+	cmd = exec.Command(dockerBinary, "run", "--name='first'", "busybox", "true")
 	if _, err := runCommand(cmd); err != nil {
 		t.Fatal(err)
 	}
@@ -1730,6 +1738,45 @@ func TestRunResolvconfUpdater(t *testing.T) {
 		t.Fatalf("Container does not have cleaned/replaced DNS in resolv.conf; expected %q, got %q", expected, string(containerResolv))
 	}
 
+	//6. Test that replacing (as opposed to modifying) resolv.conf triggers an update
+	//   of containers' resolv.conf.
+
+	// Restore the original resolv.conf
+	if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
+		t.Fatal(err)
+	}
+
+	// Run the container so it picks up the old settings
+	cmd = exec.Command(dockerBinary, "run", "--name='third'", "busybox", "true")
+	if _, err := runCommand(cmd); err != nil {
+		t.Fatal(err)
+	}
+	containerID3, err := getIDByName("third")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Create a modified resolv.conf.aside and override resolv.conf with it
+	bytesResolvConf = []byte(tmpResolvConf)
+	if err := ioutil.WriteFile("/etc/resolv.conf.aside", bytesResolvConf, 0644); err != nil {
+		t.Fatal(err)
+	}
+
+	err = os.Rename("/etc/resolv.conf.aside", "/etc/resolv.conf")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	time.Sleep(time.Second / 2)
+	// check for update in container
+	containerResolv, err = readContainerFile(containerID3, "resolv.conf")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(containerResolv, bytesResolvConf) {
+		t.Fatalf("Stopped container does not have updated resolv.conf; expected\n%q\n got\n%q", tmpResolvConf, string(containerResolv))
+	}
+
 	//cleanup, restore original resolv.conf happens in defer func()
 	logDone("run - resolv.conf updater")
 }