From 0cf8c6e4943c017eebb3cee2080a59ba80ed25a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Ma=C5=82ek?= Date: Tue, 10 Oct 2023 21:17:48 +0200 Subject: [PATCH] fix(metallb): remove conflicting IPAddressPools when metallb admission webhook rejects ktf's pool --- pkg/clusters/addons/metallb/metallb.go | 27 ++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/pkg/clusters/addons/metallb/metallb.go b/pkg/clusters/addons/metallb/metallb.go index 000afcb12..47bb260a9 100644 --- a/pkg/clusters/addons/metallb/metallb.go +++ b/pkg/clusters/addons/metallb/metallb.go @@ -13,7 +13,7 @@ import ( "go4.org/netipx" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -119,7 +119,7 @@ func (a *addon) Ready(ctx context.Context, cluster clusters.Cluster) ([]runtime. deployment, err := cluster.Client().AppsV1().Deployments(DefaultNamespace). Get(ctx, "controller", metav1.GetOptions{}) if err != nil { - if errors.IsNotFound(err) { + if apierrors.IsNotFound(err) { return nil, false, nil } return nil, false, err @@ -155,7 +155,7 @@ func deployMetallbForKindCluster(ctx context.Context, cluster clusters.Cluster, // ensure the namespace for metallb is created ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: DefaultNamespace}} if _, err := cluster.Client().CoreV1().Namespaces().Create(ctx, &ns, metav1.CreateOptions{}); err != nil { - if !errors.IsAlreadyExists(err) { + if !apierrors.IsAlreadyExists(err) { return err } } @@ -190,7 +190,7 @@ func deployMetallbForKindCluster(ctx context.Context, cluster clusters.Cluster, }, } if _, err := cluster.Client().CoreV1().Secrets(ns.Name).Create(ctx, secret, metav1.CreateOptions{}); err != nil { - if !errors.IsAlreadyExists(err) { + if !apierrors.IsAlreadyExists(err) { return err } } @@ -239,13 +239,24 @@ func createIPAddressPool(ctx context.Context, cluster clusters.Cluster, dockerNe }, metav1.CreateOptions{}) if err != nil { - if errors.IsAlreadyExists(err) { + if apierrors.IsAlreadyExists(err) { // delete the existing resource and recreate it in another round of loop. err = res.Delete(ctx, addressPoolName, metav1.DeleteOptions{}) + } else if apierrors.IsForbidden(err) { + // This means most likely that there's a conflicting IPAddressPool + // and we couldn't apply ours. In this case remove the existing pools + // 1 by 1 (most often there's going to be just 1) and re-attempt + // to create a new one. + ipAddressPools, errL := res.List(ctx, metav1.ListOptions{}) + if errL != nil { + err = errL + } else if len(ipAddressPools.Items) > 0 { + err = res.Delete(ctx, ipAddressPools.Items[0].GetName(), metav1.DeleteOptions{}) + } } select { - case <-time.After(time.Second): + case <-time.After(100 * time.Millisecond): lastErr = err continue case <-ctx.Done(): @@ -282,14 +293,14 @@ func createL2Advertisement(ctx context.Context, cluster clusters.Cluster) error }, metav1.CreateOptions{}) if err != nil { - if errors.IsAlreadyExists(err) { + if apierrors.IsAlreadyExists(err) { // delete the existing resource and recreate it in another round of loop. err = res.Delete(ctx, l2AdvertisementName, metav1.DeleteOptions{}) } lastErr = err select { - case <-time.After(time.Second): + case <-time.After(100 * time.Millisecond): continue case <-ctx.Done(): return fmt.Errorf("failed to create metallb.io/v1beta1 L2Advertisement: %w, last error %v", ctx.Err(), lastErr)