controllers/keycloak/keycloak_controller.go (102 lines of code) (raw):

package keycloak import ( "context" "fmt" "time" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" keycloakApi "github.com/epam/edp-keycloak-operator/api/v1" "github.com/epam/edp-keycloak-operator/controllers/helper" "github.com/epam/edp-keycloak-operator/pkg/client/keycloak" ) type Helper interface { CreateKeycloakClientFomAuthData(ctx context.Context, authData *helper.KeycloakAuthData) (keycloak.Client, error) } func NewReconcileKeycloak(client client.Client, scheme *runtime.Scheme, helper Helper) *ReconcileKeycloak { return &ReconcileKeycloak{ client: client, scheme: scheme, helper: helper, } } // ReconcileKeycloak reconciles a Keycloak object. type ReconcileKeycloak struct { client client.Client scheme *runtime.Scheme helper Helper successReconcileTimeout time.Duration } const connectionRetryPeriod = time.Second * 10 //+kubebuilder:rbac:groups=v1.edp.epam.com,namespace=placeholder,resources=keycloaks,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=v1.edp.epam.com,namespace=placeholder,resources=keycloaks/status,verbs=get;update;patch //+kubebuilder:rbac:groups=v1.edp.epam.com,namespace=placeholder,resources=keycloaks/finalizers,verbs=update //+kubebuilder:rbac:groups=v1,namespace=placeholder,resources=configmap,verbs=get;list;watch // Reconcile is a loop for reconciling Keycloak object. func (r *ReconcileKeycloak) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { log := ctrl.LoggerFrom(ctx) log.Info("Reconciling Keycloak") instance := &keycloakApi.Keycloak{} if err := r.client.Get(ctx, req.NamespacedName, instance); err != nil { if errors.IsNotFound(err) { log.Info("Instance not found") return reconcile.Result{}, nil } return ctrl.Result{}, fmt.Errorf("unable to get keycloak instance: %w", err) } if err := r.updateConnectionStatusToKeycloak(ctx, instance); err != nil { return reconcile.Result{}, err } if !instance.Status.Connected { log.Info("Keycloak is not connected, will retry") return reconcile.Result{RequeueAfter: connectionRetryPeriod}, nil } log.Info("Reconciling Keycloak has been finished") return reconcile.Result{}, nil } func (r *ReconcileKeycloak) SetupWithManager(mgr ctrl.Manager, successReconcileTimeout time.Duration) error { r.successReconcileTimeout = successReconcileTimeout pred := predicate.Funcs{ DeleteFunc: func(e event.DeleteEvent) bool { return false }, } err := ctrl.NewControllerManagedBy(mgr). For(&keycloakApi.Keycloak{}, builder.WithPredicates(pred)). Complete(r) if err != nil { return fmt.Errorf("failed to setup Keycloak controller: %w", err) } return nil } func (r *ReconcileKeycloak) updateConnectionStatusToKeycloak(ctx context.Context, instance *keycloakApi.Keycloak) error { log := ctrl.LoggerFrom(ctx) log.Info("Start updating connection status to Keycloak") err := r.createClient(ctx, instance) if err != nil { log.Error(err, "Unable to connect to Keycloak") } connected := err == nil if instance.Status.Connected == connected { log.Info("Connection status hasn't been changed", "status", instance.Status.Connected) return nil } log.Info("Connection status has been changed", "from", instance.Status.Connected, "to", connected) instance.Status.Connected = connected err = r.client.Status().Update(ctx, instance) if err != nil { return fmt.Errorf("failed to update status: %w", err) } log.Info("Status has been updated", "status", instance.Status) return nil } func (r *ReconcileKeycloak) createClient(ctx context.Context, instance *keycloakApi.Keycloak) error { auth, err := helper.MakeKeycloakAuthDataFromKeycloak(ctx, instance, r.client) if err != nil { return fmt.Errorf("failed to make Keycloak auth data: %w", err) } _, err = r.helper.CreateKeycloakClientFomAuthData(ctx, auth) if err != nil { return fmt.Errorf("failed to create Keycloak client: %w", err) } return nil }