diff options
author | Paul Holzinger <pholzing@redhat.com> | 2022-04-19 18:47:32 +0200 |
---|---|---|
committer | Paul Holzinger <pholzing@redhat.com> | 2022-04-22 13:05:53 +0200 |
commit | cf1b0c1965c9cc7f3b6d870720ba78865c8602e4 (patch) | |
tree | ce4a5f7c43dabcd562488b6a74cb8b1344e6deba | |
parent | 128086639c6317c324c32423765c72f38c115f74 (diff) | |
download | podman-cf1b0c1965c9cc7f3b6d870720ba78865c8602e4.tar.gz podman-cf1b0c1965c9cc7f3b6d870720ba78865c8602e4.tar.bz2 podman-cf1b0c1965c9cc7f3b6d870720ba78865c8602e4.zip |
network dis-/connect: update /etc/hosts
When we connect or disconnect from a network we also have to update
/etc/hosts to ensure we only have valid entries in there.
This also fixes problems with docker-compose since this makes use of
network connect/disconnect.
Fixes #12533
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
-rw-r--r-- | libpod/networking_linux.go | 70 | ||||
-rw-r--r-- | test/system/500-networking.bats | 15 |
2 files changed, 73 insertions, 12 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 71e29f18f..41beaf41d 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -20,7 +20,9 @@ import ( "time" "github.com/containernetworking/plugins/pkg/ns" + "github.com/containers/common/libnetwork/etchosts" "github.com/containers/common/libnetwork/types" + "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/netns" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" @@ -1282,15 +1284,35 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro for _, ip := range oldStatus.DNSServerIPs { stringIPs = append(stringIPs, ip.String()) } - if len(stringIPs) == 0 { - return nil + if len(stringIPs) > 0 { + logrus.Debugf("Removing DNS Servers %v from resolv.conf", stringIPs) + if err := c.removeNameserver(stringIPs); err != nil { + return err + } } - logrus.Debugf("Removing DNS Servers %v from resolv.conf", stringIPs) - if err := c.removeNameserver(stringIPs); err != nil { - return err + + // update /etc/hosts file + if file, ok := c.state.BindMounts[config.DefaultHostsFile]; ok { + // sync the names with c.getHostsEntries() + names := []string{c.Hostname(), c.config.Name} + rm := etchosts.GetNetworkHostEntries(map[string]types.StatusBlock{netName: oldStatus}, names...) + if len(rm) > 0 { + // make sure to lock this file to prevent concurrent writes when + // this is used a net dependency container + lock, err := lockfile.GetLockfile(file) + if err != nil { + return fmt.Errorf("failed to lock hosts file: %w", err) + } + logrus.Debugf("Remove /etc/hosts entries %v", rm) + lock.Lock() + err = etchosts.Remove(file, rm) + lock.Unlock() + if err != nil { + return err + } + } } } - return nil } @@ -1361,6 +1383,13 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe return errors.New("when adding aliases, results must be of length 1") } + // we need to get the old host entries before we add the new one to the status + // if we do not add do it here we will get the wrong existing entries which will throw of the logic + // we could also copy the map but this does not seem worth it + // sync the hostNames with c.getHostsEntries() + hostNames := []string{c.Hostname(), c.config.Name} + oldHostEntries := etchosts.GetNetworkHostEntries(networkStatus, hostNames...) + // update network status if networkStatus == nil { networkStatus = make(map[string]types.StatusBlock, 1) @@ -1394,12 +1423,31 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe } stringIPs = append(stringIPs, ip.String()) } - if len(stringIPs) == 0 { - return nil + if len(stringIPs) > 0 { + logrus.Debugf("Adding DNS Servers %v to resolv.conf", stringIPs) + if err := c.addNameserver(stringIPs); err != nil { + return err + } } - logrus.Debugf("Adding DNS Servers %v to resolv.conf", stringIPs) - if err := c.addNameserver(stringIPs); err != nil { - return err + + // update /etc/hosts file + if file, ok := c.state.BindMounts[config.DefaultHostsFile]; ok { + // make sure to lock this file to prevent concurrent writes when + // this is used a net dependency container + lock, err := lockfile.GetLockfile(file) + if err != nil { + return fmt.Errorf("failed to lock hosts file: %w", err) + } + new := etchosts.GetNetworkHostEntries(results, hostNames...) + logrus.Debugf("Add /etc/hosts entries %v", new) + // use special AddIfExists API to make sure we only add new entries if an old one exists + // see the AddIfExists() comment for more information + lock.Lock() + err = etchosts.AddIfExists(file, oldHostEntries, new) + lock.Unlock() + if err != nil { + return err + } } return nil diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index f57c3dbd7..274af7ec5 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -469,9 +469,17 @@ load helpers run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").Aliases}}" is "$output" "[${cid:0:12}]" "short container id in network aliases" + # check /etc/hosts for our entry + run_podman exec $cid cat /etc/hosts + is "$output" ".*$ip.*" "hosts contain expected ip" + run_podman network disconnect $netname $cid is "$output" "" "Output should be empty (no errors)" + # check /etc/hosts again, the entry should be gone now + run_podman exec $cid cat /etc/hosts + assert "$output" !~ "$ip" "IP ($ip) should no longer be in /etc/hosts" + # check that we cannot curl (timeout after 3 sec) run curl --max-time 3 -s $SERVER/index.txt assert $status -ne 0 \ @@ -487,13 +495,18 @@ load helpers # check that we have a new ip and mac # if the ip is still the same this whole test turns into a nop run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").IPAddress}}" - assert "$output" != "$ip" \ + new_ip="$output" + assert "$new_ip" != "$ip" \ "IP address did not change after podman network disconnect/connect" run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}" assert "$output" != "$mac" \ "MAC address did not change after podman network disconnect/connect" + # check /etc/hosts for the new entry + run_podman exec $cid cat /etc/hosts + is "$output" ".*$new_ip.*" "hosts contain expected new ip" + # Disconnect/reconnect of a container *with no ports* should succeed quietly run_podman network disconnect $netname $background_cid is "$output" "" "disconnect of container with no open ports" |