mirror of
https://github.com/k8snetworkplumbingwg/multus-cni.git
synced 2025-09-10 13:22:14 +00:00
Fix multus to support CNI plugin which does not create interface
This change fixes multus to support CNI plugin which does not create any interface and return empty result. Some CNI plugin may do network configuration change only and does not create any interface and return empty CNI result. Current multus assumes that CNI config always creates some interfaces hence above CNI plugin is out of assumption and multus may not work with such plugins.
This commit is contained in:
@@ -369,12 +369,15 @@ func DelegateAdd(exec invoke.Exec, kubeClient *k8s.ClientInfo, pod *v1.Pod, dele
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pod != nil {
|
if pod != nil {
|
||||||
|
// check Interfaces and IPs because some CNI plugin just return empty result
|
||||||
|
if res.Interfaces != nil || res.IPs != nil {
|
||||||
// send kubernetes events
|
// send kubernetes events
|
||||||
if delegate.Name != "" {
|
if delegate.Name != "" {
|
||||||
kubeClient.Eventf(pod, v1.EventTypeNormal, "AddedInterface", "Add %s %v from %s", rt.IfName, ips, delegate.Name)
|
kubeClient.Eventf(pod, v1.EventTypeNormal, "AddedInterface", "Add %s %v from %s", rt.IfName, ips, delegate.Name)
|
||||||
} else {
|
} else {
|
||||||
kubeClient.Eventf(pod, v1.EventTypeNormal, "AddedInterface", "Add %s %v", rt.IfName, ips)
|
kubeClient.Eventf(pod, v1.EventTypeNormal, "AddedInterface", "Add %s %v", rt.IfName, ips)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// for further debug https://github.com/k8snetworkplumbingwg/multus-cni/issues/481
|
// for further debug https://github.com/k8snetworkplumbingwg/multus-cni/issues/481
|
||||||
logging.Errorf("DelegateAdd: pod nil pointer: namespace: %s, name: %s, container id: %s, pod: %v", rt.Args[1][1], rt.Args[2][1], rt.Args[3][1], pod)
|
logging.Errorf("DelegateAdd: pod nil pointer: namespace: %s, name: %s, container id: %s, pod: %v", rt.Args[1][1], rt.Args[2][1], rt.Args[3][1], pod)
|
||||||
@@ -636,6 +639,19 @@ func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (c
|
|||||||
return nil, cmdPluginErr(k8sArgs, netName, "error adding container to network %q: %v", netName, err)
|
return nil, cmdPluginErr(k8sArgs, netName, "error adding container to network %q: %v", netName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Master plugin result is always used if present
|
||||||
|
if delegate.MasterPlugin || result == nil {
|
||||||
|
result = tmpResult
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := cni100.NewResultFromResult(tmpResult)
|
||||||
|
if err != nil {
|
||||||
|
logging.Errorf("CmdAdd: failed to read result: %v, but proceed", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check Interfaces and IPs because some CNI plugin does not create any interface
|
||||||
|
// and just returns empty result
|
||||||
|
if res != nil && (res.Interfaces != nil || res.IPs != nil) {
|
||||||
// Remove gateway from routing table if the gateway is not used
|
// Remove gateway from routing table if the gateway is not used
|
||||||
deleteV4gateway := false
|
deleteV4gateway := false
|
||||||
deleteV6gateway := false
|
deleteV6gateway := false
|
||||||
@@ -695,10 +711,6 @@ func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (c
|
|||||||
return nil, cmdErr(k8sArgs, "error setting default gateway in cache: %v", err)
|
return nil, cmdErr(k8sArgs, "error setting default gateway in cache: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Master plugin result is always used if present
|
|
||||||
if delegate.MasterPlugin || result == nil {
|
|
||||||
result = tmpResult
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read devInfo from CNIDeviceInfoFile if it exists so
|
// Read devInfo from CNIDeviceInfoFile if it exists so
|
||||||
|
@@ -154,6 +154,67 @@ var _ = Describe("multus operations cniVersion 0.2.0 config", func() {
|
|||||||
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("executes delegates (plugin without interface)", func() {
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "123456789",
|
||||||
|
Netns: testNS.Path(),
|
||||||
|
IfName: "eth0",
|
||||||
|
StdinData: []byte(`{
|
||||||
|
"name": "node-cni-network",
|
||||||
|
"type": "multus",
|
||||||
|
"defaultnetworkfile": "/tmp/foo.multus.conf",
|
||||||
|
"defaultnetworkwaitseconds": 3,
|
||||||
|
"delegates": [{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "0.2.0",
|
||||||
|
"type": "weave-net"
|
||||||
|
},{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "0.2.0",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}]
|
||||||
|
}`),
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.SetLogLevel("verbose")
|
||||||
|
|
||||||
|
fExec := newFakeExec()
|
||||||
|
expectedResult1 := &types020.Result{
|
||||||
|
CNIVersion: "0.2.0",
|
||||||
|
IP4: &types020.IPConfig{
|
||||||
|
IP: *testhelpers.EnsureCIDR("1.1.1.2/24"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedConf1 := `{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "0.2.0",
|
||||||
|
"type": "weave-net"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin020(nil, "eth0", expectedConf1, expectedResult1, nil)
|
||||||
|
|
||||||
|
// other1 just returns empty result
|
||||||
|
expectedResult2 := &types020.Result{
|
||||||
|
CNIVersion: "0.2.0",
|
||||||
|
}
|
||||||
|
expectedConf2 := `{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "0.2.0",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin020(nil, "net1", expectedConf2, expectedResult2, nil)
|
||||||
|
|
||||||
|
result, err := CmdAdd(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(fExec.addIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
r := result.(*types020.Result)
|
||||||
|
// plugin 1 is the masterplugin
|
||||||
|
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
|
||||||
|
|
||||||
|
err = CmdDel(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
})
|
||||||
|
|
||||||
It("executes delegates given faulty namespace", func() {
|
It("executes delegates given faulty namespace", func() {
|
||||||
args := &skel.CmdArgs{
|
args := &skel.CmdArgs{
|
||||||
ContainerID: "123456789",
|
ContainerID: "123456789",
|
||||||
|
@@ -247,6 +247,67 @@ var _ = Describe("multus operations cniVersion 0.3.1 config", func() {
|
|||||||
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
|
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("executes delegates (plugin without interface)", func() {
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "123456789",
|
||||||
|
Netns: testNS.Path(),
|
||||||
|
IfName: "eth0",
|
||||||
|
StdinData: []byte(`{
|
||||||
|
"name": "node-cni-network",
|
||||||
|
"type": "multus",
|
||||||
|
"defaultnetworkfile": "/tmp/foo.multus.conf",
|
||||||
|
"defaultnetworkwaitseconds": 3,
|
||||||
|
"delegates": [{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "weave-net"
|
||||||
|
},{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}]
|
||||||
|
}`),
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.SetLogLevel("verbose")
|
||||||
|
|
||||||
|
fExec := newFakeExec()
|
||||||
|
expectedResult1 := &cni040.Result{
|
||||||
|
CNIVersion: "0.3.1",
|
||||||
|
IPs: []*cni040.IPConfig{{
|
||||||
|
Address: *testhelpers.EnsureCIDR("1.1.1.2/24"),
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
expectedConf1 := `{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "weave-net"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin040(nil, "eth0", expectedConf1, expectedResult1, nil)
|
||||||
|
|
||||||
|
// other1 just returns empty result
|
||||||
|
expectedResult2 := &cni040.Result{
|
||||||
|
CNIVersion: "0.3.1",
|
||||||
|
}
|
||||||
|
expectedConf2 := `{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin040(nil, "net1", expectedConf2, expectedResult2, nil)
|
||||||
|
|
||||||
|
result, err := CmdAdd(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(fExec.addIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
r := result.(*cni040.Result)
|
||||||
|
// plugin 1 is the masterplugin
|
||||||
|
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
|
||||||
|
|
||||||
|
err = CmdDel(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
})
|
||||||
|
|
||||||
It("fails when pod UID is provided and does not match Kube API pod UID", func() {
|
It("fails when pod UID is provided and does not match Kube API pod UID", func() {
|
||||||
fakePod := testhelpers.NewFakePod("testpod", "net1", "")
|
fakePod := testhelpers.NewFakePod("testpod", "net1", "")
|
||||||
net1 := `{
|
net1 := `{
|
||||||
|
@@ -192,6 +192,71 @@ var _ = Describe("multus operations cniVersion 1.0.0 config", func() {
|
|||||||
Expect(err).To(MatchError("[//:weave1]: error adding container to network \"weave1\": DelegateAdd: cannot set \"weave-net\" interface name to \"eth0\": validateIfName: no net namespace fsdadfad found: failed to Statfs \"fsdadfad\": no such file or directory"))
|
Expect(err).To(MatchError("[//:weave1]: error adding container to network \"weave1\": DelegateAdd: cannot set \"weave-net\" interface name to \"eth0\": validateIfName: no net namespace fsdadfad found: failed to Statfs \"fsdadfad\": no such file or directory"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("executes delegates (plugin without interface)", func() {
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "123456789",
|
||||||
|
Netns: testNS.Path(),
|
||||||
|
IfName: "eth0",
|
||||||
|
StdinData: []byte(`{
|
||||||
|
"name": "node-cni-network",
|
||||||
|
"type": "multus",
|
||||||
|
"defaultnetworkfile": "/tmp/foo.multus.conf",
|
||||||
|
"defaultnetworkwaitseconds": 3,
|
||||||
|
"delegates": [{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "1.0.0",
|
||||||
|
"type": "weave-net"
|
||||||
|
},{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "1.0.0",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}]
|
||||||
|
}`),
|
||||||
|
}
|
||||||
|
|
||||||
|
logging.SetLogLevel("verbose")
|
||||||
|
|
||||||
|
fExec := newFakeExec()
|
||||||
|
expectedResult1 := &cni100.Result{
|
||||||
|
CNIVersion: "1.0.0",
|
||||||
|
IPs: []*cni100.IPConfig{{
|
||||||
|
Address: *testhelpers.EnsureCIDR("1.1.1.2/24"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
expectedConf1 := `{
|
||||||
|
"name": "weave1",
|
||||||
|
"cniVersion": "1.0.0",
|
||||||
|
"type": "weave-net"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin100(nil, "eth0", expectedConf1, expectedResult1, nil)
|
||||||
|
|
||||||
|
// other1 just returns empty result
|
||||||
|
expectedResult2 := &cni100.Result{
|
||||||
|
CNIVersion: "0.4.0",
|
||||||
|
}
|
||||||
|
expectedConf2 := `{
|
||||||
|
"name": "other1",
|
||||||
|
"cniVersion": "1.0.0",
|
||||||
|
"type": "other-plugin"
|
||||||
|
}`
|
||||||
|
fExec.addPlugin100(nil, "net1", expectedConf2, expectedResult2, nil)
|
||||||
|
|
||||||
|
result, err := CmdAdd(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(fExec.addIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
// plugin 1 is the masterplugin
|
||||||
|
Expect(reflect.DeepEqual(result, expectedResult1)).To(BeTrue())
|
||||||
|
|
||||||
|
err = CmdCheck(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
err = CmdDel(args, fExec, nil)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(fExec.delIndex).To(Equal(len(fExec.plugins)))
|
||||||
|
})
|
||||||
|
|
||||||
It("returns the previous result using CmdCheck", func() {
|
It("returns the previous result using CmdCheck", func() {
|
||||||
args := &skel.CmdArgs{
|
args := &skel.CmdArgs{
|
||||||
ContainerID: "123456789",
|
ContainerID: "123456789",
|
||||||
|
Reference in New Issue
Block a user