github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/drivers/shared/hostnames/mount.go (about)

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