From c652aadbfe61f7dc98ebc19505d6deb0e8f6a8bd Mon Sep 17 00:00:00 2001 From: Miguel Duarte Barroso Date: Mon, 4 Apr 2022 15:32:23 +0200 Subject: [PATCH] reconcile-loop: focus on networks w/ whereabouts IPAM type Signed-off-by: Miguel Duarte Barroso --- pkg/config/config.go | 19 ++++++++++ pkg/config/config_test.go | 18 ++++++++- .../controlloop/entity_generators.go | 19 ++++++++++ pkg/reconciler/controlloop/pod.go | 10 ++++- .../controlloop/pod_controller_test.go | 38 +++++++++++++++++++ 5 files changed, 102 insertions(+), 2 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 6a0c27a0d..93a75dc0e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -45,6 +45,8 @@ func LoadIPAMConfig(bytes []byte, envArgs string, extraConfigPaths ...string) (* if n.IPAM == nil { return nil, "", fmt.Errorf("IPAM config missing 'ipam' key") + } else if !isNetworkRelevant(n.IPAM) { + return nil, "", NewInvalidPluginError(n.IPAM.Type) } args := types.IPAMEnvArgs{} @@ -342,3 +344,20 @@ func loadPluginConfig(bytes []byte) (*cnitypes.NetConf, error) { } return &pluginConfig, nil } + +func isNetworkRelevant(ipamConfig *types.IPAMConfig) bool { + const relevantIPAMType = "whereabouts" + return ipamConfig.Type == relevantIPAMType +} + +type InvalidPluginError struct { + ipamType string +} + +func NewInvalidPluginError(ipamType string) *InvalidPluginError { + return &InvalidPluginError{ipamType: ipamType} +} + +func (e *InvalidPluginError) Error() string { + return fmt.Sprintf("only interested in networks whose IPAM type is 'whereabouts'. This one was: %s", e.ipamType) +} diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 734142bd3..40d5c5646 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -1,7 +1,7 @@ package config import ( - // "fmt" + "fmt" "io/ioutil" "net" // "os" @@ -135,4 +135,20 @@ var _ = Describe("Allocation operations", func() { Expect(ipamconfig.LeaderRenewDeadline).To(Equal(1000)) Expect(ipamconfig.LeaderRetryPeriod).To(Equal(500)) }) + + It("throws an error when passed a non-whereabouts IPAM config", func() { + const wrongPluginType = "static" + conf := fmt.Sprintf(`{ + "cniVersion": "0.3.1", + "name": "mynet", + "type": "ipvlan", + "master": "foo0", + "ipam": { + "type": "%s" + } + }`, wrongPluginType) + + _, _, err := LoadIPAMConfig([]byte(conf), "") + Expect(err).To(MatchError(&InvalidPluginError{ipamType: wrongPluginType})) + }) }) diff --git a/pkg/reconciler/controlloop/entity_generators.go b/pkg/reconciler/controlloop/entity_generators.go index e29e93069..40223809a 100644 --- a/pkg/reconciler/controlloop/entity_generators.go +++ b/pkg/reconciler/controlloop/entity_generators.go @@ -31,6 +31,25 @@ func dummyNetSpec(networkName string, ipRange string) string { }`, networkName, ipRange) } +func dummyNonWhereaboutsIPAMNetSpec(networkName string) string { + return fmt.Sprintf(`{ + "cniVersion": "0.3.0", + "name": "%s", + "type": "macvlan", + "master": "eth0", + "mode": "bridge", + "ipam": { + "type": "static", + "addresses": [ + { + "address": "10.10.0.1/24", + "gateway": "10.10.0.254" + } + ] + } + }`, networkName) +} + func podSpec(name string, namespace string, networks ...string) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/reconciler/controlloop/pod.go b/pkg/reconciler/controlloop/pod.go index 86cc3df5b..73d69ca37 100644 --- a/pkg/reconciler/controlloop/pod.go +++ b/pkg/reconciler/controlloop/pod.go @@ -167,7 +167,10 @@ func (pc *PodController) garbageCollectPodIPs(pod *v1.Pod) error { logging.Verbosef("the NAD's config: %s", nad.Spec) ipamConfig, err := ipamConfiguration(nad, podNamespace, podName, mountPath) - if err != nil { + if err != nil && isInvalidPluginType(err) { + logging.Debugf("error while computing something: %v", err) + continue + } else if err != nil { return fmt.Errorf("failed to create an IPAM configuration for the pod %s iface %s: %+v", podID(podNamespace, podName), ifaceStatus.Name, err) } @@ -194,6 +197,11 @@ func (pc *PodController) garbageCollectPodIPs(pod *v1.Pod) error { return nil } +func isInvalidPluginType(err error) bool { + _, isInvalidPluginError := err.(*config.InvalidPluginError) + return isInvalidPluginError +} + func (pc *PodController) handleResult(pod *v1.Pod, err error) { if err == nil { pc.workqueue.Forget(pod) diff --git a/pkg/reconciler/controlloop/pod_controller_test.go b/pkg/reconciler/controlloop/pod_controller_test.go index 6ef6ee7f7..de8d318ed 100644 --- a/pkg/reconciler/controlloop/pod_controller_test.go +++ b/pkg/reconciler/controlloop/pod_controller_test.go @@ -7,6 +7,7 @@ import ( "os" "path" "testing" + "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -177,6 +178,43 @@ var _ = Describe("IPControlLoop", func() { }) }) }) + + Context("with secondary networks whose type is *not* whereabouts", func() { + var ( + wbClient wbclient.Interface + eventRecorder *record.FakeRecorder + netAttachDefClient nadclient.Interface + stopChannel chan struct{} + ) + + BeforeEach(func() { + stopChannel = make(chan struct{}) + + wbClient = fakewbclient.NewSimpleClientset() + var err error + netAttachDefClient, err = newFakeNetAttachDefClient(namespace, netAttachDef(networkName, namespace, dummyNonWhereaboutsIPAMNetSpec(networkName))) + Expect(err).NotTo(HaveOccurred()) + + const maxEvents = 1 + eventRecorder = record.NewFakeRecorder(maxEvents) + Expect(newDummyPodController(k8sClient, wbClient, netAttachDefClient, stopChannel, cniConfigDir, eventRecorder)).NotTo(BeNil()) + }) + + AfterEach(func() { + stopChannel <- struct{}{} + }) + + When("the pod is deleted", func() { + BeforeEach(func() { + Expect(k8sClient.CoreV1().Pods(namespace).Delete(context.TODO(), pod.GetName(), metav1.DeleteOptions{})).To(Succeed()) + }) + + It("should not report any event", func() { + const eventTimeout = time.Second + Consistently(eventRecorder.Events, eventTimeout).ShouldNot(Receive()) + }) + }) + }) }) })