diff --git a/libnetwork/drivers/host/host.go b/libnetwork/drivers/host/host.go index 072cc890ab..5dbc4ef2fb 100644 --- a/libnetwork/drivers/host/host.go +++ b/libnetwork/drivers/host/host.go @@ -57,7 +57,11 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{}, // Join method is invoked when a Sandbox is attached to an endpoint. func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { - return (jinfo.SetHostsPath("/etc/hosts")) + if err := jinfo.SetHostsPath("/etc/hosts"); err != nil { + return err + } + + return jinfo.SetResolvConfPath("/etc/resolv.conf") } // Leave method is invoked when a Sandbox detaches from an endpoint. diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 8539ef5ae8..6d757001b1 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -811,9 +811,19 @@ func (ep *endpoint) updateDNS(resolvConf []byte) error { return os.Rename(tmpResolvFile.Name(), container.config.resolvConfPath) } +func copyFile(src, dst string) error { + sBytes, err := ioutil.ReadFile(src) + if err != nil { + return err + } + + return ioutil.WriteFile(dst, sBytes, 0644) +} + func (ep *endpoint) setupDNS() error { ep.Lock() container := ep.container + joinInfo := ep.joinInfo ep.Unlock() if container == nil { @@ -830,6 +840,14 @@ func (ep *endpoint) setupDNS() error { return err } + if joinInfo.resolvConfPath != "" { + if err := copyFile(joinInfo.resolvConfPath, container.config.resolvConfPath); err != nil { + return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", joinInfo.resolvConfPath, container.config.resolvConfPath, err) + } + + return nil + } + resolvConf, err := resolvconf.Get() if err != nil { return err diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index b890f07613..a13933187d 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -1564,6 +1564,74 @@ func TestEnableIPv6(t *testing.T) { } } +func TestResolvConfHost(t *testing.T) { + if !netutils.IsRunningInContainer() { + defer netutils.SetupTestNetNS(t)() + } + + tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888") + + //take a copy of resolv.conf for restoring after test completes + resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf") + if err != nil { + t.Fatal(err) + } + //cleanup + defer func() { + if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil { + t.Fatal(err) + } + }() + + n, err := controller.NetworkByName("testhost") + if err != nil { + t.Fatal(err) + } + + ep1, err := n.CreateEndpoint("ep1", nil) + if err != nil { + t.Fatal(err) + } + + if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil { + t.Fatal(err) + } + + resolvConfPath := "/tmp/libnetwork_test/resolv.conf" + defer os.Remove(resolvConfPath) + + err = ep1.Join(containerID, + libnetwork.JoinOptionResolvConfPath(resolvConfPath)) + if err != nil { + t.Fatal(err) + } + defer func() { + err = ep1.Leave(containerID) + if err != nil { + t.Fatal(err) + } + }() + + finfo, err := os.Stat(resolvConfPath) + if err != nil { + t.Fatal(err) + } + + fmode := (os.FileMode)(0644) + if finfo.Mode() != fmode { + t.Fatalf("Expected file mode %s, got %s", fmode.String(), finfo.Mode().String()) + } + + content, err := ioutil.ReadFile(resolvConfPath) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(content, tmpResolvConf) { + t.Fatalf("Expected %s, Got %s", string(tmpResolvConf), string(content)) + } +} + func TestResolvConf(t *testing.T) { if !netutils.IsRunningInContainer() { defer netutils.SetupTestNetNS(t)()