From 26d3a47632d3ca3af4ebd40e8064c1d0074f4cb6 Mon Sep 17 00:00:00 2001 From: Michael Nairn Date: Tue, 8 Oct 2024 17:49:16 +0100 Subject: [PATCH] sotw: dnspolicy init Add basic setup for DNSPolicy state of the world tasks, dnsrecord types, watcher and linker function (Listener -> DNSRecord) Signed-off-by: Michael Nairn --- controllers/dns_workflow.go | 58 ++++++++++++++++++- controllers/dnspolicies_validator.go | 44 ++++++++++++++ controllers/dnspolicy_controller.go | 8 --- controllers/dnspolicy_status_updater.go | 36 ++++++++++++ .../effective_dnspolicies_reconciler.go | 35 +++++++++++ controllers/state_of_the_world.go | 19 +++++- 6 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 controllers/dnspolicies_validator.go create mode 100644 controllers/dnspolicy_status_updater.go create mode 100644 controllers/effective_dnspolicies_reconciler.go diff --git a/controllers/dns_workflow.go b/controllers/dns_workflow.go index 99787a34c..99e4a0bf3 100644 --- a/controllers/dns_workflow.go +++ b/controllers/dns_workflow.go @@ -1,7 +1,59 @@ package controllers -import "github.com/kuadrant/policy-machinery/controller" +import ( + "github.com/samber/lo" -func NewDNSWorkflow() *controller.Workflow { - return &controller.Workflow{} + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + + kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" + "github.com/kuadrant/policy-machinery/controller" + "github.com/kuadrant/policy-machinery/machinery" +) + +var ( + DNSRecordResource = kuadrantdnsv1alpha1.GroupVersion.WithResource("dnsrecords") + DNSRecordGroupKind = schema.GroupKind{Group: kuadrantdnsv1alpha1.GroupVersion.Group, Kind: "DNSRecord"} +) + +//+kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch +//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies,verbs=get;list;watch;update;patch;delete +//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/finalizers,verbs=update + +//+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) *controller.Workflow { + return &controller.Workflow{ + Precondition: NewDNSPoliciesValidator().Subscription().Reconcile, + Tasks: []controller.ReconcileFunc{(&controller.Workflow{ + Tasks: []controller.ReconcileFunc{ + NewEffectiveDNSPoliciesReconciler(client).Subscription().Reconcile, + }, + }).Run}, + Postcondition: NewDNSPolicyStatusUpdater(client).Subscription().Reconcile, + } +} + +func LinkListenerToDNSRecord(objs controller.Store) machinery.LinkFunc { + gateways := lo.Map(objs.FilterByGroupKind(machinery.GatewayGroupKind), controller.ObjectAs[*gwapiv1.Gateway]) + listeners := lo.FlatMap(lo.Map(gateways, func(g *gwapiv1.Gateway, _ int) *machinery.Gateway { + return &machinery.Gateway{Gateway: g} + }), machinery.ListenersFromGatewayFunc) + + return machinery.LinkFunc{ + From: machinery.ListenerGroupKind, + To: DNSRecordGroupKind, + Func: func(child machinery.Object) []machinery.Object { + return lo.FilterMap(listeners, func(l *machinery.Listener, _ int) (machinery.Object, bool) { + if dnsRecord, ok := child.(*controller.RuntimeObject).Object.(*kuadrantdnsv1alpha1.DNSRecord); ok { + return l, l.GetNamespace() == dnsRecord.GetNamespace() && + dnsRecord.GetName() == dnsRecordName(l.Gateway.Name, string(l.Name)) + } + return nil, false + }) + }, + } } diff --git a/controllers/dnspolicies_validator.go b/controllers/dnspolicies_validator.go new file mode 100644 index 000000000..a991bb50a --- /dev/null +++ b/controllers/dnspolicies_validator.go @@ -0,0 +1,44 @@ +package controllers + +import ( + "context" + "sync" + + "github.com/kuadrant/policy-machinery/controller" + "github.com/kuadrant/policy-machinery/machinery" + "github.com/samber/lo" + + kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" +) + +var ( + StateDNSPolicyValid = struct{}{} +) + +func NewDNSPoliciesValidator() *DNSPoliciesValidator { + return &DNSPoliciesValidator{} +} + +type DNSPoliciesValidator struct{} + +func (r *DNSPoliciesValidator) Subscription() controller.Subscription { + return controller.Subscription{ + ReconcileFunc: r.validate, + Events: []controller.ResourceEventMatcher{ + {Kind: &machinery.GatewayGroupKind}, + {Kind: &kuadrantv1alpha1.DNSPolicyGroupKind}, + }, + } +} + +func (r *DNSPoliciesValidator) validate(_ context.Context, _ []controller.ResourceEvent, topology *machinery.Topology, _ error, state *sync.Map) error { + policies := topology.Policies().Items(func(o machinery.Object) bool { + return o.GroupVersionKind().GroupKind() == kuadrantv1alpha1.DNSPolicyGroupKind + }) + + state.Store(StateDNSPolicyValid, lo.SliceToMap(policies, func(policy machinery.Policy) (string, bool) { + return policy.GetLocator(), len(policy.GetTargetRefs()) == 0 || len(topology.Targetables().Parents(policy)) > 0 + })) + + return nil +} diff --git a/controllers/dnspolicy_controller.go b/controllers/dnspolicy_controller.go index 749c6efc6..a7d33cf37 100644 --- a/controllers/dnspolicy_controller.go +++ b/controllers/dnspolicy_controller.go @@ -51,14 +51,6 @@ type DNSPolicyReconciler struct { dnsHelper dnsHelper } -//+kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch -//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies,verbs=get;list;watch;update;patch;delete -//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=kuadrant.io,resources=dnspolicies/finalizers,verbs=update - -//+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 (r *DNSPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Logger().WithValues("DNSPolicy", req.NamespacedName) log.Info("Reconciling DNSPolicy") diff --git a/controllers/dnspolicy_status_updater.go b/controllers/dnspolicy_status_updater.go new file mode 100644 index 000000000..824c9e8e1 --- /dev/null +++ b/controllers/dnspolicy_status_updater.go @@ -0,0 +1,36 @@ +package controllers + +import ( + "context" + "sync" + + "github.com/kuadrant/policy-machinery/controller" + "github.com/kuadrant/policy-machinery/machinery" + "k8s.io/client-go/dynamic" + + kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" +) + +func NewDNSPolicyStatusUpdater(client *dynamic.DynamicClient) *DNSPolicyStatusUpdater { + return &DNSPolicyStatusUpdater{client: client} +} + +type DNSPolicyStatusUpdater struct { + client *dynamic.DynamicClient +} + +func (r *DNSPolicyStatusUpdater) Subscription() controller.Subscription { + return controller.Subscription{ + ReconcileFunc: r.update, + Events: []controller.ResourceEventMatcher{ + {Kind: &machinery.GatewayGroupKind}, + {Kind: &kuadrantv1alpha1.DNSPolicyGroupKind}, + {Kind: &DNSRecordGroupKind}, + }, + } +} + +func (r *DNSPolicyStatusUpdater) update(_ context.Context, _ []controller.ResourceEvent, _ *machinery.Topology, _ error, _ *sync.Map) error { + //ToDo Implement implement me !!! + return nil +} diff --git a/controllers/effective_dnspolicies_reconciler.go b/controllers/effective_dnspolicies_reconciler.go new file mode 100644 index 000000000..cfc7e0300 --- /dev/null +++ b/controllers/effective_dnspolicies_reconciler.go @@ -0,0 +1,35 @@ +package controllers + +import ( + "context" + "sync" + + "github.com/kuadrant/policy-machinery/controller" + "github.com/kuadrant/policy-machinery/machinery" + "k8s.io/client-go/dynamic" + + kuadrantv1alpha1 "github.com/kuadrant/kuadrant-operator/api/v1alpha1" +) + +func NewEffectiveDNSPoliciesReconciler(client *dynamic.DynamicClient) *EffectiveDNSPoliciesReconciler { + return &EffectiveDNSPoliciesReconciler{client: client} +} + +type EffectiveDNSPoliciesReconciler struct { + client *dynamic.DynamicClient +} + +func (r *EffectiveDNSPoliciesReconciler) Subscription() controller.Subscription { + return controller.Subscription{ + ReconcileFunc: r.reconcile, + Events: []controller.ResourceEventMatcher{ + {Kind: &machinery.GatewayGroupKind}, + {Kind: &kuadrantv1alpha1.DNSPolicyGroupKind}, + {Kind: &DNSRecordGroupKind}, + }, + } +} + +func (r *EffectiveDNSPoliciesReconciler) reconcile(ctx context.Context, _ []controller.ResourceEvent, topology *machinery.Topology, _ error, state *sync.Map) error { + return nil +} diff --git a/controllers/state_of_the_world.go b/controllers/state_of_the_world.go index 945216ca9..a30e2bed3 100644 --- a/controllers/state_of_the_world.go +++ b/controllers/state_of_the_world.go @@ -9,6 +9,7 @@ import ( egv1alpha1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/go-logr/logr" authorinov1beta1 "github.com/kuadrant/authorino-operator/api/v1beta1" + kuadrantdnsv1alpha1 "github.com/kuadrant/dns-operator/api/v1alpha1" limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" "github.com/kuadrant/policy-machinery/controller" "github.com/kuadrant/policy-machinery/machinery" @@ -158,6 +159,7 @@ func (b *BootOptionsBuilder) getOptions() []controller.ControllerOption { opts = append(opts, b.getEnvoyGatewayOptions()...) opts = append(opts, b.getCertManagerOptions()...) opts = append(opts, b.getConsolePluginOptions()...) + opts = append(opts, b.getDNSOperatorOptions()...) return opts } @@ -294,13 +296,28 @@ func (b *BootOptionsBuilder) getConsolePluginOptions() []controller.ControllerOp return opts } +func (b *BootOptionsBuilder) getDNSOperatorOptions() []controller.ControllerOption { + var opts []controller.ControllerOption + opts = append(opts, + controller.WithRunnable("dnsrecord watcher", controller.Watch(&kuadrantdnsv1alpha1.DNSRecord{}, DNSRecordResource, metav1.NamespaceAll)), + controller.WithObjectKinds( + DNSRecordGroupKind, + ), + controller.WithObjectLinks( + LinkListenerToDNSRecord, + ), + ) + + return opts +} + func (b *BootOptionsBuilder) Reconciler() controller.ReconcileFunc { mainWorkflow := &controller.Workflow{ Precondition: initWorkflow(b.client).Run, Tasks: []controller.ReconcileFunc{ NewAuthorinoReconciler(b.client).Subscription().Reconcile, NewLimitadorReconciler(b.client).Subscription().Reconcile, - NewDNSWorkflow().Run, + NewDNSWorkflow(b.client).Run, NewTLSWorkflow(b.client, b.isCertManagerInstalled).Run, NewAuthWorkflow().Run, NewRateLimitWorkflow().Run,