Skip to content

Commit

Permalink
feat: gateway api detection on kuadrant and policy status
Browse files Browse the repository at this point in the history
Signed-off-by: KevFan <[email protected]>
  • Loading branch information
KevFan committed Nov 13, 2024
1 parent d4a8f4f commit eb0788d
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 50 deletions.
7 changes: 6 additions & 1 deletion controllers/auth_policies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ 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 {
isGatewayAPIInstalled bool
isAuthorinoOperatorInstalled bool
}

Expand Down Expand Up @@ -43,6 +44,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 !r.isGatewayAPIInstalled {
return policy.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Gateway API")
}

if !r.isAuthorinoOperatorInstalled {
return policy.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Authorino Operator")
}
Expand Down
6 changes: 3 additions & 3 deletions controllers/data_plane_policies_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ 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, isLimitadorOperatorInstalled, isAuthorinoOperatorInstalled bool) *controller.Workflow {
func NewDataPlanePoliciesWorkflow(client *dynamic.DynamicClient, isGatewayAPInstalled, isIstioInstalled, isEnvoyGatewayInstalled, isLimitadorOperatorInstalled, isAuthorinoOperatorInstalled bool) *controller.Workflow {
dataPlanePoliciesValidation := &controller.Workflow{
Tasks: []controller.ReconcileFunc{
(&AuthPolicyValidator{isAuthorinoOperatorInstalled: isAuthorinoOperatorInstalled}).Subscription().Reconcile,
(&RateLimitPolicyValidator{isLimitadorOperatorInstalled: isLimitadorOperatorInstalled}).Subscription().Reconcile,
(&AuthPolicyValidator{isGatewayAPIInstalled: isGatewayAPInstalled, isAuthorinoOperatorInstalled: isAuthorinoOperatorInstalled}).Subscription().Reconcile,
(&RateLimitPolicyValidator{isGatewayAPIInstalled: isGatewayAPInstalled, isLimitadorOperatorInstalled: isLimitadorOperatorInstalled}).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, isDNSOperatorInstalled bool) *controller.Workflow {
func NewDNSWorkflow(client *dynamic.DynamicClient, scheme *runtime.Scheme, isGatewayAPIInstalled, isDNSOperatorInstalled bool) *controller.Workflow {
return &controller.Workflow{
Precondition: NewDNSPoliciesValidator(isDNSOperatorInstalled).Subscription().Reconcile,
Precondition: NewDNSPoliciesValidator(isGatewayAPIInstalled, isDNSOperatorInstalled).Subscription().Reconcile,
Tasks: []controller.ReconcileFunc{
NewEffectiveDNSPoliciesReconciler(client, scheme).Subscription().Reconcile,
},
Expand Down
8 changes: 7 additions & 1 deletion controllers/dnspolicies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

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

type DNSPoliciesValidator struct {
isGatewayAPIInstalled bool
isDNSOperatorInstalled bool
}

Expand All @@ -49,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 !r.isGatewayAPIInstalled {
return p.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Gateway API")
}

if !r.isDNSOperatorInstalled {
return p.GetLocator(), kuadrant.NewErrDependencyNotInstalled("DNS Operator")
}
Expand Down
18 changes: 16 additions & 2 deletions controllers/kuadrant_status_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,20 @@ const (

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

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

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

if !r.isGatwayAPIInstalled {
cond.Status = metav1.ConditionFalse
cond.Reason = "GatewayAPI"
cond.Message = kuadrant.NewErrDependencyNotInstalled("Gateway API").Error()
return cond
}

if !r.HasGateway {
cond.Status = metav1.ConditionFalse
cond.Reason = "GatewayAPIProviderNotFound"
Expand Down
7 changes: 6 additions & 1 deletion controllers/ratelimit_policies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ 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 {
isLimitadorOperatorInstalled bool
isGatewayAPIInstalled bool
}

// RateLimitPolicyValidator subscribes to events with potential to flip the validity of rate limit policies
Expand All @@ -43,6 +44,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 !r.isGatewayAPIInstalled {
return policy.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Gateway API")
}

if !r.isLimitadorOperatorInstalled {
return policy.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Limitador Operator")
}
Expand Down
24 changes: 16 additions & 8 deletions controllers/state_of_the_world.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,16 +392,20 @@ func (b *BootOptionsBuilder) getAuthorinoOperatorOptions() []controller.Controll
return opts
}

func (b *BootOptionsBuilder) isGatewayProviderInstalled() bool {
return b.isIstioInstalled || b.isEnvoyGatewayInstalled
}

func (b *BootOptionsBuilder) Reconciler() controller.ReconcileFunc {
mainWorkflow := &controller.Workflow{
Precondition: initWorkflow(b.client).Run,
Tasks: []controller.ReconcileFunc{
NewDNSWorkflow(b.client, b.manager.GetScheme(), b.isDNSOperatorInstalled).Run,
NewTLSWorkflow(b.client, b.manager.GetScheme(), b.isCertManagerInstalled).Run,
NewDataPlanePoliciesWorkflow(b.client, b.isIstioInstalled, b.isEnvoyGatewayInstalled, b.isLimitadorOperatorInstalled, b.isAuthorinoOperatorInstalled).Run,
NewKuadrantStatusUpdater(b.client, b.isIstioInstalled, b.isEnvoyGatewayInstalled, b.isLimitadorOperatorInstalled, b.isAuthorinoOperatorInstalled).Subscription().Reconcile,
NewDNSWorkflow(b.client, b.manager.GetScheme(), b.isGatewayAPIInstalled, b.isDNSOperatorInstalled).Run,
NewTLSWorkflow(b.client, b.manager.GetScheme(), b.isGatewayAPIInstalled, b.isCertManagerInstalled).Run,
NewDataPlanePoliciesWorkflow(b.client, b.isGatewayAPIInstalled, b.isIstioInstalled, b.isEnvoyGatewayInstalled, b.isLimitadorOperatorInstalled, b.isAuthorinoOperatorInstalled).Run,
NewKuadrantStatusUpdater(b.client, b.isGatewayAPIInstalled, b.isGatewayProviderInstalled(), b.isLimitadorOperatorInstalled, b.isAuthorinoOperatorInstalled).Subscription().Reconcile,
},
Postcondition: finalStepsWorkflow(b.client, b.isIstioInstalled, b.isGatewayAPIInstalled).Run,
Postcondition: finalStepsWorkflow(b.client, b.isGatewayAPIInstalled, b.isIstioInstalled, b.isEnvoyGatewayInstalled).Run,
}

if b.isConsolePluginInstalled {
Expand Down Expand Up @@ -495,12 +499,16 @@ func initWorkflow(client *dynamic.DynamicClient) *controller.Workflow {
}
}

func finalStepsWorkflow(client *dynamic.DynamicClient, isIstioInstalled, isEnvoyGatewayInstalled bool) *controller.Workflow {
func finalStepsWorkflow(client *dynamic.DynamicClient, isGatewayAPIInstalled, isIstioInstalled, isEnvoyGatewayInstalled bool) *controller.Workflow {
workflow := &controller.Workflow{
Tasks: []controller.ReconcileFunc{
Tasks: []controller.ReconcileFunc{},
}

if isGatewayAPIInstalled {
workflow.Tasks = append(workflow.Tasks,
NewGatewayPolicyDiscoverabilityReconciler(client).Subscription().Reconcile,
NewHTTPRoutePolicyDiscoverabilityReconciler(client).Subscription().Reconcile,
},
)
}

if isIstioInstalled {
Expand Down
4 changes: 2 additions & 2 deletions controllers/tls_workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ var (
//+kubebuilder:rbac:groups="cert-manager.io",resources=clusterissuers,verbs=get;list;watch;
//+kubebuilder:rbac:groups="cert-manager.io",resources=certificates,verbs=get;list;watch;create;update;patch;delete

func NewTLSWorkflow(client *dynamic.DynamicClient, scheme *runtime.Scheme, isCertManagerInstalled bool) *controller.Workflow {
func NewTLSWorkflow(client *dynamic.DynamicClient, scheme *runtime.Scheme, isGatewayAPIInstalled, isCertManagerInstalled bool) *controller.Workflow {
return &controller.Workflow{
Precondition: NewTLSPoliciesValidator(isCertManagerInstalled).Subscription().Reconcile,
Precondition: NewTLSPoliciesValidator(isGatewayAPIInstalled, isCertManagerInstalled).Subscription().Reconcile,
Tasks: []controller.ReconcileFunc{
NewEffectiveTLSPoliciesReconciler(client, scheme).Subscription().Reconcile,
},
Expand Down
47 changes: 21 additions & 26 deletions controllers/tlspolicies_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ import (
"github.com/kuadrant/kuadrant-operator/pkg/kuadrant"
)

func NewTLSPoliciesValidator(isCertManagerInstalled bool) *TLSPoliciesValidator {
func NewTLSPoliciesValidator(isGatewayAPIInstalled, isCertManagerInstalled bool) *TLSPoliciesValidator {
return &TLSPoliciesValidator{
isGatewayAPIInstalled: isGatewayAPIInstalled,
isCertManagerInstalled: isCertManagerInstalled,
}
}

type TLSPoliciesValidator struct {
isGatewayAPIInstalled bool
isCertManagerInstalled bool
}

Expand All @@ -42,53 +44,46 @@ func (t *TLSPoliciesValidator) Subscription() *controller.Subscription {
}
}

func (t *TLSPoliciesValidator) Validate(ctx context.Context, _ []controller.ResourceEvent, topology *machinery.Topology, _ error, s *sync.Map) error {
func (t *TLSPoliciesValidator) Validate(ctx context.Context, _ []controller.ResourceEvent, topology *machinery.Topology, _ error, state *sync.Map) error {
logger := controller.LoggerFromContext(ctx).WithName("TLSPoliciesValidator").WithName("Validate")

policies := lo.Filter(topology.Policies().Items(), filterForTLSPolicies)
logger.V(1).Info("validating tls policies", "policies", len(policies))

isPolicyValidErrorMap := make(map[string]error, len(policies))

for _, policy := range policies {
p := policy.(*kuadrantv1.TLSPolicy)
if p.DeletionTimestamp != nil {
logger.V(1).Info("tls policy is marked for deletion, skipping", "name", p.Name, "namespace", p.Namespace)
continue
state.Store(TLSPolicyAcceptedKey, lo.SliceToMap(policies, func(p machinery.Policy) (string, error) {
if !t.isGatewayAPIInstalled {
return p.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Gateway API")
}

if !t.isCertManagerInstalled {
isPolicyValidErrorMap[p.GetLocator()] = kuadrant.NewErrDependencyNotInstalled("Cert Manager")
continue
return p.GetLocator(), kuadrant.NewErrDependencyNotInstalled("Cert Manager")
}

policy := p.(*kuadrantv1.TLSPolicy)
// Validate target ref
if err := t.isTargetRefsFound(topology, p); err != nil {
isPolicyValidErrorMap[p.GetLocator()] = err
continue
if err := t.isTargetRefsFound(topology, policy); err != nil {
return p.GetLocator(), err
}

// Validate if there's a conflicting policy
if err := t.isConflict(policies, p); err != nil {
isPolicyValidErrorMap[p.GetLocator()] = err
continue
if err := t.isConflict(policies, policy); err != nil {
return p.GetLocator(), err
}

// Validate IssuerRef kind is correct
if err := t.isValidIssuerKind(p); err != nil {
isPolicyValidErrorMap[p.GetLocator()] = err
continue
if err := t.isValidIssuerKind(policy); err != nil {
return p.GetLocator(), err
}

// Validate Issuer is present on cluster through the topology
if err := t.isIssuerFound(topology, p); err != nil {
isPolicyValidErrorMap[p.GetLocator()] = err
continue
if err := t.isIssuerFound(topology, policy); err != nil {
return p.GetLocator(), err
}

isPolicyValidErrorMap[p.GetLocator()] = nil
}
return p.GetLocator(), nil
}))

s.Store(TLSPolicyAcceptedKey, isPolicyValidErrorMap)
logger.V(1).Info("finished validating tls policies")

return nil
}
Expand Down
Loading

0 comments on commit eb0788d

Please sign in to comment.