summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorjortkoopmans <jort@jabo-solutions.eu>2020-11-25 18:26:22 +0100
committerjortkoopmans <jort@jabo-solutions.eu>2020-11-25 18:27:31 +0100
commit5cfbe0b78e3672dd67cd028b85d816fc19d6a614 (patch)
tree375fe5a96bca7d04154daf63ac9b644ebb1adc34 /libpod
parenta18365c908d45a8ee9348c5e32a240a7b9a4091b (diff)
downloadpodman-5cfbe0b78e3672dd67cd028b85d816fc19d6a614.tar.gz
podman-5cfbe0b78e3672dd67cd028b85d816fc19d6a614.tar.bz2
podman-5cfbe0b78e3672dd67cd028b85d816fc19d6a614.zip
squash
Signed-off-by: jortkoopmans <jort@jabo-solutions.eu>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go55
-rw-r--r--libpod/container_api.go14
-rw-r--r--libpod/container_internal.go37
-rw-r--r--libpod/healthcheck_linux.go4
-rw-r--r--libpod/image/manifests.go36
-rw-r--r--libpod/network/config.go10
-rw-r--r--libpod/network/create.go1
-rw-r--r--libpod/network/netconflist.go7
-rw-r--r--libpod/network/subnet.go14
-rw-r--r--libpod/network/subnet_test.go62
-rw-r--r--libpod/networking_linux.go28
-rw-r--r--libpod/rootless_cni_linux.go4
12 files changed, 193 insertions, 79 deletions
diff --git a/libpod/container.go b/libpod/container.go
index 4b9e6a5ba..e954d84eb 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -13,10 +13,12 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/lock"
+ "github.com/containers/podman/v2/pkg/rootless"
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// CgroupfsDefaultCgroupParent is the cgroup parent for CGroupFS in libpod
@@ -920,19 +922,39 @@ func (c *Container) CGroupPath() (string, error) {
return "", errors.Wrapf(define.ErrNoCgroups, "this container is not creating cgroups")
}
- // Read /proc/[PID]/cgroup and look at the first line. cgroups(7)
- // nails it down to three fields with the 3rd pointing to the cgroup's
- // path which works both on v1 and v2.
+ // Read /proc/[PID]/cgroup and find the *longest* cgroup entry. That's
+ // needed to account for hacks in cgroups v1, where each line in the
+ // file could potentially point to a cgroup. The longest one, however,
+ // is the libpod-specific one we're looking for.
+ //
+ // See #8397 on the need for the longest-path look up.
procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID)
lines, err := ioutil.ReadFile(procPath)
if err != nil {
return "", err
}
- fields := bytes.Split(bytes.Split(lines, []byte("\n"))[0], []byte(":"))
- if len(fields) != 3 {
- return "", errors.Errorf("expected 3 fields but got %d: %s", len(fields), procPath)
+
+ var cgroupPath string
+ for _, line := range bytes.Split(lines, []byte("\n")) {
+ // cgroups(7) nails it down to three fields with the 3rd
+ // pointing to the cgroup's path which works both on v1 and v2.
+ fields := bytes.Split(line, []byte(":"))
+ if len(fields) != 3 {
+ logrus.Debugf("Error parsing cgroup: expected 3 fields but got %d: %s", len(fields), procPath)
+ continue
+ }
+ path := string(fields[2])
+ if len(path) > len(cgroupPath) {
+ cgroupPath = path
+ }
+
}
- return string(fields[2]), nil
+
+ if len(cgroupPath) == 0 {
+ return "", errors.Errorf("could not find any cgroup in %q", procPath)
+ }
+
+ return cgroupPath, nil
}
// RootFsSize returns the root FS size of the container
@@ -1074,13 +1096,17 @@ func (c *Container) Umask() string {
// values at runtime via network connect and disconnect.
// If the container is configured to use CNI and this function returns an empty
// array, the container will still be connected to the default network.
-func (c *Container) Networks() ([]string, error) {
+// The second return parameter, a bool, indicates that the container container
+// is joining the default CNI network - the network name will be included in the
+// returned array of network names, but the container did not explicitly join
+// this network.
+func (c *Container) Networks() ([]string, bool, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.syncContainer(); err != nil {
- return nil, err
+ return nil, false, err
}
}
@@ -1088,19 +1114,22 @@ func (c *Container) Networks() ([]string, error) {
}
// Unlocked accessor for networks
-func (c *Container) networks() ([]string, error) {
+func (c *Container) networks() ([]string, bool, error) {
networks, err := c.runtime.state.GetNetworks(c)
if err != nil && errors.Cause(err) == define.ErrNoSuchNetwork {
- return c.config.Networks, nil
+ if len(c.config.Networks) == 0 && !rootless.IsRootless() {
+ return []string{c.runtime.netPlugin.GetDefaultNetworkName()}, true, nil
+ }
+ return c.config.Networks, false, nil
}
- return networks, err
+ return networks, false, err
}
// networksByNameIndex provides us with a map of container networks where key
// is network name and value is the index position
func (c *Container) networksByNameIndex() (map[string]int, error) {
- networks, err := c.networks()
+ networks, _, err := c.networks()
if err != nil {
return nil, err
}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index a9808a30e..6a7ddc421 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -714,3 +714,17 @@ func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOpti
defer c.newContainerEvent(events.Restore)
return c.restore(ctx, options)
}
+
+// Indicate whether or not the container should restart
+func (c *Container) ShouldRestart(ctx context.Context) bool {
+ logrus.Debugf("Checking if container %s should restart", c.ID())
+ if !c.batched {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if err := c.syncContainer(); err != nil {
+ return false
+ }
+ }
+ return c.shouldRestart()
+}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 108954bad..b6a3244ea 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -206,37 +206,39 @@ func (c *Container) handleExitFile(exitFile string, fi os.FileInfo) error {
return nil
}
-// Handle container restart policy.
-// This is called when a container has exited, and was not explicitly stopped by
-// an API call to stop the container or pod it is in.
-func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr error) {
- // If we did not get a restart policy match, exit immediately.
+func (c *Container) shouldRestart() bool {
+ // If we did not get a restart policy match, return false
// Do the same if we're not a policy that restarts.
if !c.state.RestartPolicyMatch ||
c.config.RestartPolicy == RestartPolicyNo ||
c.config.RestartPolicy == RestartPolicyNone {
- return false, nil
+ return false
}
// If we're RestartPolicyOnFailure, we need to check retries and exit
// code.
if c.config.RestartPolicy == RestartPolicyOnFailure {
if c.state.ExitCode == 0 {
- return false, nil
+ return false
}
// If we don't have a max retries set, continue
if c.config.RestartRetries > 0 {
- if c.state.RestartCount < c.config.RestartRetries {
- logrus.Debugf("Container %s restart policy trigger: on retry %d (of %d)",
- c.ID(), c.state.RestartCount, c.config.RestartRetries)
- } else {
- logrus.Debugf("Container %s restart policy trigger: retries exhausted", c.ID())
- return false, nil
+ if c.state.RestartCount >= c.config.RestartRetries {
+ return false
}
}
}
+ return true
+}
+// Handle container restart policy.
+// This is called when a container has exited, and was not explicitly stopped by
+// an API call to stop the container or pod it is in.
+func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr error) {
+ if !c.shouldRestart() {
+ return false, nil
+ }
logrus.Debugf("Restarting container %s due to restart policy %s", c.ID(), c.config.RestartPolicy)
// Need to check if dependencies are alive.
@@ -641,18 +643,13 @@ func (c *Container) removeIPv4Allocations() error {
cniDefaultNetwork = c.runtime.netPlugin.GetDefaultNetworkName()
}
- networks, err := c.networks()
+ networks, _, err := c.networks()
if err != nil {
return err
}
- switch {
- case len(networks) > 0 && len(networks) != len(c.state.NetworkStatus):
+ if len(networks) != len(c.state.NetworkStatus) {
return errors.Wrapf(define.ErrInternal, "network mismatch: asked to join %d CNI networks but got %d CNI results", len(networks), len(c.state.NetworkStatus))
- case len(networks) == 0 && len(c.state.NetworkStatus) != 1:
- return errors.Wrapf(define.ErrInternal, "network mismatch: did not specify CNI networks but joined more than one (%d)", len(c.state.NetworkStatus))
- case len(networks) == 0 && cniDefaultNetwork == "":
- return errors.Wrapf(define.ErrInternal, "could not retrieve name of CNI default network")
}
for index, result := range c.state.NetworkStatus {
diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go
index b0f1ff35d..0ad15da09 100644
--- a/libpod/healthcheck_linux.go
+++ b/libpod/healthcheck_linux.go
@@ -26,6 +26,10 @@ func (c *Container) createTimer() error {
if rootless.IsRootless() {
cmd = append(cmd, "--user")
}
+ path := os.Getenv("PATH")
+ if path != "" {
+ cmd = append(cmd, "--setenv=PATH="+path)
+ }
cmd = append(cmd, "--unit", c.ID(), fmt.Sprintf("--on-unit-inactive=%s", c.HealthCheckConfig().Interval.String()), "--timer-property=AccuracySec=1s", podman, "healthcheck", "run", c.ID())
conn, err := systemd.ConnectToDBUS()
diff --git a/libpod/image/manifests.go b/libpod/image/manifests.go
index 59678fdb2..14f7c2f83 100644
--- a/libpod/image/manifests.go
+++ b/libpod/image/manifests.go
@@ -2,13 +2,14 @@ package image
import (
"context"
+ "fmt"
"github.com/containers/buildah/manifests"
+ "github.com/containers/image/v5/docker"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
- "github.com/pkg/errors"
)
// Options for adding a manifest
@@ -69,19 +70,10 @@ func CreateManifestList(rt *Runtime, systemContext types.SystemContext, names []
list := manifests.Create()
opts := ManifestAddOpts{Images: names, All: all}
for _, img := range imgs {
- var ref types.ImageReference
- newImage, err := rt.NewFromLocal(img)
- if err == nil {
- ir, err := newImage.toImageRef(context.Background())
- if err != nil {
- return "", err
- }
- if ir == nil {
- return "", errors.New("unable to convert image to ImageReference")
- }
- ref = ir.Reference()
- } else {
- ref, err = alltransports.ParseImageName(img)
+ ref, err := alltransports.ParseImageName(img)
+ if err != nil {
+ dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+ ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, img))
if err != nil {
return "", err
}
@@ -134,18 +126,10 @@ func addManifestToList(ref types.ImageReference, list manifests.List, systemCont
// AddManifest adds a manifest to a given manifest list.
func (i *Image) AddManifest(systemContext types.SystemContext, opts ManifestAddOpts) (string, error) {
- var (
- ref types.ImageReference
- )
- newImage, err := i.imageruntime.NewFromLocal(opts.Images[0])
- if err == nil {
- ir, err := newImage.toImageRef(context.Background())
- if err != nil {
- return "", err
- }
- ref = ir.Reference()
- } else {
- ref, err = alltransports.ParseImageName(opts.Images[0])
+ ref, err := alltransports.ParseImageName(opts.Images[0])
+ if err != nil {
+ dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+ ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, opts.Images[0]))
if err != nil {
return "", err
}
diff --git a/libpod/network/config.go b/libpod/network/config.go
index ce8a4446c..ce351129e 100644
--- a/libpod/network/config.go
+++ b/libpod/network/config.go
@@ -129,6 +129,16 @@ func (f FirewallConfig) Bytes() ([]byte, error) {
return json.MarshalIndent(f, "", "\t")
}
+// TuningConfig describes the tuning plugin
+type TuningConfig struct {
+ PluginType string `json:"type"`
+}
+
+// Bytes outputs the configuration as []byte
+func (f TuningConfig) Bytes() ([]byte, error) {
+ return json.MarshalIndent(f, "", "\t")
+}
+
// DNSNameConfig describes the dns container name resolution plugin config
type DNSNameConfig struct {
PluginType string `json:"type"`
diff --git a/libpod/network/create.go b/libpod/network/create.go
index 387f4fcd3..7e4fc574a 100644
--- a/libpod/network/create.go
+++ b/libpod/network/create.go
@@ -176,6 +176,7 @@ func createBridge(name string, options entities.NetworkCreateOptions, runtimeCon
plugins = append(plugins, bridge)
plugins = append(plugins, NewPortMapPlugin())
plugins = append(plugins, NewFirewallPlugin())
+ plugins = append(plugins, NewTuningPlugin())
// if we find the dnsname plugin or are rootless, we add configuration for it
// the rootless-cni-infra container has the dnsname plugin always installed
if (HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) || rootless.IsRootless()) && !options.DisableDNS {
diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go
index 111f1715c..ee9adce14 100644
--- a/libpod/network/netconflist.go
+++ b/libpod/network/netconflist.go
@@ -119,6 +119,13 @@ func NewFirewallPlugin() FirewallConfig {
}
}
+// NewTuningPlugin creates a generic tuning section
+func NewTuningPlugin() TuningConfig {
+ return TuningConfig{
+ PluginType: "tuning",
+ }
+}
+
// NewDNSNamePlugin creates the dnsname config with a given
// domainname
func NewDNSNamePlugin(domainName string) DNSNameConfig {
diff --git a/libpod/network/subnet.go b/libpod/network/subnet.go
index 90f0cdfce..120038e57 100644
--- a/libpod/network/subnet.go
+++ b/libpod/network/subnet.go
@@ -54,14 +54,10 @@ func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
ones, bits := cidr.Mask.Size()
if ones == bits {
- return FirstIPInSubnet(cidr)
+ return cidr.IP, nil
}
- hostStart := ones / 8
- // Handle the first host byte
- cidr.IP[hostStart] |= 0xff & cidr.Mask[hostStart]
- // Fill the rest with ones
- for i := hostStart; i < len(cidr.IP); i++ {
- cidr.IP[i] = 0xff
+ for i := range cidr.IP {
+ cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i]
}
return cidr.IP, nil
}
@@ -73,6 +69,10 @@ func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
if err != nil {
return nil, err
}
+ ones, bits := cidr.Mask.Size()
+ if ones == bits {
+ return cidr.IP, nil
+ }
cidr.IP[len(cidr.IP)-1]++
return cidr.IP, nil
}
diff --git a/libpod/network/subnet_test.go b/libpod/network/subnet_test.go
index 917c3be88..55b2443bd 100644
--- a/libpod/network/subnet_test.go
+++ b/libpod/network/subnet_test.go
@@ -33,3 +33,65 @@ func TestNextSubnet(t *testing.T) {
})
}
}
+
+func TestFirstIPInSubnet(t *testing.T) {
+ tests := []struct {
+ name string
+ args *net.IPNet
+ want net.IP
+ wantErr bool
+ }{
+ {"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.0.1"), false},
+ {"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.1"), false},
+ {"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.0.1"), false},
+ {"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.1"), false},
+ {"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.129"), false},
+ {"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.0.0.1"), false},
+ {"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
+ {"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
+ }
+ for _, tt := range tests {
+ test := tt
+ t.Run(test.name, func(t *testing.T) {
+ got, err := FirstIPInSubnet(test.args)
+ if (err != nil) != test.wantErr {
+ t.Errorf("FirstIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
+ return
+ }
+ if !got.Equal(test.want) {
+ t.Errorf("FirstIPInSubnet() got = %v, want %v", got, test.want)
+ }
+ })
+ }
+}
+
+func TestLastIPInSubnet(t *testing.T) {
+ tests := []struct {
+ name string
+ args *net.IPNet
+ want net.IP
+ wantErr bool
+ }{
+ {"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.255.255"), false},
+ {"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.255"), false},
+ {"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.1.255"), false},
+ {"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.127"), false},
+ {"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.191"), false},
+ {"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.255.255.255"), false},
+ {"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
+ {"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
+ }
+ for _, tt := range tests {
+ test := tt
+ t.Run(test.name, func(t *testing.T) {
+ got, err := LastIPInSubnet(test.args)
+ if (err != nil) != test.wantErr {
+ t.Errorf("LastIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
+ return
+ }
+ if !got.Equal(test.want) {
+ t.Errorf("LastIPInSubnet() got = %v, want %v", got, test.want)
+ }
+ })
+ }
+}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 8dce7c9fe..4e7ffaf81 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -110,10 +110,15 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
podName := getCNIPodName(ctr)
- networks, err := ctr.networks()
+ networks, _, err := ctr.networks()
if err != nil {
return nil, err
}
+ // All networks have been removed from the container.
+ // This is effectively forcing net=none.
+ if len(networks) == 0 {
+ return nil, nil
+ }
// Update container map of interface descriptions
if err := ctr.setupNetworkDescriptions(networks); err != nil {
@@ -224,7 +229,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
if ctr.config.NetMode.IsSlirp4netns() {
return r.setupSlirp4netns(ctr)
}
- networks, err := ctr.networks()
+ networks, _, err := ctr.networks()
if err != nil {
return err
}
@@ -744,13 +749,13 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
- networks, err := ctr.networks()
+ networks, _, err := ctr.networks()
if err != nil {
return err
}
// rootless containers do not use the CNI plugin directly
- if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() {
+ if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() && len(networks) > 0 {
var requestedIP net.IP
if ctr.requestedIP != nil {
requestedIP = ctr.requestedIP
@@ -863,7 +868,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
settings := new(define.InspectNetworkSettings)
settings.Ports = makeInspectPortBindings(c.config.PortMappings)
- networks, err := c.networks()
+ networks, isDefault, err := c.networks()
if err != nil {
return nil, err
}
@@ -872,7 +877,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
if c.state.NetNS == nil {
// We still want to make dummy configurations for each CNI net
// the container joined.
- if len(networks) > 0 {
+ if len(networks) > 0 && !isDefault {
settings.Networks = make(map[string]*define.InspectAdditionalNetwork, len(networks))
for _, net := range networks {
cniNet := new(define.InspectAdditionalNetwork)
@@ -893,9 +898,9 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
}
// If we have CNI networks - handle that here
- if len(networks) > 0 {
+ if len(networks) > 0 && !isDefault {
if len(networks) != len(c.state.NetworkStatus) {
- return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(networks), len(c.state.NetworkStatus))
+ return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI network(s) %v, but have information on %d network(s)", len(networks), networks, len(c.state.NetworkStatus))
}
settings.Networks = make(map[string]*define.InspectAdditionalNetwork)
@@ -1101,7 +1106,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
return err
}
- ctrNetworks, err := c.networks()
+ ctrNetworks, _, err := c.networks()
if err != nil {
return err
}
@@ -1139,8 +1144,8 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
// build a list of network names so we can sort and
// get the new name's index
var networkNames []string
- for netName := range networks {
- networkNames = append(networkNames, netName)
+ for name := range networks {
+ networkNames = append(networkNames, name)
}
networkNames = append(networkNames, netName)
// sort
@@ -1152,6 +1157,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
// populate network status
copy(networkStatus[index+1:], networkStatus[index:])
networkStatus[index] = networkResults[0]
+ c.state.NetworkStatus = networkStatus
}
c.newNetworkEvent(events.NetworkConnect, netName)
return c.save()
diff --git a/libpod/rootless_cni_linux.go b/libpod/rootless_cni_linux.go
index 1d6158cc2..2c2977f9f 100644
--- a/libpod/rootless_cni_linux.go
+++ b/libpod/rootless_cni_linux.go
@@ -40,7 +40,7 @@ const (
//
// AllocRootlessCNI does not lock c. c should be already locked.
func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.Result, error) {
- networks, err := c.networks()
+ networks, _, err := c.networks()
if err != nil {
return nil, nil, err
}
@@ -81,7 +81,7 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
//
// DeallocRootlessCNI does not lock c. c should be already locked.
func DeallocRootlessCNI(ctx context.Context, c *Container) error {
- networks, err := c.networks()
+ networks, _, err := c.networks()
if err != nil {
return err
}