Skip to content

Commit

Permalink
support CNI status verb
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Zappa <[email protected]>
  • Loading branch information
Michael Zappa authored and MikeZappa87 committed Nov 18, 2024
1 parent 1c1be5e commit 8f10978
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 32 deletions.
10 changes: 10 additions & 0 deletions cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@ func (c *libcni) Status() error {
if len(c.networks) < c.networkCount {
return ErrCNINotInitialized
}

// STATUS is only called for CNI Version 1.1.0 or greater. It is ignored for previous versions.
for _, v := range c.networks {
err := c.cniConfig.GetStatusNetworkList(context.Background(), v.config)

if err != nil {
return err
}
}

return nil
}

Expand Down
68 changes: 36 additions & 32 deletions cni_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,21 +292,19 @@ func TestLibCNIType120(t *testing.T) {
// Get the default CNI config
l := defaultCNIConfig()
// Create a fake cni config directory and file
cniDir, confDir := makeFakeCNIConfig(t)
cniDir, confDir := buildFakeConfig(t)
defer tearDownCNIConfig(t, cniDir)
l.pluginConfDir = confDir
// Set the minimum network count as 2 for this test
l.networkCount = 2
err := l.Load(WithAllConf)
assert.NoError(t, err)

err = l.Status()
err := l.Load(WithLoNetwork, WithDefaultConf)
assert.NoError(t, err)

mockCNI := &MockCNI{}
l.cniConfig = mockCNI
l.networks[0].cni = mockCNI
l.networks[1].cni = mockCNI
ipv4, err := types.ParseCIDR("10.0.0.1/24")
ipv4, err := types.ParseCIDR("10.88.0.1/16")
assert.NoError(t, err)
expectedRT := &cnilibrary.RuntimeConf{
ContainerID: "container-id1",
Expand All @@ -315,59 +313,65 @@ func TestLibCNIType120(t *testing.T) {
Args: [][2]string(nil),
CapabilityArgs: map[string]interface{}{},
}
mockCNI.On("AddNetworkList", l.networks[0].config, expectedRT).Return(&types100.Result{
CNIVersion: "1.1.0",
Interfaces: []*types100.Interface{

loRT := &cnilibrary.RuntimeConf{
ContainerID: "container-id1",
NetNS: "/proc/12345/ns/net",
IfName: "lo",
Args: [][2]string(nil),
CapabilityArgs: map[string]interface{}{},
}

// mock for loopback
mockCNI.On("GetStatusNetworkList", l.networks[0].config).Return(nil)
mockCNI.On("AddNetworkList", l.networks[0].config, loRT).Return(&types040.Result{
CNIVersion: "0.3.1",
Interfaces: []*types040.Interface{
{
Name: "eth0",
Name: "lo",
},
},
IPs: []*types100.IPConfig{
IPs: []*types040.IPConfig{
{
Interface: types100.Int(0),
Address: *ipv4,
Gateway: net.ParseIP("10.0.0.255"),
Interface: types040.Int(0),
Address: net.IPNet{
IP: net.ParseIP("127.0.0.1"),
},
},
},
}, nil)
mockCNI.On("DelNetworkList", l.networks[0].config, expectedRT).Return(nil)
mockCNI.On("CheckNetworkList", l.networks[0].config, expectedRT).Return(nil)
ipv4, err = types.ParseCIDR("10.0.0.2/24")
assert.NoError(t, err)
l.networks[1].cni = mockCNI
expectedRT = &cnilibrary.RuntimeConf{
ContainerID: "container-id1",
NetNS: "/proc/12345/ns/net",
IfName: "eth1",
Args: [][2]string(nil),
CapabilityArgs: map[string]interface{}{},
}
mockCNI.On("DelNetworkList", l.networks[0].config, loRT).Return(nil)
mockCNI.On("CheckNetworkList", l.networks[0].config, loRT).Return(nil)

// mock for primary cni
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{
{
Name: "eth1",
Name: "eth0",
},
},
IPs: []*types100.IPConfig{
{
Interface: types100.Int(0),
Address: *ipv4,
Gateway: net.ParseIP("10.0.0.2"),
Gateway: net.ParseIP("10.88.0.1"),
},
},
}, nil)
mockCNI.On("DelNetworkList", l.networks[1].config, expectedRT).Return(nil)
mockCNI.On("CheckNetworkList", l.networks[1].config, expectedRT).Return(nil)
ctx := context.Background()

err = l.Status()
assert.NoError(t, err)

r, err := l.Setup(ctx, "container-id1", "/proc/12345/ns/net")
assert.NoError(t, err)
assert.Contains(t, r.Interfaces, "eth0")
assert.NotNil(t, r.Interfaces["eth0"].IPConfigs)
assert.Equal(t, r.Interfaces["eth0"].IPConfigs[0].IP.String(), "10.0.0.1")
assert.Contains(t, r.Interfaces, "eth1")
assert.NotNil(t, r.Interfaces["eth1"].IPConfigs)
assert.Equal(t, r.Interfaces["eth1"].IPConfigs[0].IP.String(), "10.0.0.2")
assert.Equal(t, r.Interfaces["eth0"].IPConfigs[0].IP.String(), "10.88.0.1")

err = l.Check(ctx, "container-id1", "/proc/12345/ns/net")
assert.NoError(t, err)
Expand Down
61 changes: 61 additions & 0 deletions testutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,64 @@ func tearDownCNIConfig(t *testing.T, confDir string) {
t.Fatalf("Failed to cleanup CNI configs: %v", err)
}
}

func buildFakeConfig(t *testing.T) (string, string) {
conf := `
{
"cniVersion": "1.1.0",
"name": "containerd-net",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"promiscMode": true,
"ipam": {
"type": "host-ipam",
"ranges": [
[{
"subnet": "10.88.0.0/16"
}],
[{
"subnet": "2001:4860:4860::/64"
}]
],
"routes": [
{ "dst": "0.0.0.0/0" },
{ "dst": "::/0" }
]
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}`

cniDir, err := makeTmpDir("fakecni")
if err != nil {
t.Fatalf("Failed to create plugin config dir: %v", err)
}

cniConfDir := path.Join(cniDir, "net.d")
err = os.MkdirAll(cniConfDir, 0777)
if err != nil {
t.Fatalf("Failed to create network config dir: %v", err)
}

networkConfig1 := path.Join(cniConfDir, "mocknetwork1.conflist")
f1, err := os.Create(networkConfig1)
if err != nil {
t.Fatalf("Failed to create network config %v: %v", f1, err)
}

_, err = f1.WriteString(conf)
if err != nil {
t.Fatalf("Failed to write network config file %v: %v", f1, err)
}
f1.Close()

return cniDir, cniConfDir
}

0 comments on commit 8f10978

Please sign in to comment.