Skip to content

Commit

Permalink
refactor: bootOptionsBuilder
Browse files Browse the repository at this point in the history
Signed-off-by: KevFan <[email protected]>
  • Loading branch information
KevFan committed Oct 8, 2024
1 parent e974c4b commit c83ca3d
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 56 deletions.
168 changes: 114 additions & 54 deletions controllers/state_of_the_world.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,10 @@ var (
operatorNamespace = env.GetString("OPERATOR_NAMESPACE", "kuadrant-system")
)

type PolicyMachineryController struct {
isGatewayAPIInstalled bool
isEnvoyGatewayInstalled bool
isIstioInstalled bool
isCertManagerInstalled bool
isConsolePluginInstalled bool
}

//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses,verbs=list;watch

func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, client *dynamic.DynamicClient, logger logr.Logger) *controller.Controller {
func NewPolicyMachineryController(manager ctrlruntime.Manager, client *dynamic.DynamicClient, logger logr.Logger) *controller.Controller {
// Base options
controllerOpts := []controller.ControllerOption{
controller.ManagedBy(manager),
controller.WithLogger(logger),
Expand Down Expand Up @@ -94,6 +87,7 @@ func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, clie
controller.WithPredicates(&ctrlruntimepredicate.TypedGenerationChangedPredicate[*corev1.ConfigMap]{}),
controller.FilterResourcesByLabel[*corev1.ConfigMap](fmt.Sprintf("%s=true", kuadrant.TopologyLabel)),
)),
// TODO: Move as boot options for Limitador and Authorino as there can be a possibility that the operators are not installed
controller.WithRunnable("limitador watcher", controller.Watch(
&limitadorv1alpha1.Limitador{},
kuadrantv1beta1.LimitadorsResource,
Expand Down Expand Up @@ -123,12 +117,56 @@ func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, clie
),
}

// Boot options and reconciler based on detected dependencies
bootOptions := NewBootOptionsBuilder(manager, client, logger)
controllerOpts = append(controllerOpts, bootOptions.getOptions()...)
controllerOpts = append(controllerOpts, controller.WithReconcile(bootOptions.Reconciler()))

return controller.NewController(controllerOpts...)
}

// NewBootOptionsBuilder is used to return a list of controller.ControllerOption and a controller.ReconcileFunc that depend
// on if external dependent CRDs are installed at boot time
func NewBootOptionsBuilder(manager ctrlruntime.Manager, client *dynamic.DynamicClient, logger logr.Logger) *BootOptionsBuilder {
return &BootOptionsBuilder{
manager: manager,
client: client,
logger: logger,
}
}

type BootOptionsBuilder struct {
logger logr.Logger
manager ctrlruntime.Manager
client *dynamic.DynamicClient

// Internal configurations
isGatewayAPIInstalled bool
isEnvoyGatewayInstalled bool
isIstioInstalled bool
isCertManagerInstalled bool
isConsolePluginInstalled bool
}

func (b *BootOptionsBuilder) getOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
opts = append(opts, b.getGatewayAPIOptions()...)
opts = append(opts, b.getIstioOptions()...)
opts = append(opts, b.getEnvoyGatewayOptions()...)
opts = append(opts, b.getCertManagerOptions()...)
opts = append(opts, b.getConsolePluginOptions()...)

return opts
}

func (b *BootOptionsBuilder) getGatewayAPIOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
var err error
c.isGatewayAPIInstalled, err = kuadrantgatewayapi.IsGatewayAPIInstalled(manager.GetRESTMapper())
if err != nil || !c.isGatewayAPIInstalled {
logger.Info("gateway api is not installed, skipping watches and reconcilers", "err", err)
b.isGatewayAPIInstalled, err = kuadrantgatewayapi.IsGatewayAPIInstalled(b.manager.GetRESTMapper())
if err != nil || !b.isGatewayAPIInstalled {
b.logger.Info("gateway api is not installed, skipping watches and reconcilers", "err", err)
} else {
controllerOpts = append(controllerOpts,
opts = append(opts,
controller.WithRunnable("gatewayclass watcher", controller.Watch(
&gwapiv1.GatewayClass{},
controller.GatewayClassesResource,
Expand All @@ -147,11 +185,17 @@ func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, clie
)
}

c.isEnvoyGatewayInstalled, err = envoygateway.IsEnvoyGatewayInstalled(manager.GetRESTMapper())
if err != nil || !c.isEnvoyGatewayInstalled {
logger.Info("envoygateway is not installed, skipping related watches and reconcilers", "err", err)
return opts
}

func (b *BootOptionsBuilder) getEnvoyGatewayOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
var err error
b.isEnvoyGatewayInstalled, err = envoygateway.IsEnvoyGatewayInstalled(b.manager.GetRESTMapper())
if err != nil || !b.isEnvoyGatewayInstalled {
b.logger.Info("envoygateway is not installed, skipping related watches and reconcilers", "err", err)
} else {
controllerOpts = append(controllerOpts,
opts = append(opts,
controller.WithRunnable("envoypatchpolicy watcher", controller.Watch(
&egv1alpha1.EnvoyPatchPolicy{},
envoygateway.EnvoyPatchPoliciesResource,
Expand All @@ -177,11 +221,17 @@ func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, clie
// TODO: add specific tasks to workflow
}

c.isIstioInstalled, err = istio.IsIstioInstalled(manager.GetRESTMapper())
if err != nil || !c.isIstioInstalled {
logger.Info("istio is not installed, skipping related watches and reconcilers", "err", err)
return opts
}

func (b *BootOptionsBuilder) getIstioOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
var err error
b.isIstioInstalled, err = istio.IsIstioInstalled(b.manager.GetRESTMapper())
if err != nil || !b.isIstioInstalled {
b.logger.Info("istio is not installed, skipping related watches and reconcilers", "err", err)
} else {
controllerOpts = append(controllerOpts,
opts = append(opts,
controller.WithRunnable("envoyfilter watcher", controller.Watch(
&istioclientnetworkingv1alpha3.EnvoyFilter{},
istio.EnvoyFiltersResource,
Expand All @@ -207,28 +257,61 @@ func (c *PolicyMachineryController) Controller(manager ctrlruntime.Manager, clie
// TODO: add istio specific tasks to workflow
}

c.isCertManagerInstalled, err = kuadrantgatewayapi.IsCertManagerInstalled(manager.GetRESTMapper(), logger)
if err != nil || !c.isCertManagerInstalled {
logger.Info("cert manager is not installed, skipping related watches and reconcilers", "err", err)
return opts
}

func (b *BootOptionsBuilder) getCertManagerOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
var err error
b.isCertManagerInstalled, err = kuadrantgatewayapi.IsCertManagerInstalled(b.manager.GetRESTMapper(), b.logger)
if err != nil || !b.isCertManagerInstalled {
b.logger.Info("cert manager is not installed, skipping related watches and reconcilers", "err", err)
} else {
controllerOpts = append(controllerOpts, certManagerControllerOpts()...)
opts = append(opts, certManagerControllerOpts()...)
}

c.isConsolePluginInstalled, err = openshift.IsConsolePluginInstalled(manager.GetRESTMapper())
if err != nil || !c.isConsolePluginInstalled {
logger.Info("console plugin is not installed, skipping related watches and reconcilers", "err", err)
return opts
}

func (b *BootOptionsBuilder) getConsolePluginOptions() []controller.ControllerOption {
var opts []controller.ControllerOption
var err error
b.isConsolePluginInstalled, err = openshift.IsConsolePluginInstalled(b.manager.GetRESTMapper())
if err != nil || !b.isConsolePluginInstalled {
b.logger.Info("console plugin is not installed, skipping related watches and reconcilers", "err", err)
} else {
controllerOpts = append(controllerOpts,
opts = append(opts,
controller.WithRunnable("consoleplugin watcher", controller.Watch(
&consolev1.ConsolePlugin{}, openshift.ConsolePluginsResource, metav1.NamespaceAll,
controller.FilterResourcesByLabel[*consolev1.ConsolePlugin](fmt.Sprintf("%s=%s", consoleplugin.AppLabelKey, consoleplugin.AppLabelValue)))),
controller.WithObjectKinds(openshift.ConsolePluginGVK.GroupKind()),
)
}

controllerOpts = append(controllerOpts, controller.WithReconcile(c.buildReconciler(manager, client)))
return opts
}

return controller.NewController(controllerOpts...)
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,
NewTLSWorkflow(b.client, b.isCertManagerInstalled).Run,
NewAuthWorkflow().Run,
NewRateLimitWorkflow().Run,
},
Postcondition: finalStepsWorkflow(b.client, b.isIstioInstalled, b.isGatewayAPIInstalled).Run,
}

if b.isConsolePluginInstalled {
mainWorkflow.Tasks = append(mainWorkflow.Tasks,
NewConsolePluginReconciler(b.manager, operatorNamespace).Subscription().Reconcile,
)
}

return mainWorkflow.Run
}

func certManagerControllerOpts() []controller.ControllerOption {
Expand Down Expand Up @@ -293,29 +376,6 @@ func certManagerControllerOpts() []controller.ControllerOption {
}
}

func (c *PolicyMachineryController) buildReconciler(manager ctrlruntime.Manager, client *dynamic.DynamicClient) controller.ReconcileFunc {
mainWorkflow := &controller.Workflow{
Precondition: initWorkflow(client).Run,
Tasks: []controller.ReconcileFunc{
NewAuthorinoReconciler(client).Subscription().Reconcile,
NewLimitadorReconciler(client).Subscription().Reconcile,
NewDNSWorkflow().Run,
NewTLSWorkflow(client, c.isCertManagerInstalled).Run,
NewAuthWorkflow().Run,
NewRateLimitWorkflow().Run,
},
Postcondition: finalStepsWorkflow(client, c.isIstioInstalled, c.isGatewayAPIInstalled).Run,
}

if c.isConsolePluginInstalled {
mainWorkflow.Tasks = append(mainWorkflow.Tasks,
NewConsolePluginReconciler(manager, operatorNamespace).Subscription().Reconcile,
)
}

return mainWorkflow.Run
}

func initWorkflow(client *dynamic.DynamicClient) *controller.Workflow {
return &controller.Workflow{
Precondition: NewEventLogger().Log,
Expand Down
2 changes: 1 addition & 1 deletion controllers/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func SetupKuadrantOperatorForTest(s *runtime.Scheme, cfg *rest.Config) {
dClient, err := dynamic.NewForConfig(mgr.GetConfig())
Expect(err).NotTo(HaveOccurred())

stateOfTheWorld := (&PolicyMachineryController{}).Controller(mgr, dClient, log.Log)
stateOfTheWorld := NewPolicyMachineryController(mgr, dClient, log.Log)

go func() {
defer GinkgoRecover()
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ func main() {
os.Exit(1)
}

stateOfTheWorld := (&controllers.PolicyMachineryController{}).Controller(mgr, client, log.Log)
stateOfTheWorld := controllers.NewPolicyMachineryController(mgr, client, log.Log)
if err = stateOfTheWorld.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "unable to start stateOfTheWorld controller")
os.Exit(1)
Expand Down

0 comments on commit c83ca3d

Please sign in to comment.