diff options
author | baude <bbaude@redhat.com> | 2018-01-19 08:51:59 -0600 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-01-19 15:42:25 +0000 |
commit | a4701b56311d5d934543e2b4306b08baa844ec3f (patch) | |
tree | bcad38f7cf02a37107bfa61854a01eb58bf9868f /libpod/container_internal.go | |
parent | 1710acd18a4630ef704c66bf0cdae76dd658776a (diff) | |
download | podman-a4701b56311d5d934543e2b4306b08baa844ec3f.tar.gz podman-a4701b56311d5d934543e2b4306b08baa844ec3f.tar.bz2 podman-a4701b56311d5d934543e2b4306b08baa844ec3f.zip |
Add --dns-search, --dns-opt, --dns-server and --add-host.
Each of these options are destructive in nature, meaning if the user
adds one of them, all current ones are removed from the produced
resolv.conf.
* dns-server allows the user to specify dns servers.
* dns-opt allows the user to specify special resolv.conf options
* dns-search allows the user to specify search domains
The add-host option is not destructive and truly just adds the host
to /etc/hosts.
Signed-off-by: baude <bbaude@redhat.com>
Closes: #231
Approved by: mheon
Diffstat (limited to 'libpod/container_internal.go')
-rw-r--r-- | libpod/container_internal.go | 135 |
1 files changed, 129 insertions, 6 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index a9db43b08..c052f61fe 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -3,8 +3,10 @@ package libpod import ( "fmt" "io" + "io/ioutil" "os" "path/filepath" + "strings" "syscall" "time" @@ -13,7 +15,6 @@ import ( "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/namesgenerator" "github.com/docker/docker/pkg/stringid" - "github.com/mrunalp/fileutils" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -373,11 +374,18 @@ func (c *Container) cleanupStorage() error { return c.save() } -// copyHostFileToRundir copies the provided file to the runtimedir -func (c *Container) copyHostFileToRundir(sourcePath string) (string, error) { - destFileName := filepath.Join(c.state.RunDir, filepath.Base(sourcePath)) - if err := fileutils.CopyFile(sourcePath, destFileName); err != nil { - return "", err +// WriteStringToRundir copies the provided file to the runtimedir +func (c *Container) WriteStringToRundir(destFile, output string) (string, error) { + destFileName := filepath.Join(c.state.RunDir, destFile) + f, err := os.Create(destFileName) + if err != nil { + return "", errors.Wrapf(err, "unable to create %s", destFileName) + } + + defer f.Close() + _, err = f.WriteString(output) + if err != nil { + return "", errors.Wrapf(err, "unable to write %s", destFileName) } // Relabel runDirResolv for the container if err := label.Relabel(destFileName, c.config.MountLabel, false); err != nil { @@ -385,3 +393,118 @@ func (c *Container) copyHostFileToRundir(sourcePath string) (string, error) { } return destFileName, nil } + +type resolv struct { + nameServers []string + searchDomains []string + options []string +} + +// generateResolvConf generates a containers resolv.conf +func (c *Container) generateResolvConf() (string, error) { + // Copy /etc/resolv.conf to the container's rundir + resolvPath := "/etc/resolv.conf" + + // Check if the host system is using system resolve and if so + // copy its resolv.conf + if _, err := os.Stat("/run/systemd/resolve/resolv.conf"); err == nil { + resolvPath = "/run/systemd/resolve/resolv.conf" + } + orig, err := ioutil.ReadFile(resolvPath) + if err != nil { + return "", errors.Wrapf(err, "unable to read %s", resolvPath) + } + if len(c.config.DNSServer) == 0 && len(c.config.DNSSearch) == 0 && len(c.config.DNSOption) == 0 { + return c.WriteStringToRundir("resolv.conf", fmt.Sprintf("%s", orig)) + } + + // Read and organize the hosts /etc/resolv.conf + resolv := createResolv(string(orig[:])) + + // Populate the resolv struct with user's dns search domains + if len(c.config.DNSSearch) > 0 { + resolv.searchDomains = nil + // The . character means the user doesnt want any search domains in the container + if !StringInSlice(".", c.config.DNSSearch) { + resolv.searchDomains = append(resolv.searchDomains, c.Config().DNSSearch...) + } + } + + // Populate the resolv struct with user's dns servers + if len(c.config.DNSServer) > 0 { + resolv.nameServers = nil + for _, i := range c.config.DNSServer { + resolv.nameServers = append(resolv.nameServers, i.String()) + } + } + + // Populate the resolve struct with the users dns options + if len(c.config.DNSOption) > 0 { + resolv.options = nil + resolv.options = append(resolv.options, c.Config().DNSOption...) + } + return c.WriteStringToRundir("resolv.conf", resolv.ToString()) +} + +// createResolv creates a resolv struct from an input string +func createResolv(input string) resolv { + var resolv resolv + for _, line := range strings.Split(input, "\n") { + if strings.HasPrefix(line, "search") { + fields := strings.Fields(line) + if len(fields) < 2 { + logrus.Debugf("invalid resolv.conf line %s", line) + continue + } + resolv.searchDomains = append(resolv.searchDomains, fields[1:]...) + } else if strings.HasPrefix(line, "nameserver") { + fields := strings.Fields(line) + if len(fields) < 2 { + logrus.Debugf("invalid resolv.conf line %s", line) + continue + } + resolv.nameServers = append(resolv.nameServers, fields[1]) + } else if strings.HasPrefix(line, "options") { + fields := strings.Fields(line) + if len(fields) < 2 { + logrus.Debugf("invalid resolv.conf line %s", line) + continue + } + resolv.options = append(resolv.options, fields[1:]...) + } + } + return resolv +} + +//ToString returns a resolv struct in the form of a resolv.conf +func (r resolv) ToString() string { + var result string + // Populate the output string with search domains + result += fmt.Sprintf("search %s\n", strings.Join(r.searchDomains, " ")) + // Populate the output string with name servers + for _, i := range r.nameServers { + result += fmt.Sprintf("nameserver %s\n", i) + } + // Populate the output string with dns options + for _, i := range r.options { + result += fmt.Sprintf("options %s\n", i) + } + return result +} + +// generateHosts creates a containers hosts file +func (c *Container) generateHosts() (string, error) { + orig, err := ioutil.ReadFile("/etc/hosts") + if err != nil { + return "", errors.Wrapf(err, "unable to read /etc/hosts") + } + hosts := string(orig) + if len(c.config.HostAdd) > 0 { + for _, host := range c.config.HostAdd { + // the host format has already been verified at this point + fields := strings.Split(host, ":") + hosts += fmt.Sprintf("%s %s\n", fields[0], fields[1]) + } + } + return c.WriteStringToRundir("hosts", hosts) +} |