From 70429527b0cfde1b84191bc2be7d595a0468e5c2 Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Tue, 30 Jun 2015 13:41:28 -0700 Subject: [PATCH] Honor driver side resolv.conf file For the moment in 1.7.1 since we provide a resolv.conf set api to the driver honor that so that for host driver we can use the the host's /etc/resolv.conf file as is rather than putting the contents through a filtering logic. It should be noted that the driver side capability to set the resolv.conf file is most likely going to go away in the future but this should be fine for 1.7.1 Signed-off-by: Jana Radhakrishnan --- libnetwork/drivers/host/host.go | 6 ++- libnetwork/endpoint.go | 18 +++++++++ libnetwork/libnetwork_test.go | 68 +++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) 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)()