Skip to content

Commit

Permalink
add KongTarget sample and do not delete when upstream being deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
randmonkey committed Sep 24, 2024
1 parent 624cd59 commit 3ea4f61
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 59 deletions.
46 changes: 46 additions & 0 deletions config/samples/konnect_kongtarget.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
kind: KonnectAPIAuthConfiguration
apiVersion: konnect.konghq.com/v1alpha1
metadata:
name: konnect-api-auth-dev-1
namespace: default
spec:
type: token
token: kpat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
serverURL: us.api.konghq.com
---
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha1
metadata:
name: test1
namespace: default
spec:
name: test1
labels:
app: test1
key1: test1
konnect:
authRef:
name: konnect-api-auth-dev-1
---
kind: KongUpstream
apiVersion: configuration.konghq.com/v1alpha1
metadata:
name: upstream-1
namespace: default
spec:
name: upstream-1
controlPlaneRef:
type: konnectNamespacedRef
konnectNamespacedRef:
name: test1
---
kind: KongTarget
apiVersion: configuration.konghq.com/v1alpha1
metadata:
name: target-1
namespace: default
spec:
upstreamRef:
name: upstream-1
target: "10.0.0.1"
weight: 100
12 changes: 12 additions & 0 deletions controller/konnect/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,15 @@ type ReferencedKongUpstreamIsBeingDeleted struct {
func (e ReferencedKongUpstreamIsBeingDeleted) Error() string {
return fmt.Sprintf("referenced Kong Upstream %s is being deleted", e.Reference)
}

// ReferencedKongUpstreamDoesNotExist is an error type that is returned when
// a Konnect entity references a Kong Upstream which does not exist.
type ReferencedKongUpstreamDoesNotExist struct {
Reference types.NamespacedName
Err error
}

// Error implements the error interface.
func (e ReferencedKongUpstreamDoesNotExist) Error() string {
return fmt.Sprintf("referenced Kong Upstream %s does not exist: %v", e.Reference, e.Err)
}
49 changes: 4 additions & 45 deletions controller/konnect/ops/ops_kongtarget.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@ import (
sdkkonnectops "github.com/Kong/sdk-konnect-go/models/operations"
sdkkonnecterrs "github.com/Kong/sdk-konnect-go/models/sdkerrors"
"github.com/samber/lo"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"

"github.com/kong/gateway-operator/controller/konnect/conditions"
k8sutils "github.com/kong/gateway-operator/pkg/utils/kubernetes"

configurationv1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1"
"github.com/kong/kubernetes-configuration/pkg/metadata"
)
Expand All @@ -42,30 +38,12 @@ func createTarget(
})

if errWrapped := wrapErrIfKonnectOpFailed(err, CreateOp, target); errWrapped != nil {
k8sutils.SetCondition(
k8sutils.NewConditionWithGeneration(
conditions.KonnectEntityProgrammedConditionType,
metav1.ConditionFalse,
"FailedToCreate",
errWrapped.Error(),
target.GetGeneration(),
),
target,
)
SetKonnectEntityProgrammedConditionFalse(target, "FailedToCreate", errWrapped.Error())
return errWrapped
}

target.Status.Konnect.SetKonnectID(*resp.Target.ID)
k8sutils.SetCondition(
k8sutils.NewConditionWithGeneration(
conditions.KonnectEntityProgrammedConditionType,
metav1.ConditionTrue,
conditions.KonnectEntityProgrammedReasonProgrammed,
"",
target.GetGeneration(),
),
target,
)
SetKonnectEntityProgrammedCondition(target)

return nil
}
Expand All @@ -91,30 +69,11 @@ func updateTarget(
})

if errWrapped := wrapErrIfKonnectOpFailed(err, UpdateOp, target); errWrapped != nil {
k8sutils.SetCondition(
k8sutils.NewConditionWithGeneration(
conditions.KonnectEntityProgrammedConditionType,
metav1.ConditionFalse,
"FailedToUpdate",
errWrapped.Error(),
target.GetGeneration(),
),
target,
)
SetKonnectEntityProgrammedConditionFalse(target, "FailedToUpdate", errWrapped.Error())
return errWrapped
}

k8sutils.SetCondition(
k8sutils.NewConditionWithGeneration(
conditions.KonnectEntityProgrammedConditionType,
metav1.ConditionTrue,
conditions.KonnectEntityProgrammedReasonProgrammed,
"",
target.GetGeneration(),
),
target,
)

SetKonnectEntityProgrammedCondition(target)
return nil
}

Expand Down
32 changes: 20 additions & 12 deletions controller/konnect/reconciler_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,20 +214,28 @@ func (r *KonnectEntityReconciler[T, TEnt]) Reconcile(
// If a type has a KongUpstream ref (KongTarget), handle it.
res, err = handleKongUpstreamRef(ctx, r.Client, ent)
if err != nil {
if !errors.As(err, &ReferencedKongUpstreamIsBeingDeleted{}) {
return ctrl.Result{}, err
}

// If the referenced KongUpstream is being deleted (has a non zero deletion timestamp)
// then we remove the entity if it has not been deleted yet (deletion timestamp is zero).
// We do this because Konnect blocks deletion of entities like Services/Upstreams
// if they contain entities like Routes/Targets.
if ent.GetDeletionTimestamp().IsZero() {
if err := r.Client.Delete(ctx, ent); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to delete %s: %w", client.ObjectKeyFromObject(ent), err)
// If the referenced KongUpstream is not found or is being deleted
// and the object is being deleted, remove the finalizer and let the
// deletion proceed without trying to delete the entity from Konnect
// as the KongUpstream deletion will take care of it on the Konnect side.
if errors.As(err, &ReferencedKongUpstreamIsBeingDeleted{}) ||
errors.As(err, &ReferencedKongUpstreamDoesNotExist{}) {
if !ent.GetDeletionTimestamp().IsZero() {
if controllerutil.RemoveFinalizer(ent, KonnectCleanupFinalizer) {
if err := r.Client.Update(ctx, ent); err != nil {
if k8serrors.IsConflict(err) {
return ctrl.Result{Requeue: true}, nil
}
return ctrl.Result{}, fmt.Errorf("failed to remove finalizer %s: %w", KonnectCleanupFinalizer, err)
}
log.Debug(logger, "finalizer removed as the owning KongUpstream is being deleted or is already gone", ent,
"finalizer", KonnectCleanupFinalizer,
)
}
}
return ctrl.Result{}, nil
}

return ctrl.Result{}, err
} else if res.Requeue {
return res, nil
}
Expand Down
5 changes: 4 additions & 1 deletion controller/konnect/reconciler_upstreamref.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ func handleKongUpstreamRef[T constraints.SupportedKonnectEntityType, TEnt constr
return res, errStatus
}

return ctrl.Result{}, fmt.Errorf("can't get the referenced KongUpstream %s: %w", nn, err)
return ctrl.Result{}, ReferencedKongUpstreamDoesNotExist{
Reference: nn,
Err: err,
}
}

// If referenced KongUpstream is being deleted, return an error so that we
Expand Down
2 changes: 1 addition & 1 deletion controller/konnect/reconciler_upstreamref_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func TestHandleUpstreamRef(t *testing.T) {
},
},
expectError: true,
expectErrorContains: "can't get the referenced KongUpstream",
expectErrorContains: "referenced Kong Upstream default/upstream-nonexist does not exist",
updatedEntAssertions: []func(*configurationv1alpha1.KongTarget) (bool, string){
func(kt *configurationv1alpha1.KongTarget) (bool, string) {
return lo.ContainsBy(kt.Status.Conditions, func(c metav1.Condition) bool {
Expand Down

0 comments on commit 3ea4f61

Please sign in to comment.