diff --git a/cni.go b/cni.go index b10af47..d9a223a 100644 --- a/cni.go +++ b/cni.go @@ -30,6 +30,8 @@ import ( "github.com/containernetworking/cni/pkg/version" ) +const LoopbackNetworkName = "cni-loopback" + type CNI interface { // Setup setup the network for the namespace Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error) @@ -45,6 +47,8 @@ type CNI interface { Status() error // GetConfig returns a copy of the CNI plugin configurations as parsed by CNI GetConfig() *ConfigResult + // Status executes the status verb of the cni plugin + StatusDetail(context.Context) ([]*NetworkStatus, error) } type ConfigResult struct { @@ -310,3 +314,27 @@ func (c *libcni) GetConfig() *ConfigResult { func (c *libcni) reset() { c.networks = nil } + +// StatusDetail returns a slice of network statuses +func (c *libcni) StatusDetail(ctx context.Context) ([]*NetworkStatus, error) { + if err := c.Status(); err != nil { + return nil, err + } + + var networkStatuses []*NetworkStatus + + for _, network := range c.Networks() { + // Skip checking the status of the loopback network. It would have + // always returned the same thing, and is being deprecated anyway. + if network.config.Name == LoopbackNetworkName { + continue + } + + networkStatuses = append(networkStatuses, &NetworkStatus{ + Network: network, + Status: network.Status(ctx), + }) + } + + return networkStatuses, nil +} diff --git a/cni_test.go b/cni_test.go index ea7d1d5..9d0c4b6 100644 --- a/cni_test.go +++ b/cni_test.go @@ -315,6 +315,7 @@ func TestLibCNIType120(t *testing.T) { Args: [][2]string(nil), CapabilityArgs: map[string]interface{}{}, } + mockCNI.On("GetStatusNetworkList", l.networks[0].config).Return(nil) mockCNI.On("AddNetworkList", l.networks[0].config, expectedRT).Return(&types100.Result{ CNIVersion: "1.1.0", Interfaces: []*types100.Interface{ @@ -342,6 +343,7 @@ func TestLibCNIType120(t *testing.T) { Args: [][2]string(nil), CapabilityArgs: map[string]interface{}{}, } + mockCNI.On("GetStatusNetworkList", l.networks[1].config).Return(nil) mockCNI.On("AddNetworkList", l.networks[1].config, expectedRT).Return(&types100.Result{ CNIVersion: "1.1.0", Interfaces: []*types100.Interface{ @@ -374,6 +376,12 @@ func TestLibCNIType120(t *testing.T) { err = l.Remove(ctx, "container-id1", "/proc/12345/ns/net") assert.NoError(t, err) + + statuses, err := l.StatusDetail(ctx) + assert.NoError(t, err) + assert.Len(t, statuses, 2) + assert.Nil(t, statuses[0].Status) + assert.Nil(t, statuses[1].Status) } type MockCNI struct { diff --git a/namespace.go b/namespace.go index 319182b..af3c866 100644 --- a/namespace.go +++ b/namespace.go @@ -45,6 +45,10 @@ func (n *Network) Check(ctx context.Context, ns *Namespace) error { return n.cni.CheckNetworkList(ctx, n.config, ns.config(n.ifName)) } +func (n *Network) Status(ctx context.Context) error { + return n.cni.GetStatusNetworkList(ctx, n.config) +} + type Namespace struct { id string path string diff --git a/types.go b/types.go index 18616c0..92c6254 100644 --- a/types.go +++ b/types.go @@ -60,3 +60,8 @@ type DNS struct { // List of DNS options. Options []string } + +type NetworkStatus struct { + Network *Network + Status error +}