Merge pull request #9648 from estesp/9202-update-resolvconf
Update container resolv.conf when host network changes /etc/resolv.conf
This commit is contained in:
commit
ba9513ff3f
2 changed files with 96 additions and 2 deletions
|
@ -5,13 +5,25 @@ import (
|
|||
"io/ioutil"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
|
||||
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
|
||||
defaultDns = []string{"8.8.8.8", "8.8.4.4"}
|
||||
localHostRegexp = regexp.MustCompile(`(?m)^nameserver 127[^\n]+\n*`)
|
||||
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
|
||||
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
|
||||
)
|
||||
|
||||
var lastModified struct {
|
||||
sync.Mutex
|
||||
sha256 string
|
||||
contents []byte
|
||||
}
|
||||
|
||||
func Get() ([]byte, error) {
|
||||
resolv, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
|
@ -20,6 +32,57 @@ func Get() ([]byte, error) {
|
|||
return resolv, nil
|
||||
}
|
||||
|
||||
// Retrieves the host /etc/resolv.conf file, checks against the last hash
|
||||
// and, if modified since last check, returns the bytes and new hash.
|
||||
// This feature is used by the resolv.conf updater for containers
|
||||
func GetIfChanged() ([]byte, string, error) {
|
||||
lastModified.Lock()
|
||||
defer lastModified.Unlock()
|
||||
|
||||
resolv, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
newHash, err := utils.HashData(bytes.NewReader(resolv))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if lastModified.sha256 != newHash {
|
||||
lastModified.sha256 = newHash
|
||||
lastModified.contents = resolv
|
||||
return resolv, newHash, nil
|
||||
}
|
||||
// nothing changed, so return no data
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
// retrieve the last used contents and hash of the host resolv.conf
|
||||
// Used by containers updating on restart
|
||||
func GetLastModified() ([]byte, string) {
|
||||
lastModified.Lock()
|
||||
defer lastModified.Unlock()
|
||||
|
||||
return lastModified.contents, lastModified.sha256
|
||||
}
|
||||
|
||||
// RemoveReplaceLocalDns looks for localhost (127.*) entries in the provided
|
||||
// resolv.conf, removing local nameserver entries, and, if the resulting
|
||||
// cleaned config has no defined nameservers left, adds default DNS entries
|
||||
// It also returns a boolean to notify the caller if changes were made at all
|
||||
func RemoveReplaceLocalDns(resolvConf []byte) ([]byte, bool) {
|
||||
changed := false
|
||||
cleanedResolvConf := localHostRegexp.ReplaceAll(resolvConf, []byte{})
|
||||
// if the resulting resolvConf is empty, use defaultDns
|
||||
if !bytes.Contains(cleanedResolvConf, []byte("nameserver")) {
|
||||
log.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultDns)
|
||||
cleanedResolvConf = append(cleanedResolvConf, []byte("\nnameserver "+strings.Join(defaultDns, "\nnameserver "))...)
|
||||
}
|
||||
if !bytes.Equal(resolvConf, cleanedResolvConf) {
|
||||
changed = true
|
||||
}
|
||||
return cleanedResolvConf, changed
|
||||
}
|
||||
|
||||
// getLines parses input into lines and strips away comments.
|
||||
func getLines(input []byte, commentMarker []byte) [][]byte {
|
||||
lines := bytes.Split(input, []byte("\n"))
|
||||
|
|
|
@ -156,3 +156,34 @@ func TestBuildWithZeroLengthDomainSearch(t *testing.T) {
|
|||
t.Fatalf("Expected to not find '%s' got '%s'", notExpected, content)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveReplaceLocalDns(t *testing.T) {
|
||||
ns0 := "nameserver 10.16.60.14\nnameserver 10.16.60.21\n"
|
||||
|
||||
if result, _ := RemoveReplaceLocalDns([]byte(ns0)); result != nil {
|
||||
if ns0 != string(result) {
|
||||
t.Fatalf("Failed No Localhost: expected \n<%s> got \n<%s>", ns0, string(result))
|
||||
}
|
||||
}
|
||||
|
||||
ns1 := "nameserver 10.16.60.14\nnameserver 10.16.60.21\nnameserver 127.0.0.1\n"
|
||||
if result, _ := RemoveReplaceLocalDns([]byte(ns1)); result != nil {
|
||||
if ns0 != string(result) {
|
||||
t.Fatalf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result))
|
||||
}
|
||||
}
|
||||
|
||||
ns1 = "nameserver 10.16.60.14\nnameserver 127.0.0.1\nnameserver 10.16.60.21\n"
|
||||
if result, _ := RemoveReplaceLocalDns([]byte(ns1)); result != nil {
|
||||
if ns0 != string(result) {
|
||||
t.Fatalf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result))
|
||||
}
|
||||
}
|
||||
|
||||
ns1 = "nameserver 127.0.1.1\nnameserver 10.16.60.14\nnameserver 10.16.60.21\n"
|
||||
if result, _ := RemoveReplaceLocalDns([]byte(ns1)); result != nil {
|
||||
if ns0 != string(result) {
|
||||
t.Fatalf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue