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  }