open-nomad/drivers/shared/hostnames/mount.go

83 lines
2.5 KiB
Go
Raw Normal View History

package hostnames
import (
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"strings"
"github.com/hashicorp/nomad/plugins/drivers"
)
// GenerateEtcHostsMount writes a /etc/hosts file using the network spec's
// hosts configuration, and returns a mount config so that task drivers can
// bind-mount it into the resulting task's filesystem. The extraHosts
// parameter is expected to be the same format as the extra_hosts field from
// the Docker or containerd drivers: []string{"<hostname>:<ip address>"}
func GenerateEtcHostsMount(taskDir string, conf *drivers.NetworkIsolationSpec, extraHosts []string) (*drivers.MountConfig, error) {
if conf == nil || conf.Mode != drivers.NetIsolationModeGroup {
return nil, nil
}
hostsCfg := conf.HostsConfig
if hostsCfg == nil || hostsCfg.Address == "" || hostsCfg.Hostname == "" {
return nil, nil
}
var content strings.Builder
fmt.Fprintf(&content, `# this file was generated by Nomad
127.0.0.1 localhost
::1 localhost
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
# this entry is the IP address and hostname of the allocation
# shared with tasks in the task group's network
%s %s
`, hostsCfg.Address, hostsCfg.Hostname)
if len(extraHosts) > 0 {
content.WriteString("\n# these entries are extra hosts added by the task config")
for _, hostLine := range extraHosts {
hostsEntry := strings.SplitN(hostLine, ":", 2)
if len(hostsEntry) != 2 {
return nil, fmt.Errorf("invalid hosts entry %q", hostLine)
}
if net.ParseIP(hostsEntry[1]) == nil {
return nil, fmt.Errorf("invalid IP address %q", hostLine)
}
content.WriteString(fmt.Sprintf("\n%s %s", hostsEntry[1], hostsEntry[0]))
}
content.WriteString("\n")
}
path := filepath.Join(taskDir, "hosts")
// tasks within an alloc should be able to share and modify the file, so
// only write to it if it doesn't exist
if _, err := os.Stat(path); os.IsNotExist(err) {
err := ioutil.WriteFile(path, []byte(content.String()), 0644)
if err != nil {
return nil, err
}
}
// Note that we're not setting readonly. The file is in the task dir
// anyways, so this lets the task overwrite its own hosts file if the
// application knows better than Nomad here. Task drivers may override
// this behavior.
mount := &drivers.MountConfig{
TaskPath: "/etc/hosts",
HostPath: path,
Readonly: false,
PropagationMode: "private",
}
return mount, nil
}