mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #467 from thockin/14069-dns-options
Add DNS 'options' support
This commit is contained in:
commit
1e0b620ea7
3 changed files with 96 additions and 9 deletions
|
@ -30,6 +30,7 @@ var (
|
||||||
nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
|
nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
|
||||||
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
|
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
|
||||||
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
|
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
|
||||||
|
optionsRegexp = regexp.MustCompile(`^\s*options\s*(([^\s]+\s*)*)$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
var lastModified struct {
|
var lastModified struct {
|
||||||
|
@ -165,10 +166,25 @@ func GetSearchDomains(resolvConf []byte) []string {
|
||||||
return domains
|
return domains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOptions returns options (if any) listed in /etc/resolv.conf
|
||||||
|
// If more than one options line is encountered, only the contents of the last
|
||||||
|
// one is returned.
|
||||||
|
func GetOptions(resolvConf []byte) []string {
|
||||||
|
options := []string{}
|
||||||
|
for _, line := range getLines(resolvConf, []byte("#")) {
|
||||||
|
match := optionsRegexp.FindSubmatch(line)
|
||||||
|
if match == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
options = strings.Fields(string(match[1]))
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
// Build writes a configuration file to path containing a "nameserver" entry
|
// Build writes a configuration file to path containing a "nameserver" entry
|
||||||
// for every element in dns, and a "search" entry for every element in
|
// for every element in dns, a "search" entry for every element in
|
||||||
// dnsSearch.
|
// dnsSearch, and an "options" entry for every element in dnsOptions.
|
||||||
func Build(path string, dns, dnsSearch []string) (string, error) {
|
func Build(path string, dns, dnsSearch, dnsOptions []string) (string, error) {
|
||||||
content := bytes.NewBuffer(nil)
|
content := bytes.NewBuffer(nil)
|
||||||
if len(dnsSearch) > 0 {
|
if len(dnsSearch) > 0 {
|
||||||
if searchString := strings.Join(dnsSearch, " "); strings.Trim(searchString, " ") != "." {
|
if searchString := strings.Join(dnsSearch, " "); strings.Trim(searchString, " ") != "." {
|
||||||
|
@ -182,6 +198,13 @@ func Build(path string, dns, dnsSearch []string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(dnsOptions) > 0 {
|
||||||
|
if optsString := strings.Join(dnsOptions, " "); strings.Trim(optsString, " ") != "" {
|
||||||
|
if _, err := content.WriteString("options " + optsString + "\n"); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hash, err := ioutils.HashData(bytes.NewReader(content.Bytes()))
|
hash, err := ioutils.HashData(bytes.NewReader(content.Bytes()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -98,6 +98,32 @@ nameserver 4.30.20.100`: {"foo.example.com", "example.com"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetOptions(t *testing.T) {
|
||||||
|
for resolv, result := range map[string][]string{
|
||||||
|
`options opt1`: {"opt1"},
|
||||||
|
`options opt1 # ignored`: {"opt1"},
|
||||||
|
` options opt1 `: {"opt1"},
|
||||||
|
` options opt1 # ignored`: {"opt1"},
|
||||||
|
`options opt1 opt2 opt3`: {"opt1", "opt2", "opt3"},
|
||||||
|
`options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
|
||||||
|
` options opt1 opt2 opt3 `: {"opt1", "opt2", "opt3"},
|
||||||
|
` options opt1 opt2 opt3 # ignored`: {"opt1", "opt2", "opt3"},
|
||||||
|
``: {},
|
||||||
|
`# ignored`: {},
|
||||||
|
`nameserver 1.2.3.4`: {},
|
||||||
|
`nameserver 1.2.3.4
|
||||||
|
options opt1 opt2 opt3`: {"opt1", "opt2", "opt3"},
|
||||||
|
`nameserver 1.2.3.4
|
||||||
|
options opt1 opt2
|
||||||
|
options opt3 opt4`: {"opt3", "opt4"},
|
||||||
|
} {
|
||||||
|
test := GetOptions([]byte(resolv))
|
||||||
|
if !strSlicesEqual(test, result) {
|
||||||
|
t.Fatalf("Wrong options string {%s} should be %v. Input: %s", test, result, resolv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func strSlicesEqual(a, b []string) bool {
|
func strSlicesEqual(a, b []string) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
|
@ -119,7 +145,7 @@ func TestBuild(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.Remove(file.Name())
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
_, err = Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"search1"})
|
_, err = Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"search1"}, []string{"opt1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -129,7 +155,7 @@ func TestBuild(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if expected := "search search1\nnameserver ns1\nnameserver ns2\nnameserver ns3\n"; !bytes.Contains(content, []byte(expected)) {
|
if expected := "search search1\nnameserver ns1\nnameserver ns2\nnameserver ns3\noptions opt1\n"; !bytes.Contains(content, []byte(expected)) {
|
||||||
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +167,7 @@ func TestBuildWithZeroLengthDomainSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer os.Remove(file.Name())
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
_, err = Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"."})
|
_, err = Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"."}, []string{"opt1"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -151,7 +177,32 @@ func TestBuildWithZeroLengthDomainSearch(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if expected := "nameserver ns1\nnameserver ns2\nnameserver ns3\n"; !bytes.Contains(content, []byte(expected)) {
|
if expected := "nameserver ns1\nnameserver ns2\nnameserver ns3\noptions opt1\n"; !bytes.Contains(content, []byte(expected)) {
|
||||||
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
||||||
|
}
|
||||||
|
if notExpected := "search ."; bytes.Contains(content, []byte(notExpected)) {
|
||||||
|
t.Fatalf("Expected to not find '%s' got '%s'", notExpected, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildWithNoOptions(t *testing.T) {
|
||||||
|
file, err := ioutil.TempFile("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
|
_, err = Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"search1"}, []string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := ioutil.ReadFile(file.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected := "search search1\nnameserver ns1\nnameserver ns2\nnameserver ns3\n"; !bytes.Contains(content, []byte(expected)) {
|
||||||
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
t.Fatalf("Expected to find '%s' got '%s'", expected, content)
|
||||||
}
|
}
|
||||||
if notExpected := "search ."; bytes.Contains(content, []byte(notExpected)) {
|
if notExpected := "search ."; bytes.Contains(content, []byte(notExpected)) {
|
||||||
|
|
|
@ -93,6 +93,7 @@ type resolvConfPathConfig struct {
|
||||||
resolvConfHashFile string
|
resolvConfHashFile string
|
||||||
dnsList []string
|
dnsList []string
|
||||||
dnsSearchList []string
|
dnsSearchList []string
|
||||||
|
dnsOptionsList []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type containerConfig struct {
|
type containerConfig struct {
|
||||||
|
@ -406,17 +407,21 @@ func (sb *sandbox) setupDNS() error {
|
||||||
}
|
}
|
||||||
dnsList := resolvconf.GetNameservers(resolvConf)
|
dnsList := resolvconf.GetNameservers(resolvConf)
|
||||||
dnsSearchList := resolvconf.GetSearchDomains(resolvConf)
|
dnsSearchList := resolvconf.GetSearchDomains(resolvConf)
|
||||||
|
dnsOptionsList := resolvconf.GetOptions(resolvConf)
|
||||||
|
|
||||||
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 {
|
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(dnsOptionsList) > 0 {
|
||||||
if len(sb.config.dnsList) > 0 {
|
if len(sb.config.dnsList) > 0 {
|
||||||
dnsList = sb.config.dnsList
|
dnsList = sb.config.dnsList
|
||||||
}
|
}
|
||||||
if len(sb.config.dnsSearchList) > 0 {
|
if len(sb.config.dnsSearchList) > 0 {
|
||||||
dnsSearchList = sb.config.dnsSearchList
|
dnsSearchList = sb.config.dnsSearchList
|
||||||
}
|
}
|
||||||
|
if len(sb.config.dnsOptionsList) > 0 {
|
||||||
|
dnsOptionsList = sb.config.dnsOptionsList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList)
|
hash, err := resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -580,6 +585,14 @@ func OptionDNSSearch(search string) SandboxOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OptionDNSOptions function returns an option setter for dns options entry option to
|
||||||
|
// be passed to container Create method.
|
||||||
|
func OptionDNSOptions(options string) SandboxOption {
|
||||||
|
return func(sb *sandbox) {
|
||||||
|
sb.config.dnsOptionsList = append(sb.config.dnsOptionsList, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OptionUseDefaultSandbox function returns an option setter for using default sandbox to
|
// OptionUseDefaultSandbox function returns an option setter for using default sandbox to
|
||||||
// be passed to container Create method.
|
// be passed to container Create method.
|
||||||
func OptionUseDefaultSandbox() SandboxOption {
|
func OptionUseDefaultSandbox() SandboxOption {
|
||||||
|
|
Loading…
Add table
Reference in a new issue