From a54b953ddcc54b5829fbde045035ac1383347b87 Mon Sep 17 00:00:00 2001 From: Andreas Fritzler Date: Wed, 27 Sep 2023 16:08:09 +0200 Subject: [PATCH 1/2] Fix ephemeral resource handling - Fix the cleanup of ephemeral resources {nic,prefix,volume,vip} - Update test cases Co-authored-by: Axel Christ --- api/common/v1alpha1/common_types.go | 7 ++++ ...ne_ephemeralnetworkinterface_controller.go | 13 ++++--- ...hemeralnetworkinterface_controller_test.go | 37 ++++++++++++++++++- .../machine_ephemeralvolume_controller.go | 15 ++++++-- ...machine_ephemeralvolume_controller_test.go | 30 +++++++++++++++ ...loadbalancer_ephemeralprefix_controller.go | 11 ++++-- ...alancer_ephemeralprefix_controller_test.go | 35 ++++++++++++++++++ ...orkinterface_ephemeralprefix_controller.go | 11 ++++-- ...terface_ephemeralprefix_controller_test.go | 36 +++++++++++++++++- ...interface_ephemeralvirtualip_controller.go | 13 ++++--- ...face_ephemeralvirtualip_controller_test.go | 36 +++++++++++++++++- utils/annotations/annotations.go | 13 +++++++ 12 files changed, 232 insertions(+), 25 deletions(-) diff --git a/api/common/v1alpha1/common_types.go b/api/common/v1alpha1/common_types.go index 4cec63579..2c2c85775 100644 --- a/api/common/v1alpha1/common_types.go +++ b/api/common/v1alpha1/common_types.go @@ -40,6 +40,13 @@ const ( // ManagedByAnnotation is an annotation that can be applied to resources to signify that // some external system is managing the resource. ManagedByAnnotation = "common.api.onmetal.de/managed-by" + + // EphemeralManagedByAnnotation is an annotation that can be applied to resources to signify that + // some ephemeral controller is managing the resource. + EphemeralManagedByAnnotation = "common.api.onmetal.de/ephemeral-managed-by" + + // DefaultEphemeralManager is the default onmetal-api ephemeral manager. + DefaultEphemeralManager = "ephemeral-manager" ) // ConfigMapKeySelector is a reference to a specific 'key' within a ConfigMap resource. diff --git a/internal/controllers/compute/machine_ephemeralnetworkinterface_controller.go b/internal/controllers/compute/machine_ephemeralnetworkinterface_controller.go index 3356d665f..60c04dbb9 100644 --- a/internal/controllers/compute/machine_ephemeralnetworkinterface_controller.go +++ b/internal/controllers/compute/machine_ephemeralnetworkinterface_controller.go @@ -19,6 +19,9 @@ import ( "errors" "fmt" + "github.com/onmetal/onmetal-api/utils/annotations" + "golang.org/x/exp/maps" + "github.com/go-logr/logr" commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" computev1alpha1 "github.com/onmetal/onmetal-api/api/compute/v1alpha1" @@ -73,22 +76,23 @@ func (r *MachineEphemeralNetworkInterfaceReconciler) ephemeralNetworkInterfaceBy Namespace: machine.Namespace, Name: nicName, Labels: ephemeral.NetworkInterfaceTemplate.Labels, - Annotations: ephemeral.NetworkInterfaceTemplate.Annotations, + Annotations: maps.Clone(ephemeral.NetworkInterfaceTemplate.Annotations), }, Spec: ephemeral.NetworkInterfaceTemplate.Spec, } + annotations.SetDefaultEphemeralManagedBy(nic) + _ = ctrl.SetControllerReference(machine, nic, r.Scheme()) nic.Spec.MachineRef = &commonv1alpha1.LocalUIDReference{ Name: machine.Name, UID: machine.UID, } - _ = ctrl.SetControllerReference(machine, nic, r.Scheme()) res[nicName] = nic } return res } func (r *MachineEphemeralNetworkInterfaceReconciler) handleExistingNetworkInterface(ctx context.Context, log logr.Logger, machine *computev1alpha1.Machine, shouldManage bool, nic *networkingv1alpha1.NetworkInterface) error { - if metav1.IsControlledBy(nic, machine) { + if annotations.IsDefaultEphemeralControlledBy(nic, machine) { if shouldManage { log.V(1).Info("Ephemeral network interface is present and controlled by machine") return nil @@ -107,9 +111,8 @@ func (r *MachineEphemeralNetworkInterfaceReconciler) handleExistingNetworkInterf } if shouldManage { - return fmt.Errorf("network interface %s was not created for machine %s (machine is not owner)", nic.Name, machine.Name) + log.V(1).Info("Won't adopt unmanaged network interface") } - // Network interface is not desired but also not controlled by the machine. return nil } diff --git a/internal/controllers/compute/machine_ephemeralnetworkinterface_controller_test.go b/internal/controllers/compute/machine_ephemeralnetworkinterface_controller_test.go index 270bdf5e3..7f97cd91e 100644 --- a/internal/controllers/compute/machine_ephemeralnetworkinterface_controller_test.go +++ b/internal/controllers/compute/machine_ephemeralnetworkinterface_controller_test.go @@ -18,6 +18,7 @@ import ( commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" computev1alpha1 "github.com/onmetal/onmetal-api/api/compute/v1alpha1" networkingv1alpha1 "github.com/onmetal/onmetal-api/api/networking/v1alpha1" + "github.com/onmetal/onmetal-api/utils/annotations" . "github.com/onmetal/onmetal-api/utils/testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -78,7 +79,7 @@ var _ = Describe("MachineEphemeralNetworkInterfaceController", func() { )) }) - It("should delete undesired ephemeral network interfaces", MustPassRepeatedly(10), func(ctx SpecContext) { + It("should delete undesired ephemeral network interfaces", func(ctx SpecContext) { By("creating a machine") machine := &computev1alpha1.Machine{ ObjectMeta: metav1.ObjectMeta{ @@ -104,10 +105,44 @@ var _ = Describe("MachineEphemeralNetworkInterfaceController", func() { }, }, } + annotations.SetDefaultEphemeralManagedBy(undesiredNic) Expect(ctrl.SetControllerReference(machine, undesiredNic, k8sClient.Scheme())).To(Succeed()) Expect(k8sClient.Create(ctx, undesiredNic)).To(Succeed()) By("waiting for the undesired network interface to be gone") Eventually(Get(undesiredNic)).Should(Satisfy(apierrors.IsNotFound)) }) + + It("should not delete an externally managed network interface", func(ctx SpecContext) { + By("creating a machine") + machine := &computev1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "machine-", + }, + Spec: computev1alpha1.MachineSpec{ + MachineClassRef: corev1.LocalObjectReference{Name: machineClass.Name}, + }, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed()) + + By("creating an externally managed network interface") + externalNic := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "external-nic-", + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: "my-network"}, + IPs: []networkingv1alpha1.IPSource{ + {Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}, + }, + }, + } + Expect(ctrl.SetControllerReference(machine, externalNic, k8sClient.Scheme())).To(Succeed()) + Expect(k8sClient.Create(ctx, externalNic)).To(Succeed()) + + By("asserting the network interface is not being deleted") + Consistently(Object(externalNic)).Should(HaveField("DeletionTimestamp", BeNil())) + }) }) diff --git a/internal/controllers/compute/machine_ephemeralvolume_controller.go b/internal/controllers/compute/machine_ephemeralvolume_controller.go index d37062212..240236505 100644 --- a/internal/controllers/compute/machine_ephemeralvolume_controller.go +++ b/internal/controllers/compute/machine_ephemeralvolume_controller.go @@ -18,6 +18,9 @@ import ( "context" "errors" "fmt" + "maps" + + "github.com/onmetal/onmetal-api/utils/annotations" "github.com/go-logr/logr" computev1alpha1 "github.com/onmetal/onmetal-api/api/compute/v1alpha1" @@ -33,6 +36,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const ( + MachineEphemeralVolumeManager = "machine-ephemeral-volume" +) + type MachineEphemeralVolumeReconciler struct { client.Client } @@ -73,10 +80,11 @@ func (r *MachineEphemeralVolumeReconciler) ephemeralMachineVolumeByName(machine Namespace: machine.Namespace, Name: volumeName, Labels: ephemeral.VolumeTemplate.Labels, - Annotations: ephemeral.VolumeTemplate.Annotations, + Annotations: maps.Clone(ephemeral.VolumeTemplate.Annotations), }, Spec: ephemeral.VolumeTemplate.Spec, } + annotations.SetDefaultEphemeralManagedBy(volume) _ = ctrl.SetControllerReference(machine, volume, r.Scheme()) res[volumeName] = volume } @@ -84,7 +92,7 @@ func (r *MachineEphemeralVolumeReconciler) ephemeralMachineVolumeByName(machine } func (r *MachineEphemeralVolumeReconciler) handleExistingVolume(ctx context.Context, log logr.Logger, machine *computev1alpha1.Machine, shouldManage bool, volume *storagev1alpha1.Volume) error { - if metav1.IsControlledBy(volume, machine) { + if annotations.IsDefaultEphemeralControlledBy(volume, machine) { if shouldManage { log.V(1).Info("Ephemeral volume is present and controlled by machine") return nil @@ -103,9 +111,8 @@ func (r *MachineEphemeralVolumeReconciler) handleExistingVolume(ctx context.Cont } if shouldManage { - return fmt.Errorf("volume %s was not created for machine %s (machine is not owner)", volume.Name, machine.Name) + log.V(1).Info("Won't adopt unmanaged volume") } - // Volume is not desired but also not controlled by the machine. return nil } diff --git a/internal/controllers/compute/machine_ephemeralvolume_controller_test.go b/internal/controllers/compute/machine_ephemeralvolume_controller_test.go index ee1173fcc..fb41f0737 100644 --- a/internal/controllers/compute/machine_ephemeralvolume_controller_test.go +++ b/internal/controllers/compute/machine_ephemeralvolume_controller_test.go @@ -17,6 +17,7 @@ package compute import ( computev1alpha1 "github.com/onmetal/onmetal-api/api/compute/v1alpha1" storagev1alpha1 "github.com/onmetal/onmetal-api/api/storage/v1alpha1" + "github.com/onmetal/onmetal-api/utils/annotations" . "github.com/onmetal/onmetal-api/utils/testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -80,6 +81,7 @@ var _ = Describe("MachineEphemeralVolumeController", func() { }, Spec: storagev1alpha1.VolumeSpec{}, } + annotations.SetDefaultEphemeralManagedBy(undesiredControlledVolume) _ = ctrl.SetControllerReference(machine, undesiredControlledVolume, k8sClient.Scheme()) Expect(k8sClient.Create(ctx, undesiredControlledVolume)).To(Succeed()) @@ -98,4 +100,32 @@ var _ = Describe("MachineEphemeralVolumeController", func() { By("waiting for the undesired controlled volume to be gone") Eventually(Get(undesiredControlledVolume)).Should(Satisfy(apierrors.IsNotFound)) }) + + It("should not delete externally managed volumes for a machine", func(ctx SpecContext) { + By("creating a machine") + machine := &computev1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "machine-", + }, + Spec: computev1alpha1.MachineSpec{ + MachineClassRef: corev1.LocalObjectReference{Name: machineClass.Name}, + }, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed()) + + By("creating an undesired controlled volume") + externalVolume := &storagev1alpha1.Volume{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "external-volume-", + }, + Spec: storagev1alpha1.VolumeSpec{}, + } + _ = ctrl.SetControllerReference(machine, externalVolume, k8sClient.Scheme()) + Expect(k8sClient.Create(ctx, externalVolume)).To(Succeed()) + + By("asserting that the external volume is not being deleted") + Consistently(Object(externalVolume)).Should(HaveField("DeletionTimestamp", BeNil())) + }) }) diff --git a/internal/controllers/networking/loadbalancer_ephemeralprefix_controller.go b/internal/controllers/networking/loadbalancer_ephemeralprefix_controller.go index 81fb99c77..9b574a57f 100644 --- a/internal/controllers/networking/loadbalancer_ephemeralprefix_controller.go +++ b/internal/controllers/networking/loadbalancer_ephemeralprefix_controller.go @@ -18,6 +18,9 @@ import ( "context" "errors" "fmt" + "maps" + + "github.com/onmetal/onmetal-api/utils/annotations" "github.com/go-logr/logr" ipamv1alpha1 "github.com/onmetal/onmetal-api/api/ipam/v1alpha1" @@ -74,10 +77,11 @@ func (r *LoadBalancerEphemeralPrefixReconciler) ephemeralLoadBalancerPrefixByNam Namespace: loadBalancer.Namespace, Name: prefixName, Labels: ephemeral.PrefixTemplate.Labels, - Annotations: ephemeral.PrefixTemplate.Annotations, + Annotations: maps.Clone(ephemeral.PrefixTemplate.Annotations), }, Spec: ephemeral.PrefixTemplate.Spec, } + annotations.SetDefaultEphemeralManagedBy(prefix) _ = ctrl.SetControllerReference(loadBalancer, prefix, r.Scheme()) res[prefixName] = prefix } @@ -86,7 +90,7 @@ func (r *LoadBalancerEphemeralPrefixReconciler) ephemeralLoadBalancerPrefixByNam } func (r *LoadBalancerEphemeralPrefixReconciler) handleExistingPrefix(ctx context.Context, log logr.Logger, loadBalancer *networkingv1alpha1.LoadBalancer, shouldManage bool, prefix *ipamv1alpha1.Prefix) error { - if metav1.IsControlledBy(prefix, loadBalancer) { + if annotations.IsDefaultEphemeralControlledBy(prefix, loadBalancer) { if shouldManage { log.V(1).Info("Ephemeral prefix is present and controlled by load balancer") return nil @@ -105,9 +109,8 @@ func (r *LoadBalancerEphemeralPrefixReconciler) handleExistingPrefix(ctx context } if shouldManage { - return fmt.Errorf("prefix %s was not created for load balancer %s (load balancer is not owner)", prefix.Name, loadBalancer.Name) + log.V(1).Info("Won't adopt unmanaged prefix") } - // Prefix is not desired but also not controlled by the load balancer. return nil } diff --git a/internal/controllers/networking/loadbalancer_ephemeralprefix_controller_test.go b/internal/controllers/networking/loadbalancer_ephemeralprefix_controller_test.go index aea39e203..6d2f8c35f 100644 --- a/internal/controllers/networking/loadbalancer_ephemeralprefix_controller_test.go +++ b/internal/controllers/networking/loadbalancer_ephemeralprefix_controller_test.go @@ -19,6 +19,7 @@ import ( commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" ipamv1alpha1 "github.com/onmetal/onmetal-api/api/ipam/v1alpha1" networkingv1alpha1 "github.com/onmetal/onmetal-api/api/networking/v1alpha1" + "github.com/onmetal/onmetal-api/utils/annotations" . "github.com/onmetal/onmetal-api/utils/testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -100,10 +101,44 @@ var _ = Describe("LoadBalancerEphemeralPrefix", func() { Prefix: commonv1alpha1.MustParseNewIPPrefix("10.0.0.1/32"), }, } + annotations.SetDefaultEphemeralManagedBy(prefix) Expect(ctrl.SetControllerReference(loadBalancer, prefix, k8sClient.Scheme())).To(Succeed()) Expect(k8sClient.Create(ctx, prefix)).To(Succeed()) By("waiting for the prefix to be marked for deletion") Eventually(Get(prefix)).Should(Satisfy(apierrors.IsNotFound)) }) + + It("should not delete externally managed prefix for a load balancer", MustPassRepeatedly(10), func(ctx SpecContext) { + By("creating a load balancer") + loadBalancer := &networkingv1alpha1.LoadBalancer{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "load-balancer-", + }, + Spec: networkingv1alpha1.LoadBalancerSpec{ + Type: networkingv1alpha1.LoadBalancerTypeInternal, + NetworkRef: corev1.LocalObjectReference{Name: "my-network"}, + IPs: []networkingv1alpha1.IPSource{{Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}}, + }, + } + Expect(k8sClient.Create(ctx, loadBalancer)).To(Succeed()) + + By("creating an undesired prefix") + externalPrefix := &ipamv1alpha1.Prefix{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "external-prefix-", + }, + Spec: ipamv1alpha1.PrefixSpec{ + IPFamily: corev1.IPv4Protocol, + Prefix: commonv1alpha1.MustParseNewIPPrefix("10.0.0.1/32"), + }, + } + Expect(ctrl.SetControllerReference(loadBalancer, externalPrefix, k8sClient.Scheme())).To(Succeed()) + Expect(k8sClient.Create(ctx, externalPrefix)).To(Succeed()) + + By("asserting that the external prefix is not being deleted") + Eventually(Object(externalPrefix)).Should(HaveField("DeletionTimestamp", BeNil())) + }) }) diff --git a/internal/controllers/networking/networkinterface_ephemeralprefix_controller.go b/internal/controllers/networking/networkinterface_ephemeralprefix_controller.go index 76597625f..d14e16e62 100644 --- a/internal/controllers/networking/networkinterface_ephemeralprefix_controller.go +++ b/internal/controllers/networking/networkinterface_ephemeralprefix_controller.go @@ -18,6 +18,9 @@ import ( "context" "errors" "fmt" + "maps" + + "github.com/onmetal/onmetal-api/utils/annotations" "github.com/go-logr/logr" ipamv1alpha1 "github.com/onmetal/onmetal-api/api/ipam/v1alpha1" @@ -74,10 +77,11 @@ func (r *NetworkInterfaceEphemeralPrefixReconciler) ephemeralNetworkInterfacePre Namespace: nic.Namespace, Name: prefixName, Labels: ephemeral.PrefixTemplate.Labels, - Annotations: ephemeral.PrefixTemplate.Annotations, + Annotations: maps.Clone(ephemeral.PrefixTemplate.Annotations), }, Spec: ephemeral.PrefixTemplate.Spec, } + annotations.SetDefaultEphemeralManagedBy(prefix) _ = ctrl.SetControllerReference(nic, prefix, r.Scheme()) res[prefixName] = prefix } @@ -106,7 +110,7 @@ func (r *NetworkInterfaceEphemeralPrefixReconciler) ephemeralNetworkInterfacePre } func (r *NetworkInterfaceEphemeralPrefixReconciler) handleExistingPrefix(ctx context.Context, log logr.Logger, nic *networkingv1alpha1.NetworkInterface, shouldManage bool, prefix *ipamv1alpha1.Prefix) error { - if metav1.IsControlledBy(prefix, nic) { + if annotations.IsDefaultEphemeralControlledBy(prefix, nic) { if shouldManage { log.V(1).Info("Ephemeral prefix is present and controlled by network interface") return nil @@ -125,9 +129,8 @@ func (r *NetworkInterfaceEphemeralPrefixReconciler) handleExistingPrefix(ctx con } if shouldManage { - return fmt.Errorf("prefix %s was not created for network interface %s (network interface is not owner)", prefix.Name, nic.Name) + log.V(1).Info("Won't adopt unmanaged prefix") } - // Prefix is not desired but also not controlled by the networkInterface. return nil } diff --git a/internal/controllers/networking/networkinterface_ephemeralprefix_controller_test.go b/internal/controllers/networking/networkinterface_ephemeralprefix_controller_test.go index 7925c7b33..06da1ef1a 100644 --- a/internal/controllers/networking/networkinterface_ephemeralprefix_controller_test.go +++ b/internal/controllers/networking/networkinterface_ephemeralprefix_controller_test.go @@ -19,6 +19,7 @@ import ( commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" ipamv1alpha1 "github.com/onmetal/onmetal-api/api/ipam/v1alpha1" networkingv1alpha1 "github.com/onmetal/onmetal-api/api/networking/v1alpha1" + "github.com/onmetal/onmetal-api/utils/annotations" . "github.com/onmetal/onmetal-api/utils/testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -73,7 +74,7 @@ var _ = Describe("NetworkInterfaceEphemeralPrefix", func() { )) }) - It("should delete undesired prefixes for a network interface", MustPassRepeatedly(10), func(ctx SpecContext) { + It("should delete undesired prefixes for a network interface", func(ctx SpecContext) { By("creating a network interface") nic := &networkingv1alpha1.NetworkInterface{ ObjectMeta: metav1.ObjectMeta{ @@ -98,10 +99,43 @@ var _ = Describe("NetworkInterfaceEphemeralPrefix", func() { Prefix: commonv1alpha1.MustParseNewIPPrefix("10.0.0.1/32"), }, } + annotations.SetDefaultEphemeralManagedBy(prefix) Expect(ctrl.SetControllerReference(nic, prefix, k8sClient.Scheme())).To(Succeed()) Expect(k8sClient.Create(ctx, prefix)).To(Succeed()) By("waiting for the prefix to be marked for deletion") Eventually(Get(prefix)).Should(Satisfy(apierrors.IsNotFound)) }) + + It("should not delete externally managed prefix for a network interface", func(ctx SpecContext) { + By("creating a network interface") + nic := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "nic-", + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: "my-network"}, + IPs: []networkingv1alpha1.IPSource{{Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}}, + }, + } + Expect(k8sClient.Create(ctx, nic)).To(Succeed()) + + By("creating an undesired prefix") + externalPrefix := &ipamv1alpha1.Prefix{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "external-prefix-", + }, + Spec: ipamv1alpha1.PrefixSpec{ + IPFamily: corev1.IPv4Protocol, + Prefix: commonv1alpha1.MustParseNewIPPrefix("10.0.0.1/32"), + }, + } + Expect(ctrl.SetControllerReference(nic, externalPrefix, k8sClient.Scheme())).To(Succeed()) + Expect(k8sClient.Create(ctx, externalPrefix)).To(Succeed()) + + By("asserting that the prefix is not being deleted") + Eventually(Object(externalPrefix)).Should(HaveField("DeletionTimestamp", BeNil())) + }) }) diff --git a/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller.go b/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller.go index 89288cc3d..29c73677d 100644 --- a/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller.go +++ b/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller.go @@ -18,6 +18,9 @@ import ( "context" "errors" "fmt" + "maps" + + "github.com/onmetal/onmetal-api/utils/annotations" "github.com/go-logr/logr" commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" @@ -77,22 +80,23 @@ func (r *NetworkInterfaceEphemeralVirtualIPReconciler) ephemeralNetworkInterface Namespace: nic.Namespace, Name: virtualIPName, Labels: ephemeral.VirtualIPTemplate.Labels, - Annotations: ephemeral.VirtualIPTemplate.Annotations, + Annotations: maps.Clone(ephemeral.VirtualIPTemplate.Annotations), }, Spec: ephemeral.VirtualIPTemplate.Spec, } + annotations.SetDefaultEphemeralManagedBy(virtualIP) + _ = ctrl.SetControllerReference(nic, virtualIP, r.Scheme()) virtualIP.Spec.TargetRef = &commonv1alpha1.LocalUIDReference{ Name: nic.Name, UID: nic.UID, } - _ = ctrl.SetControllerReference(nic, virtualIP, r.Scheme()) res[virtualIPName] = virtualIP return res } func (r *NetworkInterfaceEphemeralVirtualIPReconciler) handleExistingVirtualIP(ctx context.Context, log logr.Logger, nic *networkingv1alpha1.NetworkInterface, shouldManage bool, virtualIP *networkingv1alpha1.VirtualIP) error { - if metav1.IsControlledBy(virtualIP, nic) { + if annotations.IsDefaultEphemeralControlledBy(virtualIP, nic) { if shouldManage { log.V(1).Info("Ephemeral virtual IP is present and controlled by network interface") return nil @@ -111,9 +115,8 @@ func (r *NetworkInterfaceEphemeralVirtualIPReconciler) handleExistingVirtualIP(c } if shouldManage { - return fmt.Errorf("virtual IP %s was not created for network interface %s (network interface is not owner)", virtualIP.Name, nic.Name) + log.V(1).Info("Won't adopt unmanaged virtual IP") } - // VirtualIP is not desired but also not controlled by the networkInterface. return nil } diff --git a/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller_test.go b/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller_test.go index e3fb2e584..a1ad8da59 100644 --- a/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller_test.go +++ b/internal/controllers/networking/networkinterface_ephemeralvirtualip_controller_test.go @@ -18,6 +18,7 @@ package networking import ( commonv1alpha1 "github.com/onmetal/onmetal-api/api/common/v1alpha1" networkingv1alpha1 "github.com/onmetal/onmetal-api/api/networking/v1alpha1" + "github.com/onmetal/onmetal-api/utils/annotations" . "github.com/onmetal/onmetal-api/utils/testing" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -80,7 +81,7 @@ var _ = Describe("NetworkInterfaceEphemeralVirtualIP", func() { )) }) - It("should delete undesired virtual IPs for a network interface", MustPassRepeatedly(10), func(ctx SpecContext) { + It("should delete undesired virtual IPs for a network interface", func(ctx SpecContext) { By("creating a network interface") nic := &networkingv1alpha1.NetworkInterface{ ObjectMeta: metav1.ObjectMeta{ @@ -105,10 +106,43 @@ var _ = Describe("NetworkInterfaceEphemeralVirtualIP", func() { IPFamily: corev1.IPv4Protocol, }, } + annotations.SetDefaultEphemeralManagedBy(vip) Expect(ctrl.SetControllerReference(nic, vip, k8sClient.Scheme())).To(Succeed()) Expect(k8sClient.Create(ctx, vip)).To(Succeed()) By("waiting for the virtual IP to be gone") Eventually(Get(vip)).Should(Satisfy(apierrors.IsNotFound)) }) + + It("should not delete externally managed virtual IPs for a network interface", func(ctx SpecContext) { + By("creating a network interface") + nic := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "nic-", + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: "my-network"}, + IPs: []networkingv1alpha1.IPSource{{Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}}, + }, + } + Expect(k8sClient.Create(ctx, nic)).To(Succeed()) + + By("creating an undesired virtual IP") + externalVip := &networkingv1alpha1.VirtualIP{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "external-vip-", + }, + Spec: networkingv1alpha1.VirtualIPSpec{ + Type: networkingv1alpha1.VirtualIPTypePublic, + IPFamily: corev1.IPv4Protocol, + }, + } + Expect(ctrl.SetControllerReference(nic, externalVip, k8sClient.Scheme())).To(Succeed()) + Expect(k8sClient.Create(ctx, externalVip)).To(Succeed()) + + By("asserting that the virtual IP is not being deleted") + Eventually(Object(externalVip)).Should(HaveField("DeletionTimestamp", BeNil())) + }) }) diff --git a/utils/annotations/annotations.go b/utils/annotations/annotations.go index 225dcf825..1a5c465fb 100644 --- a/utils/annotations/annotations.go +++ b/utils/annotations/annotations.go @@ -38,6 +38,19 @@ func IsExternallyManaged(o metav1.Object) bool { return metautils.HasAnnotation(o, commonv1alpha1.ManagedByAnnotation) } +func IsEphemeralManagedBy(o metav1.Object, manager string) bool { + actual, ok := o.GetAnnotations()[commonv1alpha1.EphemeralManagedByAnnotation] + return ok && actual == manager +} + +func IsDefaultEphemeralControlledBy(o metav1.Object, owner metav1.Object) bool { + return metav1.IsControlledBy(o, owner) && IsEphemeralManagedBy(o, commonv1alpha1.DefaultEphemeralManager) +} + +func SetDefaultEphemeralManagedBy(o metav1.Object) { + metautils.SetAnnotation(o, commonv1alpha1.EphemeralManagedByAnnotation, commonv1alpha1.DefaultEphemeralManager) +} + func SetExternallyMangedBy(o metav1.Object, manager string) { metautils.SetAnnotation(o, commonv1alpha1.ManagedByAnnotation, manager) } From 505ebc076260d0ae40edccb8a744a3e5057b5320 Mon Sep 17 00:00:00 2001 From: Andreas Fritzler Date: Wed, 27 Sep 2023 16:25:24 +0200 Subject: [PATCH 2/2] Bump go to 1.21 --- go.mod | 2 +- go.sum | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e698aca17..3236130b5 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/onmetal/onmetal-api -go 1.20 +go 1.21 require ( github.com/bits-and-blooms/bitset v1.9.0 diff --git a/go.sum b/go.sum index 708f1da30..c012b1605 100644 --- a/go.sum +++ b/go.sum @@ -21,7 +21,9 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -45,10 +47,12 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.9.0 h1:g1YivPG8jOtrN013Fe8OBXubkiTwvm7/vG2vXz03ANU= @@ -74,6 +78,7 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -81,10 +86,12 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -95,6 +102,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= @@ -129,9 +137,11 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -165,6 +175,7 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/cel-go v0.16.1 h1:3hZfSNiAU3KOiNtxuFXVp5WFy4hf/Ly3Sa4/7F8SXNo= github.com/google/cel-go v0.16.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -203,6 +214,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= @@ -219,6 +231,7 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -230,6 +243,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -276,9 +290,12 @@ github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPH github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -299,24 +316,32 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo= +go.etcd.io/etcd/client/v2 v2.305.9/go.mod h1:0NBdNx9wbxtEQLwAQtrDHwx58m02vXpDcgSYI2seohQ= go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= go.etcd.io/etcd/pkg/v3 v3.5.9 h1:6R2jg/aWd/zB9+9JxmijDKStGJAPFsX3e6BeJkMi6eQ= +go.etcd.io/etcd/pkg/v3 v3.5.9/go.mod h1:BZl0SAShQFk0IpLWR78T/+pyt8AruMHhTNNX73hkNVY= go.etcd.io/etcd/raft/v3 v3.5.9 h1:ZZ1GIHoUlHsn0QVqiRysAm3/81Xx7+i2d7nSdWxlOiI= +go.etcd.io/etcd/raft/v3 v3.5.9/go.mod h1:WnFkqzFdZua4LVlVXQEGhmooLeyS7mqzS4Pf4BCVqXg= go.etcd.io/etcd/server/v3 v3.5.9 h1:vomEmmxeztLtS5OEH7d0hBAg4cjVIu9wXuNzUZx2ZA0= +go.etcd.io/etcd/server/v3 v3.5.9/go.mod h1:GgI1fQClQCFIzuVjlvdbMxNbnISt90gdfYyqiAIt65g= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -346,7 +371,9 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -396,6 +423,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=