2021-06-16 18:55:22 +00:00
|
|
|
package hostnames
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
2021-06-30 15:10:04 +00:00
|
|
|
"os"
|
2021-06-16 18:55:22 +00:00
|
|
|
"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")
|
2021-06-30 15:10:04 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
2021-06-16 18:55:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|