multus: fail if given pod UID does not match Kube API pod UID

If the runtime passes a pod UID via K8S_POD_UID (which both CRIO and
containerd do as of mid-2021) then fail if the pod we get from the
Kube API has a different UID. This would indicate that the pod was
deleted and recreated while Multus was attempting to set up
networking for the old pod instance's sandbox, and it's pointless
to continue setting up a sandbox for a dead pod instance.

Also pass the pod UID through to plugins so they can perform
additional checking and validation on the pods they get from the
Kube API.

Signed-off-by: Dan Williams <dcbw@redhat.com>
This commit is contained in:
Dan Williams 2021-10-21 10:44:29 -05:00 committed by Tomofumi Hayashi
parent 392726842f
commit cb19a22cb9
6 changed files with 327 additions and 203 deletions

View File

@ -114,11 +114,16 @@ func SetNetworkStatus(client *ClientInfo, k8sArgs *types.K8sArgs, netStatus []ne
podName := string(k8sArgs.K8S_POD_NAME) podName := string(k8sArgs.K8S_POD_NAME)
podNamespace := string(k8sArgs.K8S_POD_NAMESPACE) podNamespace := string(k8sArgs.K8S_POD_NAMESPACE)
podUID := string(k8sArgs.K8S_POD_UID)
pod, err := client.GetPod(podNamespace, podName) pod, err := client.GetPod(podNamespace, podName)
if err != nil { if err != nil {
return logging.Errorf("SetNetworkStatus: failed to query the pod %v in out of cluster comm: %v", podName, err) return logging.Errorf("SetNetworkStatus: failed to query the pod %v in out of cluster comm: %v", podName, err)
} }
if podUID != "" && string(pod.UID) != podUID {
return logging.Errorf("SetNetworkStatus: expected pod %s/%s UID %q but got %q from Kube API", podNamespace, podName, podUID, pod.UID)
}
if netStatus != nil { if netStatus != nil {
err = netutils.SetNetworkStatus(client.Client, pod, netStatus) err = netutils.SetNetworkStatus(client.Client, pod, netStatus)
if err != nil { if err != nil {

View File

@ -55,6 +55,9 @@ var _ = Describe("k8sclient operations", func() {
var tmpDir string var tmpDir string
var err error var err error
var genericConf string var genericConf string
var args *skel.CmdArgs
const fakePodName string = "testPod"
BeforeEach(func() { BeforeEach(func() {
tmpDir, err = ioutil.TempDir("", "multus_tmp") tmpDir, err = ioutil.TempDir("", "multus_tmp")
@ -69,6 +72,11 @@ var _ = Describe("k8sclient operations", func() {
}], }],
"kubeconfig":"/etc/kubernetes/node-kubeconfig.yaml" "kubeconfig":"/etc/kubernetes/node-kubeconfig.yaml"
}` }`
args = &skel.CmdArgs{
// Values come from NewFakePod()
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_UID=%s", fakePodName, "test", "testUID"),
}
}) })
AfterEach(func() { AfterEach(func() {
@ -77,7 +85,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves delegates from kubernetes using simple format annotation", func() { It("retrieves delegates from kubernetes using simple format annotation", func() {
fakePod := testutils.NewFakePod("testpod", "net1,net2", "") fakePod := testutils.NewFakePod(fakePodName, "net1,net2", "")
net1 := `{ net1 := `{
"name": "net1", "name": "net1",
"type": "mynet", "type": "mynet",
@ -94,10 +102,6 @@ var _ = Describe("k8sclient operations", func() {
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -130,15 +134,12 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails when the network does not exist", func() { It("fails when the network does not exist", func() {
fakePod := testutils.NewFakePod("testpod", "net1,net2", "") fakePod := testutils.NewFakePod(fakePodName, "net1,net2", "")
net3 := `{ net3 := `{
"name": "net3", "name": "net3",
"type": "mynet3", "type": "mynet3",
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -160,7 +161,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves delegates from kubernetes using JSON format annotation", func() { It("retrieves delegates from kubernetes using JSON format annotation", func() {
fakePod := testutils.NewFakePod("testpod", `[ fakePod := testutils.NewFakePod(fakePodName, `[
{"name":"net1"}, {"name":"net1"},
{ {
"name":"net2", "name":"net2",
@ -172,9 +173,6 @@ var _ = Describe("k8sclient operations", func() {
"namespace":"other-ns" "namespace":"other-ns"
} }
]`, "") ]`, "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -218,10 +216,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails when the JSON format annotation is invalid", func() { It("fails when the JSON format annotation is invalid", func() {
fakePod := testutils.NewFakePod("testpod", "[adsfasdfasdfasf]", "") fakePod := testutils.NewFakePod(fakePodName, "[adsfasdfasdfasf]", "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -236,7 +231,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("can set the default-gateway on an additional interface", func() { It("can set the default-gateway on an additional interface", func() {
fakePod := testutils.NewFakePod("testpod", `[ fakePod := testutils.NewFakePod(fakePodName, `[
{"name":"net1"}, {"name":"net1"},
{ {
"name":"net2", "name":"net2",
@ -247,9 +242,6 @@ var _ = Describe("k8sclient operations", func() {
"namespace":"other-ns" "namespace":"other-ns"
} }
]`, "") ]`, "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -294,10 +286,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves delegates from kubernetes using on-disk config files", func() { It("retrieves delegates from kubernetes using on-disk config files", func() {
fakePod := testutils.NewFakePod("testpod", "net1,net2", "") fakePod := testutils.NewFakePod(fakePodName, "net1,net2", "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -338,10 +327,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("injects network name into minimal thick plugin CNI config", func() { It("injects network name into minimal thick plugin CNI config", func() {
fakePod := testutils.NewFakePod("testpod", "net1", "") fakePod := testutils.NewFakePod(fakePodName, "net1", "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -365,10 +351,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails when on-disk config file is not valid", func() { It("fails when on-disk config file is not valid", func() {
fakePod := testutils.NewFakePod("testpod", "net1,net2", "") fakePod := testutils.NewFakePod(fakePodName, "net1,net2", "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -399,7 +382,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves cluster network from CRD", func() { It("retrieves cluster network from CRD", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -409,10 +392,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -431,7 +410,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves default networks from CRD", func() { It("retrieves default networks from CRD", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -442,10 +421,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -469,7 +444,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("ignore default networks from CRD in case of kube-system namespace", func() { It("ignore default networks from CRD in case of kube-system namespace", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
// overwrite namespace // overwrite namespace
fakePod.ObjectMeta.Namespace = "kube-system" fakePod.ObjectMeta.Namespace = "kube-system"
conf := `{ conf := `{
@ -482,10 +457,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -507,7 +478,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves cluster network from file", func() { It("retrieves cluster network from file", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -518,10 +489,6 @@ var _ = Describe("k8sclient operations", func() {
netConf.ConfDir = tmpDir netConf.ConfDir = tmpDir
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -546,7 +513,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("retrieves cluster network from path", func() { It("retrieves cluster network from path", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
conf := fmt.Sprintf(`{ conf := fmt.Sprintf(`{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -556,10 +523,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -582,7 +545,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("Error in case of CRD not found", func() { It("Error in case of CRD not found", func() {
fakePod := testutils.NewFakePod("testpod", "", "") fakePod := testutils.NewFakePod(fakePodName, "", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -592,10 +555,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -608,7 +567,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("overwrite cluster network when Pod annotation is set", func() { It("overwrite cluster network when Pod annotation is set", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -619,10 +578,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -650,7 +605,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails with bad confdir", func() { It("fails with bad confdir", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -661,10 +616,6 @@ var _ = Describe("k8sclient operations", func() {
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -686,7 +637,7 @@ var _ = Describe("k8sclient operations", func() {
It("overwrite multus config when Pod annotation is set", func() { It("overwrite multus config when Pod annotation is set", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -701,10 +652,6 @@ var _ = Describe("k8sclient operations", func() {
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2")) Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -723,7 +670,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails with no kubeclient and invalid kubeconfig", func() { It("fails with no kubeclient and invalid kubeconfig", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -738,10 +685,6 @@ var _ = Describe("k8sclient operations", func() {
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2")) Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -757,7 +700,7 @@ var _ = Describe("k8sclient operations", func() {
}) })
It("fails with no kubeclient and no kubeconfig", func() { It("fails with no kubeclient and no kubeconfig", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -772,10 +715,6 @@ var _ = Describe("k8sclient operations", func() {
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2")) Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -821,7 +760,7 @@ users:
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBMUxyZmUxaXNQaTNDYng4eHRDWG1QTlE2L0xXYVVEa1ZRNVBkdGtQK3dVYmdJUFJ6CmNtRzNEcnUya0kvamsxMGQzaUgzOVZlZDlHVjczbnZyVm5Id0pzZEF5QzVmYlRTQVBUVVNJOW90MVFGbENRUGcKQ2JLbjBRbmxUeUhXMmNnTis2Q3BWK0U4dFpWajJ2cDZoTDlmR0s2bUJCL2I4VFN3RmYxRmtnWC9hTGN1emZDaApmVFNDOWlRTk15cEFjamZadEkzWiszbHVzSVB6TVpBNTZPZXNodzlnRkJHUkw3RzZHWmZKcG9OaGVxTDlmandUClRkNURlbVZXcUxUR05ZNWhhV3hicy9VbThuM0QvdlV1QkVPYTYxQ2cvcGljUkU3Um14SmFJRWJiQlNTV1dkSDMKWDlrem5RdHJrUXloL28xZnpSV1pxeWFCY3hxR1FWN0JSSzFtSndJREFRQUJBb0lCQUJ0bjA4QzFSTU5oNjhtYgpFREV3TE1BcmEwb0JMMWNrYzN2WVFkam9XNXFVd2UwYzhQNk1YaVAweE9sTTBEbTg1a3NtdnlZSldwMFFzZXVRCnRWbldwZVNwQ015QlJPUHh2bytrRmFrdXczYk1qaktpSUN1L3EyVC96RjNzY3h4dGJIZTlVL094WGJ2YStobE0KNlpuT2ViYlpVU1A0NHNIcFVzSVNkZk1BK00ySmg1UFJibGZWaUFEY1hxNFR5RU1JaStzRkhOcFIrdmdWZzRFawp4RmFVaS83V0E2YUxWVzBUTzREdjMwbTJ0TVczWXN1bk1LTU0xOTNyUEZrU0dEdFpheWV2Z0JDeURXaFhOTEo2Clh1cTNxSUg4bFE2bzRBUjMvcDc1ZW9hOCtrVzVmT3o2UWF3WnpPYlBENkRCQlVOYVM1YklXaVV1dmx5L0JlM20KZnlxK3NRRUNnWUVBMW84R3l6ODk2bFhwdU1yVXVsb2orbGp5U0FaNkpLOCsyaFMvQnpyREx6NlpvY3FzKzg3awpVUkwzKy9LL1pja2pIMVVDeXROVVZ6Q3RKaG4zZmdLS2dpQWhsU0pNRzhqc05sbEkydFZSazNZZ1RCcUg2bXZxCit3citsTUxoUDZxbWFObUx3QXljY2lEanpMdXlRdjhVOFhKazJOdVFsQlFwbkt2eWJIRGdxSUVDZ1lFQS9kRnMKazNlYmRNNFAxV2psYXJoRTV5blpuRmdQbDg1L2Vudk4rQ1oxcStlMGxYendaUGswdWdJUWozYyt2UEpLWlh0OApLWk1HQjM0N2VLNlFIL3J1a2xRWXlLOStHeUV1YnRJQUZ2NWFrYXZxV1haR1p5ZC9QdDR1V09adXMrd3BnSG00CkxFY0lzZElsYkpFY2RJTzJyb3FaY0VNY3FEbGtXcTdwQWxqU2VxY0NnWUJYdUQ0RTFxUlByRFJVRXNrS0wxUksKUkJjNkR6dmN4N0VncEI2OXErNms0Q2tibHF0R2YvMmtqK2JISVNYVFRYcUlrczhEY1ljbjVvVEQ4UlhZZE4xLworZmNBNi9iRjNVMkZvdGRBY0xwYldZNDJ6eG9HWTN5OGluQXZEY1hkcTcxQlhML2dFc2ZiZVVycEowdm9URFdaCnlUVWwzQTZ1RzlndmI3VTdWS0xsQVFLQmdBTmNscmVOU2YzT0ROK2l1QWNsMGFQT0poZXdBdVRiMDB4bi8xNWUKQkFqMjFLbDJNaWprTkJLU25HMktBc2ExM3M1aFNFKzBwc3ZLbkRjSStOZXpseDFSQjlNQW9BYno5WTE2TW80YgphRSt0bXpqOEhBcVp0MUc1MTV0TjBnR0lDelNzYUFnT0dNdGlJU1RDOTBHRHpST2F1bFdHVGdiY1c3dm52U1pPCnp0clpBb0dBWmtIRWV5em16Z2cxR3dtTzN3bmljSHRMR1BQRFhiSW53NTdsdkIrY3lyd0FrVEs1MlFScTM0VkMKRDhnQWFwMTU2OWlWUER3YlgrNkpBQk1WQ2tNUmdxMjdHanUzN0pVY2Fib2g1YzJQeTBYNUlhUG8rek1hWHgvQwpqbjUvUW5YandjU1MrRU5hL1lXVWcxWEVjQjJYdEM0UExCdGUycitrUTVLbFNOREcxSTQ9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==` client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBMUxyZmUxaXNQaTNDYng4eHRDWG1QTlE2L0xXYVVEa1ZRNVBkdGtQK3dVYmdJUFJ6CmNtRzNEcnUya0kvamsxMGQzaUgzOVZlZDlHVjczbnZyVm5Id0pzZEF5QzVmYlRTQVBUVVNJOW90MVFGbENRUGcKQ2JLbjBRbmxUeUhXMmNnTis2Q3BWK0U4dFpWajJ2cDZoTDlmR0s2bUJCL2I4VFN3RmYxRmtnWC9hTGN1emZDaApmVFNDOWlRTk15cEFjamZadEkzWiszbHVzSVB6TVpBNTZPZXNodzlnRkJHUkw3RzZHWmZKcG9OaGVxTDlmandUClRkNURlbVZXcUxUR05ZNWhhV3hicy9VbThuM0QvdlV1QkVPYTYxQ2cvcGljUkU3Um14SmFJRWJiQlNTV1dkSDMKWDlrem5RdHJrUXloL28xZnpSV1pxeWFCY3hxR1FWN0JSSzFtSndJREFRQUJBb0lCQUJ0bjA4QzFSTU5oNjhtYgpFREV3TE1BcmEwb0JMMWNrYzN2WVFkam9XNXFVd2UwYzhQNk1YaVAweE9sTTBEbTg1a3NtdnlZSldwMFFzZXVRCnRWbldwZVNwQ015QlJPUHh2bytrRmFrdXczYk1qaktpSUN1L3EyVC96RjNzY3h4dGJIZTlVL094WGJ2YStobE0KNlpuT2ViYlpVU1A0NHNIcFVzSVNkZk1BK00ySmg1UFJibGZWaUFEY1hxNFR5RU1JaStzRkhOcFIrdmdWZzRFawp4RmFVaS83V0E2YUxWVzBUTzREdjMwbTJ0TVczWXN1bk1LTU0xOTNyUEZrU0dEdFpheWV2Z0JDeURXaFhOTEo2Clh1cTNxSUg4bFE2bzRBUjMvcDc1ZW9hOCtrVzVmT3o2UWF3WnpPYlBENkRCQlVOYVM1YklXaVV1dmx5L0JlM20KZnlxK3NRRUNnWUVBMW84R3l6ODk2bFhwdU1yVXVsb2orbGp5U0FaNkpLOCsyaFMvQnpyREx6NlpvY3FzKzg3awpVUkwzKy9LL1pja2pIMVVDeXROVVZ6Q3RKaG4zZmdLS2dpQWhsU0pNRzhqc05sbEkydFZSazNZZ1RCcUg2bXZxCit3citsTUxoUDZxbWFObUx3QXljY2lEanpMdXlRdjhVOFhKazJOdVFsQlFwbkt2eWJIRGdxSUVDZ1lFQS9kRnMKazNlYmRNNFAxV2psYXJoRTV5blpuRmdQbDg1L2Vudk4rQ1oxcStlMGxYendaUGswdWdJUWozYyt2UEpLWlh0OApLWk1HQjM0N2VLNlFIL3J1a2xRWXlLOStHeUV1YnRJQUZ2NWFrYXZxV1haR1p5ZC9QdDR1V09adXMrd3BnSG00CkxFY0lzZElsYkpFY2RJTzJyb3FaY0VNY3FEbGtXcTdwQWxqU2VxY0NnWUJYdUQ0RTFxUlByRFJVRXNrS0wxUksKUkJjNkR6dmN4N0VncEI2OXErNms0Q2tibHF0R2YvMmtqK2JISVNYVFRYcUlrczhEY1ljbjVvVEQ4UlhZZE4xLworZmNBNi9iRjNVMkZvdGRBY0xwYldZNDJ6eG9HWTN5OGluQXZEY1hkcTcxQlhML2dFc2ZiZVVycEowdm9URFdaCnlUVWwzQTZ1RzlndmI3VTdWS0xsQVFLQmdBTmNscmVOU2YzT0ROK2l1QWNsMGFQT0poZXdBdVRiMDB4bi8xNWUKQkFqMjFLbDJNaWprTkJLU25HMktBc2ExM3M1aFNFKzBwc3ZLbkRjSStOZXpseDFSQjlNQW9BYno5WTE2TW80YgphRSt0bXpqOEhBcVp0MUc1MTV0TjBnR0lDelNzYUFnT0dNdGlJU1RDOTBHRHpST2F1bFdHVGdiY1c3dm52U1pPCnp0clpBb0dBWmtIRWV5em16Z2cxR3dtTzN3bmljSHRMR1BQRFhiSW53NTdsdkIrY3lyd0FrVEs1MlFScTM0VkMKRDhnQWFwMTU2OWlWUER3YlgrNkpBQk1WQ2tNUmdxMjdHanUzN0pVY2Fib2g1YzJQeTBYNUlhUG8rek1hWHgvQwpqbjUvUW5YandjU1MrRU5hL1lXVWcxWEVjQjJYdEM0UExCdGUycitrUTVLbFNOREcxSTQ9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==`
kubeletconf.Write([]byte(kubeletconfDef)) kubeletconf.Write([]byte(kubeletconfDef))
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := fmt.Sprintf(`{ conf := fmt.Sprintf(`{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -836,10 +775,6 @@ users:
Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2")) Expect(netConf.Delegates[0].Conf.Type).To(Equal("mynet2"))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -854,7 +789,7 @@ users:
}) })
It("Errors when namespace isolation is violated", func() { It("Errors when namespace isolation is violated", func() {
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -875,10 +810,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -902,7 +833,7 @@ users:
}) })
It("Properly allows a specified namespace reference when namespace isolation is enabled", func() { It("Properly allows a specified namespace reference when namespace isolation is enabled", func() {
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -924,10 +855,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -958,7 +885,7 @@ users:
Context("getDefaultNetDelegateCRD", func() { Context("getDefaultNetDelegateCRD", func() {
It("fails when netConf contains bad confDir", func() { It("fails when netConf contains bad confDir", func() {
fakePod := testutils.NewFakePod("testpod", "", "net1") fakePod := testutils.NewFakePod(fakePodName, "", "net1")
conf := `{ conf := `{
"name":"node-cni-network", "name":"node-cni-network",
"type":"multus", "type":"multus",
@ -969,10 +896,6 @@ users:
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -992,9 +915,9 @@ users:
Context("GetK8sArgs", func() { Context("GetK8sArgs", func() {
It("fails when provided with bad format", func() { It("fails when provided with bad format", func() {
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
args := &skel.CmdArgs{ args = &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME:%s;K8S_POD_NAMESPACE:%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace), Args: fmt.Sprintf("K8S_POD_NAME:%s;K8S_POD_NAMESPACE:%s;K8S_POD_UID:%s", fakePod.Name, fakePod.Namespace, fakePod.UID),
} }
// using colon instead of equals sign makes an invalid CmdArgs // using colon instead of equals sign makes an invalid CmdArgs
@ -1005,7 +928,7 @@ users:
Context("getKubernetesDelegate", func() { Context("getKubernetesDelegate", func() {
It("failed to get a ResourceClient instance", func() { It("failed to get a ResourceClient instance", func() {
fakePod := testutils.NewFakePod("testpod", "net1,net2", "") fakePod := testutils.NewFakePod(fakePodName, "net1,net2", "")
net1 := `{ net1 := `{
"name": "net1", "name": "net1",
"type": "mynet", "type": "mynet",
@ -1021,9 +944,6 @@ users:
"type": "mynet3", "type": "mynet3",
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
// args := &skel.CmdArgs{
// Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
// }
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -1051,10 +971,7 @@ users:
Context("parsePodNetworkObjectName", func() { Context("parsePodNetworkObjectName", func() {
It("fails to get podnetwork given bad annotation values", func() { It("fails to get podnetwork given bad annotation values", func() {
fakePod := testutils.NewFakePod("testpod", "net1", "") fakePod := testutils.NewFakePod(fakePodName, "net1", "")
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
@ -1087,7 +1004,7 @@ users:
Context("setPodNetworkAnnotation", func() { Context("setPodNetworkAnnotation", func() {
It("Sets pod network annotations without error", func() { It("Sets pod network annotations without error", func() {
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
net1 := `{ net1 := `{
"name": "net1", "name": "net1",
@ -1095,10 +1012,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1172,10 +1085,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err := clientInfo.AddPod(fakePod) _, err := clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1183,6 +1092,9 @@ users:
_, err = clientInfo.AddNetAttachDef(testutils.NewFakeNetAttachDef("kube-system", "net1", net1)) _, err = clientInfo.AddNetAttachDef(testutils.NewFakeNetAttachDef("kube-system", "net1", net1))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
args = &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_UID=%s", fakePod.Name, fakePod.Namespace, "blahblah"),
}
k8sArgs, err := GetK8sArgs(args) k8sArgs, err := GetK8sArgs(args)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1209,7 +1121,7 @@ users:
// TODO Still figuring this next one out. deals with exponentialBackoff // TODO Still figuring this next one out. deals with exponentialBackoff
// It("Fails to set pod network annotations without error", func() { // It("Fails to set pod network annotations without error", func() {
// fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") // fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
// net1 := `{ // net1 := `{
// "name": "net1", // "name": "net1",
@ -1217,10 +1129,6 @@ users:
// "cniVersion": "0.2.0" // "cniVersion": "0.2.0"
// }` // }`
// args := &skel.CmdArgs{
// Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
// }
// clientInfo := NewFakeClientInfo() // clientInfo := NewFakeClientInfo()
// _, err := clientInfo.AddPod(fakePod) // _, err := clientInfo.AddPod(fakePod)
// Expect(err).NotTo(HaveOccurred()) // Expect(err).NotTo(HaveOccurred())
@ -1240,7 +1148,7 @@ users:
}) })
Context("SetNetworkStatus", func() { Context("SetNetworkStatus", func() {
It("Sets network status without error", func() { It("Sets network status without error when pod UIDs match", func() {
result := &types020.Result{ result := &types020.Result{
CNIVersion: "0.2.0", CNIVersion: "0.2.0",
IP4: &types020.IPConfig{ IP4: &types020.IPConfig{
@ -1271,7 +1179,7 @@ users:
netstatus := []nettypes.NetworkStatus{*delegateNetStatus} netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1282,10 +1190,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1299,6 +1203,123 @@ users:
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}) })
It("Sets pod network annotations without error when runtime does not provide a pod UID", func() {
result := &types020.Result{
CNIVersion: "0.2.0",
IP4: &types020.IPConfig{
IP: *testutils.EnsureCIDR("1.1.1.2/24"),
},
}
conf := `{
"name": "node-cni-network",
"type": "multus",
"kubeconfig": "/etc/kubernetes/node-kubeconfig.yaml",
"delegates": [{
"type": "weave-net"
}],
"runtimeConfig": {
"portMappings": [
{"hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
]
}
}`
delegate, err := types.LoadDelegateNetConf([]byte(conf), nil, "0000:00:00.0", "")
Expect(err).NotTo(HaveOccurred())
delegateNetStatus, err := netutils.CreateNetworkStatus(result, delegate.Conf.Name, delegate.MasterPlugin, nil)
GinkgoT().Logf("delegateNetStatus %+v\n", delegateNetStatus)
Expect(err).NotTo(HaveOccurred())
netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred())
net1 := `{
"name": "net1",
"type": "mynet",
"cniVersion": "0.2.0"
}`
clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred())
_, err = clientInfo.AddNetAttachDef(testutils.NewFakeNetAttachDef("kube-system", "net1", net1))
Expect(err).NotTo(HaveOccurred())
args = &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.Name, fakePod.Namespace),
}
k8sArgs, err := GetK8sArgs(args)
Expect(err).NotTo(HaveOccurred())
err = SetNetworkStatus(clientInfo, k8sArgs, netstatus, netConf)
Expect(err).NotTo(HaveOccurred())
})
It("Fails to set pod network annotations when pod UIDs don't match", func() {
result := &types020.Result{
CNIVersion: "0.2.0",
IP4: &types020.IPConfig{
IP: *testutils.EnsureCIDR("1.1.1.2/24"),
},
}
conf := `{
"name": "node-cni-network",
"type": "multus",
"kubeconfig": "/etc/kubernetes/node-kubeconfig.yaml",
"delegates": [{
"type": "weave-net"
}],
"runtimeConfig": {
"portMappings": [
{"hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
]
}
}`
delegate, err := types.LoadDelegateNetConf([]byte(conf), nil, "0000:00:00.0", "")
Expect(err).NotTo(HaveOccurred())
delegateNetStatus, err := netutils.CreateNetworkStatus(result, delegate.Conf.Name, delegate.MasterPlugin, nil)
GinkgoT().Logf("delegateNetStatus %+v\n", delegateNetStatus)
Expect(err).NotTo(HaveOccurred())
netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred())
net1 := `{
"name": "net1",
"type": "mynet",
"cniVersion": "0.2.0"
}`
clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred())
_, err = clientInfo.AddNetAttachDef(testutils.NewFakeNetAttachDef("kube-system", "net1", net1))
Expect(err).NotTo(HaveOccurred())
args = &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_UID=%s", fakePod.Name, fakePod.Namespace, "foobar"),
}
k8sArgs, err := GetK8sArgs(args)
Expect(err).NotTo(HaveOccurred())
err = SetNetworkStatus(clientInfo, k8sArgs, netstatus, netConf)
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("expected pod %s/%s UID %q but got %q from Kube API",
fakePod.Namespace, fakePod.Name, string(k8sArgs.K8S_POD_UID), fakePod.UID)))
})
It("Sets network status with kubeclient built from kubeconfig and attempts to connect", func() { It("Sets network status with kubeclient built from kubeconfig and attempts to connect", func() {
kubeletconf, err := os.Create("/etc/kubernetes/kubelet.conf") kubeletconf, err := os.Create("/etc/kubernetes/kubelet.conf")
kubeletconfDef := `apiVersion: v1 kubeletconfDef := `apiVersion: v1
@ -1353,7 +1374,7 @@ users:
netstatus := []nettypes.NetworkStatus{*delegateNetStatus} netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1364,10 +1385,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1413,7 +1430,7 @@ users:
netstatus := []nettypes.NetworkStatus{*delegateNetStatus} netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1424,10 +1441,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1472,7 +1485,7 @@ users:
netstatus := []nettypes.NetworkStatus{*delegateNetStatus} netstatus := []nettypes.NetworkStatus{*delegateNetStatus}
fakePod := testutils.NewFakePod("testpod", "kube-system/net1", "") fakePod := testutils.NewFakePod(fakePodName, "kube-system/net1", "")
netConf, err := types.LoadNetConf([]byte(conf)) netConf, err := types.LoadNetConf([]byte(conf))
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1483,10 +1496,6 @@ users:
"cniVersion": "0.2.0" "cniVersion": "0.2.0"
}` }`
args := &skel.CmdArgs{
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", fakePod.ObjectMeta.Name, fakePod.ObjectMeta.Namespace),
}
clientInfo := NewFakeClientInfo() clientInfo := NewFakeClientInfo()
_, err = clientInfo.AddPod(fakePod) _, err = clientInfo.AddPod(fakePod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())

View File

@ -496,7 +496,7 @@ func delPlugins(exec invoke.Exec, pod *v1.Pod, args *skel.CmdArgs, k8sArgs *type
func cmdErr(k8sArgs *types.K8sArgs, format string, args ...interface{}) error { func cmdErr(k8sArgs *types.K8sArgs, format string, args ...interface{}) error {
prefix := "Multus: " prefix := "Multus: "
if k8sArgs != nil { if k8sArgs != nil {
prefix += fmt.Sprintf("[%s/%s]: ", k8sArgs.K8S_POD_NAMESPACE, k8sArgs.K8S_POD_NAME) prefix += fmt.Sprintf("[%s/%s/%s]: ", k8sArgs.K8S_POD_NAMESPACE, k8sArgs.K8S_POD_NAME, k8sArgs.K8S_POD_UID)
} }
return logging.Errorf(prefix+format, args...) return logging.Errorf(prefix+format, args...)
} }
@ -504,7 +504,7 @@ func cmdErr(k8sArgs *types.K8sArgs, format string, args ...interface{}) error {
func cmdPluginErr(k8sArgs *types.K8sArgs, confName string, format string, args ...interface{}) error { func cmdPluginErr(k8sArgs *types.K8sArgs, confName string, format string, args ...interface{}) error {
msg := "" msg := ""
if k8sArgs != nil { if k8sArgs != nil {
msg += fmt.Sprintf("[%s/%s:%s]: ", k8sArgs.K8S_POD_NAMESPACE, k8sArgs.K8S_POD_NAME, confName) msg += fmt.Sprintf("[%s/%s/%s:%s]: ", k8sArgs.K8S_POD_NAMESPACE, k8sArgs.K8S_POD_NAME, k8sArgs.K8S_POD_UID, confName)
} }
return logging.Errorf(msg+format, args...) return logging.Errorf(msg+format, args...)
} }
@ -521,6 +521,43 @@ func isCriticalRequestRetriable(err error) bool {
return false return false
} }
func getPod(kubeClient *k8s.ClientInfo, k8sArgs *types.K8sArgs, ignoreNotFound bool) (*v1.Pod, error) {
if kubeClient == nil {
return nil, nil
}
podNamespace := string(k8sArgs.K8S_POD_NAMESPACE)
podName := string(k8sArgs.K8S_POD_NAME)
podUID := string(k8sArgs.K8S_POD_UID)
pod, err := kubeClient.GetPod(podNamespace, podName)
if err != nil {
// in case of a retriable error, retry 10 times with 0.25 sec interval
if isCriticalRequestRetriable(err) {
waitErr := wait.PollImmediate(shortPollDuration, shortPollTimeout, func() (bool, error) {
pod, err = kubeClient.GetPod(podNamespace, podName)
return pod != nil, err
})
// retry failed, then return error with retry out
if waitErr != nil {
return nil, cmdErr(k8sArgs, "error waiting for pod: %v", err)
}
} else if ignoreNotFound && errors.IsNotFound(err) {
// If not found, proceed to remove interface with cache
return nil, nil
} else {
// Other case, return error
return nil, cmdErr(k8sArgs, "error getting pod: %v", err)
}
}
if podUID != "" && string(pod.UID) != podUID {
return nil, cmdErr(k8sArgs, "expected pod UID %q but got %q from Kube API", podUID, pod.UID)
}
return pod, nil
}
//CmdAdd ... //CmdAdd ...
func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (cnitypes.Result, error) { func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (cnitypes.Result, error) {
n, err := types.LoadNetConf(args.StdinData) n, err := types.LoadNetConf(args.StdinData)
@ -549,26 +586,9 @@ func CmdAdd(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) (c
} }
} }
pod := (*v1.Pod)(nil) pod, err := getPod(kubeClient, k8sArgs, false)
if kubeClient != nil { if err != nil {
pod, err = kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME)) return nil, err
if err != nil {
var waitErr error
// in case of a retriable error, retry 10 times with 0.25 sec interval
if isCriticalRequestRetriable(err) {
waitErr = wait.PollImmediate(shortPollDuration, shortPollTimeout, func() (bool, error) {
pod, err = kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
return pod != nil, err
})
// retry failed, then return error with retry out
if waitErr != nil {
return nil, cmdErr(k8sArgs, "error getting pod with error: %v", err)
}
} else {
// Other case, return error
return nil, cmdErr(k8sArgs, "error getting pod: %v", err)
}
}
} }
// resourceMap holds Pod device allocation information; only initizized if CRD contains 'resourceName' annotation. // resourceMap holds Pod device allocation information; only initizized if CRD contains 'resourceName' annotation.
@ -774,29 +794,9 @@ func CmdDel(args *skel.CmdArgs, exec invoke.Exec, kubeClient *k8s.ClientInfo) er
return cmdErr(nil, "error getting k8s client: %v", err) return cmdErr(nil, "error getting k8s client: %v", err)
} }
pod := (*v1.Pod)(nil) pod, err := getPod(kubeClient, k8sArgs, true)
if kubeClient != nil { if err != nil {
pod, err = kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME)) return err
if err != nil {
var waitErr error
// in case of a retriable error, retry 10 times with 0.25 sec interval
if isCriticalRequestRetriable(err) {
waitErr = wait.PollImmediate(shortPollDuration, shortPollTimeout, func() (bool, error) {
pod, err = kubeClient.GetPod(string(k8sArgs.K8S_POD_NAMESPACE), string(k8sArgs.K8S_POD_NAME))
return pod != nil, err
})
// retry failed, then return error with retry out
if waitErr != nil {
return cmdErr(k8sArgs, "error getting pod with error: %v", err)
}
} else if errors.IsNotFound(err) {
// If not found, proceed to remove interface with cache
pod = nil
} else {
// Other case, return error
return cmdErr(k8sArgs, "error getting pod: %v", err)
}
}
} }
// Read the cache to get delegates json for the pod // Read the cache to get delegates json for the pod

View File

@ -1236,7 +1236,7 @@ var _ = Describe("multus operations cniVersion 0.2.0 config", func() {
_, err = CmdAdd(args, fExec, nil) _, err = CmdAdd(args, fExec, nil)
Expect(fExec.addIndex).To(Equal(2)) Expect(fExec.addIndex).To(Equal(2))
Expect(fExec.delIndex).To(Equal(2)) Expect(fExec.delIndex).To(Equal(2))
Expect(err).To(MatchError("[/:other1]: error adding container to network \"other1\": expected plugin failure")) Expect(err).To(MatchError("[//:other1]: error adding container to network \"other1\": expected plugin failure"))
// Cleanup default network file. // Cleanup default network file.
if _, errStat := os.Stat(configPath); errStat == nil { if _, errStat := os.Stat(configPath); errStat == nil {
@ -1420,6 +1420,116 @@ var _ = Describe("multus operations cniVersion 0.2.0 config", func() {
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue()) Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
}) })
It("fails when pod UID is provided and does not match Kube API pod UID", func() {
fakePod := testhelpers.NewFakePod("testpod", "net1", "")
net1 := `{
"name": "net1",
"type": "mynet",
"capabilities": {"mac": true, "ips": true, "bandwidth": true, "portMappings": true},
"cniVersion": "0.3.1"
}`
args := &skel.CmdArgs{
ContainerID: "123456789",
Netns: testNS.Path(),
IfName: "eth0",
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_UID=foobar", fakePod.Name, fakePod.Namespace),
StdinData: []byte(`{
"name": "node-cni-network",
"type": "multus",
"kubeconfig": "/etc/kubernetes/node-kubeconfig.yaml",
"delegates": [{
"name": "weave1",
"cniVersion": "0.3.1",
"type": "weave-net"
}]
}`),
}
clientInfo := NewFakeClientInfo()
_, err := clientInfo.Client.CoreV1().Pods(fakePod.Namespace).Create(
context.TODO(), fakePod, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
_, err = clientInfo.AddNetAttachDef(
testhelpers.NewFakeNetAttachDef(fakePod.Namespace, "net1", net1))
Expect(err).NotTo(HaveOccurred())
os.Setenv("CNI_COMMAND", "ADD")
os.Setenv("CNI_IFNAME", "eth0")
_, err = CmdAdd(args, &fakeExec{}, clientInfo)
Expect(err.Error()).To(ContainSubstring("expected pod UID \"foobar\" but got %q from Kube API", fakePod.UID))
})
It("executes delegates when runtime provides a matching pod UID", func() {
fakePod := testhelpers.NewFakePod("testpod", "net1", "")
net1 := `{
"name": "net1",
"type": "mynet",
"cniVersion": "0.3.1"
}`
args := &skel.CmdArgs{
ContainerID: "123456789",
Netns: testNS.Path(),
IfName: "eth0",
Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s;K8S_POD_UID=%s", fakePod.Name, fakePod.Namespace, fakePod.UID),
StdinData: []byte(`{
"name": "node-cni-network",
"type": "multus",
"kubeconfig": "/etc/kubernetes/node-kubeconfig.yaml",
"delegates": [{
"name": "weave1",
"cniVersion": "0.3.1",
"type": "weave-net"
}]
}`),
}
fExec := &fakeExec{}
expectedResult1 := &current.Result{
CNIVersion: resultCNIVersion,
IPs: []*current.IPConfig{{
Address: *testhelpers.EnsureCIDR("1.1.1.2/24"),
},
},
}
expectedConf1 := `{
"name": "weave1",
"cniVersion": "0.3.1",
"type": "weave-net"
}`
expectedNet1 := `{
"name": "net1",
"type": "mynet",
"cniVersion": "0.3.1"
}`
fExec.addPlugin(nil, "eth0", expectedConf1, expectedResult1, nil)
fExec.addPlugin(nil, "net1", expectedNet1, &current.Result{
CNIVersion: "0.3.1",
IPs: []*current.IPConfig{{
Address: *testhelpers.EnsureCIDR("1.1.1.3/24"),
},
},
}, nil)
clientInfo := NewFakeClientInfo()
_, err := clientInfo.Client.CoreV1().Pods(fakePod.ObjectMeta.Namespace).Create(
context.TODO(), fakePod, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
_, err = clientInfo.AddNetAttachDef(
testhelpers.NewFakeNetAttachDef(fakePod.ObjectMeta.Namespace, "net1", net1))
Expect(err).NotTo(HaveOccurred())
os.Setenv("CNI_COMMAND", "ADD")
os.Setenv("CNI_IFNAME", "eth0")
result, err := CmdAdd(args, fExec, clientInfo)
Expect(err).NotTo(HaveOccurred())
Expect(fExec.addIndex).To(Equal(len(fExec.plugins)))
r := result.(*current.Result)
// plugin 1 is the masterplugin
Expect(reflect.DeepEqual(r, expectedResult1)).To(BeTrue())
})
It("executes delegates and kubernetes networks with events check", func() { It("executes delegates and kubernetes networks with events check", func() {
fakePod := testhelpers.NewFakePod("testpod", "net1,net2", "") fakePod := testhelpers.NewFakePod("testpod", "net1,net2", "")
net1 := `{ net1 := `{
@ -2486,7 +2596,7 @@ var _ = Describe("multus operations cniVersion 0.4.0 config", func() {
_, err = CmdAdd(args, fExec, nil) _, err = CmdAdd(args, fExec, nil)
Expect(fExec.addIndex).To(Equal(2)) Expect(fExec.addIndex).To(Equal(2))
Expect(fExec.delIndex).To(Equal(2)) Expect(fExec.delIndex).To(Equal(2))
Expect(err).To(MatchError("[/:other1]: error adding container to network \"other1\": expected plugin failure")) Expect(err).To(MatchError("[//:other1]: error adding container to network \"other1\": expected plugin failure"))
// Cleanup default network file. // Cleanup default network file.
if _, errStat := os.Stat(configPath); errStat == nil { if _, errStat := os.Stat(configPath); errStat == nil {

View File

@ -204,8 +204,6 @@ func CreateCNIRuntimeConf(args *skel.CmdArgs, k8sArgs *K8sArgs, ifName string, r
} }
// In part, adapted from K8s pkg/kubelet/dockershim/network/cni/cni.go#buildCNIRuntimeConf // In part, adapted from K8s pkg/kubelet/dockershim/network/cni/cni.go#buildCNIRuntimeConf
// Todo
// ingress, egress and bandwidth capability features as same as kubelet.
rt := &libcni.RuntimeConf{ rt := &libcni.RuntimeConf{
ContainerID: args.ContainerID, ContainerID: args.ContainerID,
NetNS: args.Netns, NetNS: args.Netns,
@ -216,6 +214,7 @@ func CreateCNIRuntimeConf(args *skel.CmdArgs, k8sArgs *K8sArgs, ifName string, r
{"K8S_POD_NAMESPACE", string(k8sArgs.K8S_POD_NAMESPACE)}, {"K8S_POD_NAMESPACE", string(k8sArgs.K8S_POD_NAMESPACE)},
{"K8S_POD_NAME", string(k8sArgs.K8S_POD_NAME)}, {"K8S_POD_NAME", string(k8sArgs.K8S_POD_NAME)},
{"K8S_POD_INFRA_CONTAINER_ID", string(k8sArgs.K8S_POD_INFRA_CONTAINER_ID)}, {"K8S_POD_INFRA_CONTAINER_ID", string(k8sArgs.K8S_POD_INFRA_CONTAINER_ID)},
{"K8S_POD_UID", string(k8sArgs.K8S_POD_UID)},
}, },
} }

View File

@ -157,6 +157,7 @@ type K8sArgs struct {
K8S_POD_NAME types.UnmarshallableString //revive:disable-line K8S_POD_NAME types.UnmarshallableString //revive:disable-line
K8S_POD_NAMESPACE types.UnmarshallableString //revive:disable-line K8S_POD_NAMESPACE types.UnmarshallableString //revive:disable-line
K8S_POD_INFRA_CONTAINER_ID types.UnmarshallableString //revive:disable-line K8S_POD_INFRA_CONTAINER_ID types.UnmarshallableString //revive:disable-line
K8S_POD_UID types.UnmarshallableString //revive:disable-line
} }
// ResourceInfo is struct to hold Pod device allocation information // ResourceInfo is struct to hold Pod device allocation information