Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement: report dependency not installed to kuadrant & policy status #994

Merged
merged 12 commits into from
Jan 20, 2025
Merged
36 changes: 34 additions & 2 deletions controllers/auth_policies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import (
"k8s.io/utils/ptr"

kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1"
kuadrant "github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

type AuthPolicyValidator struct{}
type AuthPolicyValidator struct {
isGatewayAPIInstalled bool
isGatewayProviderInstalled bool
isAuthorinoOperatorInstalled bool
}

// AuthPolicyValidator subscribes to events with potential to flip the validity of auth policies
func (r *AuthPolicyValidator) Subscription() controller.Subscription {
Expand All @@ -41,6 +45,10 @@ func (r *AuthPolicyValidator) Validate(ctx context.Context, _ []controller.Resou
defer logger.V(1).Info("finished validating auth policies")

state.Store(StateAuthPolicyValid, lo.SliceToMap(policies, func(policy machinery.Policy) (string, error) {
if err := r.isMissingDependency(); err != nil {
return policy.GetLocator(), err
}

var err error
if len(policy.GetTargetRefs()) > 0 && len(topology.Targetables().Children(policy)) == 0 {
ref := policy.GetTargetRefs()[0]
Expand All @@ -58,3 +66,27 @@ func (r *AuthPolicyValidator) Validate(ctx context.Context, _ []controller.Resou

return nil
}

func (r *AuthPolicyValidator) isMissingDependency() error {
isMissingDependency := false
var missingDependencies []string

if !r.isGatewayAPIInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API")
}
if !r.isGatewayProviderInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API provider (istio / envoy gateway)")
}
if !r.isAuthorinoOperatorInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Authorino Operator")
}

if isMissingDependency {
return kuadrant.NewErrDependencyNotInstalled(missingDependencies...)
}

return nil
}
7 changes: 4 additions & 3 deletions controllers/data_plane_policies_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ var (
//+kubebuilder:rbac:groups=kuadrant.io,resources=ratelimitpolicies/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=kuadrant.io,resources=ratelimitpolicies/finalizers,verbs=update

func NewDataPlanePoliciesWorkflow(client *dynamic.DynamicClient, isIstioInstalled, isEnvoyGatewayInstalled bool) *controller.Workflow {
func NewDataPlanePoliciesWorkflow(client *dynamic.DynamicClient, isGatewayAPInstalled, isIstioInstalled, isEnvoyGatewayInstalled, isLimitadorOperatorInstalled, isAuthorinoOperatorInstalled bool) *controller.Workflow {
isGatewayProviderInstalled := isIstioInstalled || isEnvoyGatewayInstalled
dataPlanePoliciesValidation := &controller.Workflow{
Tasks: []controller.ReconcileFunc{
(&AuthPolicyValidator{}).Subscription().Reconcile,
(&RateLimitPolicyValidator{}).Subscription().Reconcile,
(&AuthPolicyValidator{isGatewayAPIInstalled: isGatewayAPInstalled, isAuthorinoOperatorInstalled: isAuthorinoOperatorInstalled, isGatewayProviderInstalled: isGatewayProviderInstalled}).Subscription().Reconcile,
(&RateLimitPolicyValidator{isGatewayAPIInstalled: isGatewayAPInstalled, isLimitadorOperatorInstalled: isLimitadorOperatorInstalled, isGatewayProviderInstalled: isGatewayProviderInstalled}).Subscription().Reconcile,
},
}

Expand Down
4 changes: 2 additions & 2 deletions controllers/dns_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ var (
//+kubebuilder:rbac:groups=kuadrant.io,resources=dnsrecords,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=kuadrant.io,resources=dnsrecords/status,verbs=get

func NewDNSWorkflow(client *dynamic.DynamicClient, scheme *runtime.Scheme) *controller.Workflow {
func NewDNSWorkflow(client *dynamic.DynamicClient, scheme *runtime.Scheme, isGatewayAPIInstalled, isDNSOperatorInstalled bool) *controller.Workflow {
return &controller.Workflow{
Precondition: NewDNSPoliciesValidator().Subscription().Reconcile,
Precondition: NewDNSPoliciesValidator(isGatewayAPIInstalled, isDNSOperatorInstalled).Subscription().Reconcile,
Tasks: []controller.ReconcileFunc{
NewEffectiveDNSPoliciesReconciler(client, scheme).Subscription().Reconcile,
},
Expand Down
36 changes: 33 additions & 3 deletions controllers/dnspolicies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ import (
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

func NewDNSPoliciesValidator() *DNSPoliciesValidator {
return &DNSPoliciesValidator{}
func NewDNSPoliciesValidator(isGatewayAPIInstalled, isDNSOperatorInstalled bool) *DNSPoliciesValidator {
return &DNSPoliciesValidator{
isGatewayAPIInstalled: isGatewayAPIInstalled,
isDNSOperatorInstalled: isDNSOperatorInstalled,
}
}

type DNSPoliciesValidator struct{}
type DNSPoliciesValidator struct {
isGatewayAPIInstalled bool
isDNSOperatorInstalled bool
}

func (r *DNSPoliciesValidator) Subscription() controller.Subscription {
return controller.Subscription{
Expand All @@ -45,6 +51,10 @@ func (r *DNSPoliciesValidator) validate(ctx context.Context, _ []controller.Reso
logger.V(1).Info("validating dns policies", "policies", len(policies))

state.Store(StateDNSPolicyAcceptedKey, lo.SliceToMap(policies, func(p machinery.Policy) (string, error) {
if err := r.isMissingDependency(); err != nil {
return p.GetLocator(), err
}

policy := p.(*kuadrantv1.DNSPolicy)

if err := isTargetRefsFound(topology, policy); err != nil {
Expand All @@ -63,6 +73,26 @@ func (r *DNSPoliciesValidator) validate(ctx context.Context, _ []controller.Reso
return nil
}

func (r *DNSPoliciesValidator) isMissingDependency() error {
isMissingDependency := false
var missingDependencies []string

if !r.isGatewayAPIInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API")
}
if !r.isDNSOperatorInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "DNS Operator")
}

if isMissingDependency {
return kuadrant.NewErrDependencyNotInstalled(missingDependencies...)
}

return nil
}

// isTargetRefsFound Policies are already linked to their targets.
// If the target ref length and length of targetables by this policy is not the same, then the policy could not find the target.
func isTargetRefsFound(topology *machinery.Topology, p *kuadrantv1.DNSPolicy) error {
Expand Down
55 changes: 47 additions & 8 deletions controllers/kuadrant_status_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"

"github.com/go-logr/logr"
limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1"
"github.com/kuadrant/policy-machinery/controller"
"github.com/kuadrant/policy-machinery/machinery"
corev1 "k8s.io/api/core/v1"
Expand All @@ -18,19 +19,29 @@ import (

kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1"
"github.com/kuadrant/kuadrant-operator/pkg/authorino"
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

const (
ReadyConditionType string = "Ready"
)

type KuadrantStatusUpdater struct {
Client *dynamic.DynamicClient
HasGateway bool
Client *dynamic.DynamicClient
isGatewayAPIInstalled bool
isGatewayProviderInstalled bool
isLimitadorOperatorInstalled bool
isAuthorinoOperatorInstalled bool
}

func NewKuadrantStatusUpdater(client *dynamic.DynamicClient, isIstioInstalled, isEnvoyGatewayInstalled bool) *KuadrantStatusUpdater {
return &KuadrantStatusUpdater{Client: client, HasGateway: isIstioInstalled || isEnvoyGatewayInstalled}
func NewKuadrantStatusUpdater(client *dynamic.DynamicClient, isGatewayAPIInstalled, isGatewayProviderInstalled, isLimitadorOperatorInstalled, isAuthorinoOperatorInstalled bool) *KuadrantStatusUpdater {
return &KuadrantStatusUpdater{
Client: client,
isGatewayAPIInstalled: isGatewayAPIInstalled,
isGatewayProviderInstalled: isGatewayProviderInstalled,
isLimitadorOperatorInstalled: isLimitadorOperatorInstalled,
isAuthorinoOperatorInstalled: isAuthorinoOperatorInstalled,
}
}

func (r *KuadrantStatusUpdater) Subscription() *controller.Subscription {
Expand Down Expand Up @@ -117,10 +128,10 @@ func (r *KuadrantStatusUpdater) readyCondition(topology *machinery.Topology, log
Message: "Kuadrant is ready",
}

if !r.HasGateway {
if err := r.isMissingDependency(); err != nil {
cond.Status = metav1.ConditionFalse
cond.Reason = "GatewayAPIProviderNotFound"
cond.Message = "GatewayAPI provider not found"
cond.Reason = string(err.Reason())
cond.Message = err.Error()
return cond
}

Expand All @@ -141,14 +152,42 @@ func (r *KuadrantStatusUpdater) readyCondition(topology *machinery.Topology, log
return cond
}

func (r *KuadrantStatusUpdater) isMissingDependency() kuadrant.PolicyError {
isMissingDependency := false
var missingDependencies []string

if !r.isGatewayAPIInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API")
}
if !r.isGatewayProviderInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API provider (istio / envoy gateway)")
}
if !r.isAuthorinoOperatorInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Authorino Operator")
}
if !r.isLimitadorOperatorInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Limitador Operator")
}

if isMissingDependency {
return kuadrant.NewErrDependencyNotInstalled(missingDependencies...)
}

return nil
}

func checkLimitadorReady(topology *machinery.Topology, logger logr.Logger) *string {
limitadorObj := GetLimitadorFromTopology(topology)
if limitadorObj == nil {
logger.V(1).Info("failed getting Limitador resource from topology", "status", "error")
return ptr.To("limitador resoure not in topology")
}

statusConditionReady := meta.FindStatusCondition(limitadorObj.Status.Conditions, "Ready")
statusConditionReady := meta.FindStatusCondition(limitadorObj.Status.Conditions, limitadorv1alpha1.StatusConditionReady)
if statusConditionReady == nil {
return ptr.To("Ready condition not found")
}
Expand Down
36 changes: 34 additions & 2 deletions controllers/ratelimit_policies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import (
"k8s.io/utils/ptr"

kuadrantv1 "github.com/kuadrant/kuadrant-operator/api/v1"
kuadrant "github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

type RateLimitPolicyValidator struct{}
type RateLimitPolicyValidator struct {
isLimitadorOperatorInstalled bool
isGatewayAPIInstalled bool
isGatewayProviderInstalled bool
}

// RateLimitPolicyValidator subscribes to events with potential to flip the validity of rate limit policies
func (r *RateLimitPolicyValidator) Subscription() controller.Subscription {
Expand All @@ -41,6 +45,10 @@ func (r *RateLimitPolicyValidator) Validate(ctx context.Context, _ []controller.
defer logger.V(1).Info("finished validating rate limit policies")

state.Store(StateRateLimitPolicyValid, lo.SliceToMap(policies, func(policy machinery.Policy) (string, error) {
if err := r.isMissingDependency(); err != nil {
return policy.GetLocator(), err
}

var err error
if len(policy.GetTargetRefs()) > 0 && len(topology.Targetables().Children(policy)) == 0 {
ref := policy.GetTargetRefs()[0]
Expand All @@ -58,3 +66,27 @@ func (r *RateLimitPolicyValidator) Validate(ctx context.Context, _ []controller.

return nil
}

func (r *RateLimitPolicyValidator) isMissingDependency() error {
isMissingDependency := false
var missingDependencies []string

if !r.isGatewayAPIInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API")
}
if !r.isGatewayProviderInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Gateway API provider (istio / envoy gateway)")
}
if !r.isLimitadorOperatorInstalled {
isMissingDependency = true
missingDependencies = append(missingDependencies, "Limitador Operator")
}

if isMissingDependency {
return kuadrant.NewErrDependencyNotInstalled(missingDependencies...)
}

return nil
}
Loading
Loading