-
Notifications
You must be signed in to change notification settings - Fork 28
/
authpolicy_status.go
109 lines (89 loc) · 3.9 KB
/
authpolicy_status.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package controllers
import (
"context"
"fmt"
"slices"
"github.com/go-logr/logr"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
authorinoapi "github.com/kuadrant/authorino/api/v1beta2"
api "github.com/kuadrant/kuadrant-operator/api/v1beta2"
)
const APAvailableConditionType string = "Available"
// reconcileStatus makes sure status block of AuthPolicy is up-to-date.
func (r *AuthPolicyReconciler) reconcileStatus(ctx context.Context, ap *api.AuthPolicy, specErr error) (ctrl.Result, error) {
logger, _ := logr.FromContext(ctx)
logger.V(1).Info("Reconciling AuthPolicy status", "spec error", specErr)
// fetch the AuthConfig and check if it's ready.
isAuthConfigReady := true
if specErr == nil { // skip fetching authconfig if we already have a reconciliation error.
apKey := client.ObjectKeyFromObject(ap)
authConfigKey := client.ObjectKey{
Namespace: ap.Namespace,
Name: authConfigName(apKey),
}
authConfig := &authorinoapi.AuthConfig{}
if err := r.GetResource(ctx, authConfigKey, authConfig); err != nil && !apierrors.IsNotFound(err) {
return ctrl.Result{}, err
}
isAuthConfigReady = authConfig.Status.Ready()
}
newStatus := r.calculateStatus(ap, specErr, isAuthConfigReady)
equalStatus := ap.Status.Equals(newStatus, logger)
logger.V(1).Info("Status", "status is different", !equalStatus)
logger.V(1).Info("Status", "generation is different", ap.Generation != ap.Status.ObservedGeneration)
logger.V(1).Info("Status", "AuthConfig is ready", isAuthConfigReady)
if equalStatus && ap.Generation == ap.Status.ObservedGeneration {
logger.V(1).Info("Status up-to-date. No changes required.")
return ctrl.Result{}, nil
}
// Save the generation number we acted on, otherwise we might wrongfully indicate
// that we've seen a spec update when we retry.
// TODO: This can clobber an update if we allow multiple agents to write to the
// same status.
newStatus.ObservedGeneration = ap.Generation
logger.V(1).Info("Updating Status", "sequence no:", fmt.Sprintf("sequence No: %v->%v", ap.Status.ObservedGeneration, newStatus.ObservedGeneration))
ap.Status = *newStatus
updateErr := r.Client().Status().Update(ctx, ap)
if updateErr != nil {
// Ignore conflicts, resource might just be outdated.
if apierrors.IsConflict(updateErr) {
logger.Info("Failed to update status: resource might just be outdated")
return ctrl.Result{Requeue: true}, nil
}
return ctrl.Result{}, fmt.Errorf("failed to update status: %w", updateErr)
}
return ctrl.Result{}, nil
}
func (r *AuthPolicyReconciler) calculateStatus(ap *api.AuthPolicy, specErr error, authConfigReady bool) *api.AuthPolicyStatus {
newStatus := &api.AuthPolicyStatus{
Conditions: slices.Clone(ap.Status.Conditions),
ObservedGeneration: ap.Status.ObservedGeneration,
}
targetNetworkObjectKind := string(ap.Spec.TargetRef.Kind)
availableCond := r.availableCondition(targetNetworkObjectKind, specErr, authConfigReady)
meta.SetStatusCondition(&newStatus.Conditions, *availableCond)
return newStatus
}
func (r *AuthPolicyReconciler) availableCondition(targetNetworkObjectectKind string, specErr error, authConfigReady bool) *metav1.Condition {
// Condition if there is no issue
cond := &metav1.Condition{
Type: APAvailableConditionType,
Status: metav1.ConditionTrue,
Reason: fmt.Sprintf("%sProtected", targetNetworkObjectectKind),
Message: fmt.Sprintf("%s is protected", targetNetworkObjectectKind),
}
if specErr != nil {
cond.Status = metav1.ConditionFalse
cond.Reason = "ReconciliationError"
cond.Message = specErr.Error()
} else if !authConfigReady {
cond.Status = metav1.ConditionFalse
cond.Reason = "AuthSchemeNotReady"
cond.Message = "AuthScheme is not ready yet" // TODO(rahul): need to take care if status change is delayed.
}
return cond
}