mirror of
https://github.com/containers/podman.git
synced 2025-07-25 09:05:00 +08:00
Merge pull request #2518 from haircommander/pod_host
Append hosts to dependency container's /etc/hosts file
This commit is contained in:
@ -1231,6 +1231,23 @@ func (c *Container) writeStringToRundir(destFile, output string) (string, error)
|
|||||||
return filepath.Join(c.state.DestinationRunDir, destFile), nil
|
return filepath.Join(c.state.DestinationRunDir, destFile), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appendStringToRundir appends the provided string to the runtimedir file
|
||||||
|
func (c *Container) appendStringToRundir(destFile, output string) (string, error) {
|
||||||
|
destFileName := filepath.Join(c.state.RunDir, destFile)
|
||||||
|
|
||||||
|
f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrapf(err, "unable to open %s", destFileName)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if _, err := f.WriteString(output); err != nil {
|
||||||
|
return "", errors.Wrapf(err, "unable to write %s", destFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(c.state.DestinationRunDir, destFile), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Save OCI spec to disk, replacing any existing specs for the container
|
// Save OCI spec to disk, replacing any existing specs for the container
|
||||||
func (c *Container) saveSpec(spec *spec.Spec) error {
|
func (c *Container) saveSpec(spec *spec.Spec) error {
|
||||||
// If the OCI spec already exists, we need to replace it
|
// If the OCI spec already exists, we need to replace it
|
||||||
|
@ -698,13 +698,29 @@ func (c *Container) makeBindMounts() error {
|
|||||||
// If it doesn't, don't copy them
|
// If it doesn't, don't copy them
|
||||||
resolvPath, exists := bindMounts["/etc/resolv.conf"]
|
resolvPath, exists := bindMounts["/etc/resolv.conf"]
|
||||||
if exists {
|
if exists {
|
||||||
|
|
||||||
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
|
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if dependency container has an /etc/hosts file
|
||||||
hostsPath, exists := bindMounts["/etc/hosts"]
|
hostsPath, exists := bindMounts["/etc/hosts"]
|
||||||
if exists {
|
if !exists {
|
||||||
c.state.BindMounts["/etc/hosts"] = hostsPath
|
return errors.Errorf("error finding hosts file of dependency container %s for container %s", depCtr.ID(), c.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
depCtr.lock.Lock()
|
||||||
|
// generate a hosts file for the dependency container,
|
||||||
|
// based on either its old hosts file, or the default,
|
||||||
|
// and add the relevant information from the new container (hosts and IP)
|
||||||
|
hostsPath, err = depCtr.appendHosts(hostsPath, c)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
depCtr.lock.Unlock()
|
||||||
|
return errors.Wrapf(err, "error creating hosts file for container %s which depends on container %s", c.ID(), depCtr.ID())
|
||||||
|
}
|
||||||
|
depCtr.lock.Unlock()
|
||||||
|
|
||||||
|
// finally, save it in the new container
|
||||||
|
c.state.BindMounts["/etc/hosts"] = hostsPath
|
||||||
} else {
|
} else {
|
||||||
newResolv, err := c.generateResolvConf()
|
newResolv, err := c.generateResolvConf()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -712,7 +728,7 @@ func (c *Container) makeBindMounts() error {
|
|||||||
}
|
}
|
||||||
c.state.BindMounts["/etc/resolv.conf"] = newResolv
|
c.state.BindMounts["/etc/resolv.conf"] = newResolv
|
||||||
|
|
||||||
newHosts, err := c.generateHosts()
|
newHosts, err := c.generateHosts("/etc/hosts")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
|
return errors.Wrapf(err, "error creating hosts file for container %s", c.ID())
|
||||||
}
|
}
|
||||||
@ -854,12 +870,28 @@ func (c *Container) generateResolvConf() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generateHosts creates a containers hosts file
|
// generateHosts creates a containers hosts file
|
||||||
func (c *Container) generateHosts() (string, error) {
|
func (c *Container) generateHosts(path string) (string, error) {
|
||||||
orig, err := ioutil.ReadFile("/etc/hosts")
|
orig, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "unable to read /etc/hosts")
|
return "", errors.Wrapf(err, "unable to read %s", path)
|
||||||
}
|
}
|
||||||
hosts := string(orig)
|
hosts := string(orig)
|
||||||
|
hosts += c.getHosts()
|
||||||
|
return c.writeStringToRundir("hosts", hosts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendHosts appends a container's config and state pertaining to hosts to a container's
|
||||||
|
// local hosts file. netCtr is the container from which the netNS information is
|
||||||
|
// taken.
|
||||||
|
// path is the basis of the hosts file, into which netCtr's netNS information will be appended.
|
||||||
|
func (c *Container) appendHosts(path string, netCtr *Container) (string, error) {
|
||||||
|
return c.appendStringToRundir("hosts", netCtr.getHosts())
|
||||||
|
}
|
||||||
|
|
||||||
|
// getHosts finds the pertinent information for a container's host file in its config and state
|
||||||
|
// and returns a string in a format that can be written to the host file
|
||||||
|
func (c *Container) getHosts() string {
|
||||||
|
var hosts string
|
||||||
if len(c.config.HostAdd) > 0 {
|
if len(c.config.HostAdd) > 0 {
|
||||||
for _, host := range c.config.HostAdd {
|
for _, host := range c.config.HostAdd {
|
||||||
// the host format has already been verified at this point
|
// the host format has already been verified at this point
|
||||||
@ -871,7 +903,7 @@ func (c *Container) generateHosts() (string, error) {
|
|||||||
ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0]
|
ipAddress := strings.Split(c.state.NetworkStatus[0].IPs[0].Address.String(), "/")[0]
|
||||||
hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname())
|
hosts += fmt.Sprintf("%s\t%s\n", ipAddress, c.Hostname())
|
||||||
}
|
}
|
||||||
return c.writeStringToRundir("hosts", hosts)
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
// generatePasswd generates a container specific passwd file,
|
// generatePasswd generates a container specific passwd file,
|
||||||
|
@ -360,4 +360,21 @@ var _ = Describe("Podman pod create", func() {
|
|||||||
|
|
||||||
Expect(result.OutputToString()).To(ContainSubstring(infraID))
|
Expect(result.OutputToString()).To(ContainSubstring(infraID))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run --add-host in pod", func() {
|
||||||
|
session := podmanTest.Podman([]string{"pod", "create"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
podID := session.OutputToString()
|
||||||
|
|
||||||
|
// verify we can add a host to the infra's /etc/hosts
|
||||||
|
session = podmanTest.Podman([]string{"run", "--pod", podID, "--add-host", "foobar:127.0.0.1", BB, "ping", "-c", "1", "foobar"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
// verify we can see the other hosts of infra's /etc/hosts
|
||||||
|
session = podmanTest.Podman([]string{"run", "--pod", podID, BB, "ping", "-c", "1", "foobar"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user