github.com/hernad/nomad@v1.6.112/drivers/shared/hostnames/mount.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package hostnames 5 6 import ( 7 "fmt" 8 "net" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/hernad/nomad/plugins/drivers" 14 ) 15 16 // GenerateEtcHostsMount writes a /etc/hosts file using the network spec's 17 // hosts configuration, and returns a mount config so that task drivers can 18 // bind-mount it into the resulting task's filesystem. The extraHosts 19 // parameter is expected to be the same format as the extra_hosts field from 20 // the Docker or containerd drivers: []string{"<hostname>:<ip address>"} 21 func GenerateEtcHostsMount(taskDir string, conf *drivers.NetworkIsolationSpec, extraHosts []string) (*drivers.MountConfig, error) { 22 if conf == nil || conf.Mode != drivers.NetIsolationModeGroup { 23 return nil, nil 24 } 25 hostsCfg := conf.HostsConfig 26 if hostsCfg == nil || hostsCfg.Address == "" || hostsCfg.Hostname == "" { 27 return nil, nil 28 } 29 30 var content strings.Builder 31 fmt.Fprintf(&content, `# this file was generated by Nomad 32 127.0.0.1 localhost 33 ::1 localhost 34 ::1 ip6-localhost ip6-loopback 35 fe00::0 ip6-localnet 36 ff00::0 ip6-mcastprefix 37 ff02::1 ip6-allnodes 38 ff02::2 ip6-allrouters 39 ff02::3 ip6-allhosts 40 41 # this entry is the IP address and hostname of the allocation 42 # shared with tasks in the task group's network 43 %s %s 44 `, hostsCfg.Address, hostsCfg.Hostname) 45 46 if len(extraHosts) > 0 { 47 content.WriteString("\n# these entries are extra hosts added by the task config") 48 for _, hostLine := range extraHosts { 49 hostsEntry := strings.SplitN(hostLine, ":", 2) 50 if len(hostsEntry) != 2 { 51 return nil, fmt.Errorf("invalid hosts entry %q", hostLine) 52 } 53 if net.ParseIP(hostsEntry[1]) == nil { 54 return nil, fmt.Errorf("invalid IP address %q", hostLine) 55 } 56 content.WriteString(fmt.Sprintf("\n%s %s", hostsEntry[1], hostsEntry[0])) 57 } 58 content.WriteString("\n") 59 } 60 61 path := filepath.Join(taskDir, "hosts") 62 63 // tasks within an alloc should be able to share and modify the file, so 64 // only write to it if it doesn't exist 65 if _, err := os.Stat(path); os.IsNotExist(err) { 66 err := os.WriteFile(path, []byte(content.String()), 0644) 67 if err != nil { 68 return nil, err 69 } 70 } 71 72 // Note that we're not setting readonly. The file is in the task dir 73 // anyways, so this lets the task overwrite its own hosts file if the 74 // application knows better than Nomad here. Task drivers may override 75 // this behavior. 76 mount := &drivers.MountConfig{ 77 TaskPath: "/etc/hosts", 78 HostPath: path, 79 Readonly: false, 80 PropagationMode: "private", 81 } 82 83 return mount, nil 84 }