Browse code

Merge pull request #8983 from LK4D4/consistent_hosts

Consistent hosts

Michael Crosby authored on 2014/11/07 04:51:28
Showing 3 changed files
... ...
@@ -424,7 +424,7 @@ func (container *Container) buildHostsFiles(IP string) error {
424 424
 	}
425 425
 	container.HostsPath = hostsPath
426 426
 
427
-	extraContent := make(map[string]string)
427
+	var extraContent []etchosts.Record
428 428
 
429 429
 	children, err := container.daemon.Children(container.Name)
430 430
 	if err != nil {
... ...
@@ -433,15 +433,15 @@ func (container *Container) buildHostsFiles(IP string) error {
433 433
 
434 434
 	for linkAlias, child := range children {
435 435
 		_, alias := path.Split(linkAlias)
436
-		extraContent[alias] = child.NetworkSettings.IPAddress
436
+		extraContent = append(extraContent, etchosts.Record{Hosts: alias, IP: child.NetworkSettings.IPAddress})
437 437
 	}
438 438
 
439 439
 	for _, extraHost := range container.hostConfig.ExtraHosts {
440 440
 		parts := strings.Split(extraHost, ":")
441
-		extraContent[parts[0]] = parts[1]
441
+		extraContent = append(extraContent, etchosts.Record{Hosts: parts[0], IP: parts[1]})
442 442
 	}
443 443
 
444
-	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, &extraContent)
444
+	return etchosts.Build(container.HostsPath, IP, container.Config.Hostname, container.Config.Domainname, extraContent)
445 445
 }
446 446
 
447 447
 func (container *Container) buildHostnameAndHostsFiles(IP string) error {
... ...
@@ -3,40 +3,54 @@ package etchosts
3 3
 import (
4 4
 	"bytes"
5 5
 	"fmt"
6
+	"io"
6 7
 	"io/ioutil"
7 8
 	"regexp"
8 9
 )
9 10
 
10
-var defaultContent = map[string]string{
11
-	"localhost":                            "127.0.0.1",
12
-	"localhost ip6-localhost ip6-loopback": "::1",
13
-	"ip6-localnet":                         "fe00::0",
14
-	"ip6-mcastprefix":                      "ff00::0",
15
-	"ip6-allnodes":                         "ff02::1",
16
-	"ip6-allrouters":                       "ff02::2",
11
+type Record struct {
12
+	Hosts string
13
+	IP    string
17 14
 }
18 15
 
19
-func Build(path, IP, hostname, domainname string, extraContent *map[string]string) error {
16
+func (r Record) WriteTo(w io.Writer) (int64, error) {
17
+	n, err := fmt.Fprintf(w, "%s\t%s\n", r.IP, r.Hosts)
18
+	return int64(n), err
19
+}
20
+
21
+var defaultContent = []Record{
22
+	{Hosts: "localhost", IP: "127.0.0.1"},
23
+	{Hosts: "localhost ip6-localhost ip6-loopback", IP: "::1"},
24
+	{Hosts: "ip6-localnet", IP: "fe00::0"},
25
+	{Hosts: "ip6-mcastprefix", IP: "ff00::0"},
26
+	{Hosts: "ip6-allnodes", IP: "ff02::1"},
27
+	{Hosts: "ip6-allrouters", IP: "ff02::2"},
28
+}
29
+
30
+func Build(path, IP, hostname, domainname string, extraContent []Record) error {
20 31
 	content := bytes.NewBuffer(nil)
21 32
 	if IP != "" {
33
+		var mainRec Record
34
+		mainRec.IP = IP
22 35
 		if domainname != "" {
23
-			content.WriteString(fmt.Sprintf("%s\t%s.%s %s\n", IP, hostname, domainname, hostname))
36
+			mainRec.Hosts = fmt.Sprintf("%s.%s %s", hostname, domainname, hostname)
24 37
 		} else {
25
-			content.WriteString(fmt.Sprintf("%s\t%s\n", IP, hostname))
38
+			mainRec.Hosts = hostname
39
+		}
40
+		if _, err := mainRec.WriteTo(content); err != nil {
41
+			return err
26 42
 		}
27 43
 	}
28 44
 
29
-	for hosts, ip := range defaultContent {
30
-		if _, err := content.WriteString(fmt.Sprintf("%s\t%s\n", ip, hosts)); err != nil {
45
+	for _, r := range defaultContent {
46
+		if _, err := r.WriteTo(content); err != nil {
31 47
 			return err
32 48
 		}
33 49
 	}
34 50
 
35
-	if extraContent != nil {
36
-		for hosts, ip := range *extraContent {
37
-			if _, err := content.WriteString(fmt.Sprintf("%s\t%s\n", ip, hosts)); err != nil {
38
-				return err
39
-			}
51
+	for _, r := range extraContent {
52
+		if _, err := r.WriteTo(content); err != nil {
53
+			return err
40 54
 		}
41 55
 	}
42 56
 
... ...
@@ -7,6 +7,32 @@ import (
7 7
 	"testing"
8 8
 )
9 9
 
10
+func TestBuildDefault(t *testing.T) {
11
+	file, err := ioutil.TempFile("", "")
12
+	if err != nil {
13
+		t.Fatal(err)
14
+	}
15
+	defer os.Remove(file.Name())
16
+
17
+	// check that /etc/hosts has consistent ordering
18
+	for i := 0; i <= 5; i++ {
19
+		err = Build(file.Name(), "", "", "", nil)
20
+		if err != nil {
21
+			t.Fatal(err)
22
+		}
23
+
24
+		content, err := ioutil.ReadFile(file.Name())
25
+		if err != nil {
26
+			t.Fatal(err)
27
+		}
28
+		expected := "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n"
29
+
30
+		if expected != string(content) {
31
+			t.Fatalf("Expected to find '%s' got '%s'", expected, content)
32
+		}
33
+	}
34
+}
35
+
10 36
 func TestBuildHostnameDomainname(t *testing.T) {
11 37
 	file, err := ioutil.TempFile("", "")
12 38
 	if err != nil {