Skip to content

Commit

Permalink
feat: add Programmed condition to KongUpstreamPolicy ancestors status
Browse files Browse the repository at this point in the history
  • Loading branch information
czeslavo committed Jan 16, 2024
1 parent 3936d7d commit 96cbf05
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 25 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ Adding a new version? You'll need three changes:
enforce `KongUpstreamPolicy` status.
The controller will set an ancestor status in `KongUpstreamPolicy` status for
each of its ancestors (i.e. `Service` or `KongServiceFacade`) with the `Accepted`
condition.
and `Programmed` condition.
[#5185](https://github.com/Kong/kubernetes-ingress-controller/pull/5185)
[#5428](https://github.com/Kong/kubernetes-ingress-controller/pull/5428)
[#5444](https://github.com/Kong/kubernetes-ingress-controller/pull/5444)
- New CRD `KongVault` to reperesent a custom Kong vault for storing senstive
data used in plugin configurations. Now users can create a `KongVault` to
create a custom Kong vault and reference the values in configurations of
Expand Down
59 changes: 43 additions & 16 deletions internal/controllers/configuration/kongupstreampolicy_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
incubatorv1alpha1 "github.com/kong/kubernetes-ingress-controller/v3/pkg/apis/incubator/v1alpha1"
)

// maxNAncestors is the maximum number of ancestors that can be stored in the KongUpstreamPolicy status.
// This is a limitation of the Gateway API.
const maxNAncestors = 16

// upstreamPolicyAncestorKind represents kind of KongUpstreamPolicy ancestor (Service or KongServiceFacade).
Expand All @@ -32,10 +34,11 @@ const (
// ancestorStatus represents the status of an ancestor (Service or KongServiceFacade).
// A collection of all ancestors' statuses is used to build the KongUpstreamPolicy status.
type ancestorStatus struct {
namespacedName k8stypes.NamespacedName
ancestorKind upstreamPolicyAncestorKind
acceptedCondition metav1.Condition
creationTimestamp metav1.Time
namespacedName k8stypes.NamespacedName
ancestorKind upstreamPolicyAncestorKind
acceptedCondition metav1.Condition
programmedCondition metav1.Condition
creationTimestamp metav1.Time
}

// serviceKey is used as a key for indexing Services by "namespace/name".
Expand Down Expand Up @@ -146,38 +149,58 @@ func (r *KongUpstreamPolicyReconciler) buildAncestorsStatus(
Reason: string(gatewayapi.PolicyReasonAccepted),
LastTransitionTime: metav1.Now(),
}
conflictedCondition := metav1.Condition{
Type: string(gatewayapi.PolicyConditionAccepted),
Status: metav1.ConditionFalse,
Reason: string(gatewayapi.PolicyReasonConflicted),
programmedCondition := metav1.Condition{
Type: string(gatewayapi.GatewayConditionProgrammed),
Status: metav1.ConditionTrue,
Reason: string(gatewayapi.GatewayReasonProgrammed),
LastTransitionTime: metav1.Now(),
}

// Build the status for each ancestor (Services and KongServiceFacades).
ancestorsStatus := make([]ancestorStatus, 0, len(services)+len(serviceFacades))
for _, service := range services {
condition := acceptedCondition
service := service
acceptedCondition := acceptedCondition
if _, isConflicted := conflictedServices[buildServiceReference(service.Namespace, service.Name)]; isConflicted {
// If the service is conflicted, we will use the conflictedCondition.
condition = conflictedCondition
// If the Service is conflicted, we change it to False.
acceptedCondition.Status = metav1.ConditionFalse
acceptedCondition.Reason = string(gatewayapi.PolicyReasonConflicted)
}

programmedCondition := programmedCondition
if !r.DataplaneClient.KubernetesObjectIsConfigured(&service) {
// If the Service is not configured, we change it to False.
programmedCondition.Status = metav1.ConditionFalse
programmedCondition.Reason = string(gatewayapi.GatewayReasonPending)
}

ancestorsStatus = append(ancestorsStatus, ancestorStatus{
namespacedName: k8stypes.NamespacedName{
Namespace: service.Namespace,
Name: service.Name,
},
ancestorKind: upstreamPolicyAncestorKindService,
acceptedCondition: condition,
ancestorKind: upstreamPolicyAncestorKindService,
acceptedCondition: acceptedCondition,
programmedCondition: programmedCondition,
})
}
for _, serviceFacade := range serviceFacades {
serviceFacade := serviceFacade
programmedCondition := programmedCondition
if !r.DataplaneClient.KubernetesObjectIsConfigured(&serviceFacade) {
// If the KongServiceFacade is not configured, we change it to False.
programmedCondition.Status = metav1.ConditionFalse
programmedCondition.Reason = string(gatewayapi.GatewayReasonPending)
}

ancestorsStatus = append(ancestorsStatus, ancestorStatus{
namespacedName: k8stypes.NamespacedName{
Namespace: serviceFacade.Namespace,
Name: serviceFacade.Name,
},
ancestorKind: upstreamPolicyAncestorKindKongServiceFacade,
acceptedCondition: acceptedCondition,
ancestorKind: upstreamPolicyAncestorKindKongServiceFacade,
acceptedCondition: acceptedCondition,
programmedCondition: programmedCondition,
})
}

Expand Down Expand Up @@ -262,6 +285,9 @@ func getAllBackendRefsUsedWithService(httpRoute gatewayapi.HTTPRoute, serviceKey
return backendRefs
}

// buildPolicyStatus builds the KongUpstreamPolicy status from the ancestors' statuses.
// It ensures that the number of ancestors is not greater than the maximum allowed by the Gateway API
// and that the oldest ancestors are kept.
func (r *KongUpstreamPolicyReconciler) buildPolicyStatus(
upstreamPolicyNN k8stypes.NamespacedName,
ancestorsStatus []ancestorStatus,
Expand All @@ -271,7 +297,7 @@ func (r *KongUpstreamPolicyReconciler) buildPolicyStatus(
return ancestorsStatus[i].creationTimestamp.Before(&ancestorsStatus[j].creationTimestamp)
})
if len(ancestorsStatus) > maxNAncestors {
r.Log.Info("status has too many ancestors, the newest ones will be ignored",
r.Log.Info("status has more ancestors than the Gateway API permits, the newest ones will be ignored",
"KongUpstreamPolicy", upstreamPolicyNN.String(),
"ancestorsCount", len(ancestorsStatus),
"maxAllowedAncestors", maxNAncestors,
Expand All @@ -295,6 +321,7 @@ func (r *KongUpstreamPolicyReconciler) buildPolicyStatus(
ControllerName: gatewaycontroller.GetControllerName(),
Conditions: []metav1.Condition{
ss.acceptedCondition,
ss.programmedCondition,
},
},
)
Expand Down
Loading

0 comments on commit 96cbf05

Please sign in to comment.