|
|
@@ -72,26 +72,30 @@ type Reconciler struct {
|
|
|
RequeueInterval time.Duration
|
|
|
|
|
|
// the controller is ready when all crds are injected
|
|
|
- rdyMu *sync.Mutex
|
|
|
- readyStatusMap map[string]bool
|
|
|
+ // and the controller is elected as leader
|
|
|
+ leaderChan <-chan struct{}
|
|
|
+ leaderElected bool
|
|
|
+ readyStatusMapMu *sync.Mutex
|
|
|
+ readyStatusMap map[string]bool
|
|
|
}
|
|
|
|
|
|
-func New(k8sClient client.Client, scheme *runtime.Scheme, logger logr.Logger,
|
|
|
+func New(k8sClient client.Client, scheme *runtime.Scheme, leaderChan <-chan struct{}, logger logr.Logger,
|
|
|
interval time.Duration, svcName, svcNamespace, secretName, secretNamespace string, resources []string) *Reconciler {
|
|
|
return &Reconciler{
|
|
|
- Client: k8sClient,
|
|
|
- Log: logger,
|
|
|
- Scheme: scheme,
|
|
|
- SvcName: svcName,
|
|
|
- SvcNamespace: svcNamespace,
|
|
|
- SecretName: secretName,
|
|
|
- SecretNamespace: secretNamespace,
|
|
|
- RequeueInterval: interval,
|
|
|
- CrdResources: resources,
|
|
|
- CAName: "external-secrets",
|
|
|
- CAOrganization: "external-secrets",
|
|
|
- rdyMu: &sync.Mutex{},
|
|
|
- readyStatusMap: map[string]bool{},
|
|
|
+ Client: k8sClient,
|
|
|
+ Log: logger,
|
|
|
+ Scheme: scheme,
|
|
|
+ SvcName: svcName,
|
|
|
+ SvcNamespace: svcNamespace,
|
|
|
+ SecretName: secretName,
|
|
|
+ SecretNamespace: secretNamespace,
|
|
|
+ RequeueInterval: interval,
|
|
|
+ CrdResources: resources,
|
|
|
+ CAName: "external-secrets",
|
|
|
+ CAOrganization: "external-secrets",
|
|
|
+ leaderChan: leaderChan,
|
|
|
+ readyStatusMapMu: &sync.Mutex{},
|
|
|
+ readyStatusMap: map[string]bool{},
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -117,14 +121,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
|
|
err := r.updateCRD(ctx, req)
|
|
|
if err != nil {
|
|
|
log.Error(err, "failed to inject conversion webhook")
|
|
|
- r.rdyMu.Lock()
|
|
|
+ r.readyStatusMapMu.Lock()
|
|
|
r.readyStatusMap[req.NamespacedName.Name] = false
|
|
|
- r.rdyMu.Unlock()
|
|
|
+ r.readyStatusMapMu.Unlock()
|
|
|
return ctrl.Result{}, err
|
|
|
}
|
|
|
- r.rdyMu.Lock()
|
|
|
+ r.readyStatusMapMu.Lock()
|
|
|
r.readyStatusMap[req.NamespacedName.Name] = true
|
|
|
- r.rdyMu.Unlock()
|
|
|
+ r.readyStatusMapMu.Unlock()
|
|
|
}
|
|
|
return ctrl.Result{RequeueAfter: r.RequeueInterval}, nil
|
|
|
}
|
|
|
@@ -132,14 +136,35 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
|
|
// ReadyCheck reviews if all webhook configs have been injected into the CRDs
|
|
|
// and if the referenced webhook service is ready.
|
|
|
func (r *Reconciler) ReadyCheck(_ *http.Request) error {
|
|
|
+ // skip readiness check if we're not leader
|
|
|
+ // as we depend on caches and being able to reconcile Webhooks
|
|
|
+ if !r.leaderElected {
|
|
|
+ select {
|
|
|
+ case <-r.leaderChan:
|
|
|
+ r.leaderElected = true
|
|
|
+ default:
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if err := r.checkCRDs(); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return r.checkEndpoints()
|
|
|
+}
|
|
|
+
|
|
|
+func (r Reconciler) checkCRDs() error {
|
|
|
for _, res := range r.CrdResources {
|
|
|
- r.rdyMu.Lock()
|
|
|
+ r.readyStatusMapMu.Lock()
|
|
|
rdy := r.readyStatusMap[res]
|
|
|
- r.rdyMu.Unlock()
|
|
|
+ r.readyStatusMapMu.Unlock()
|
|
|
if !rdy {
|
|
|
return fmt.Errorf(errResNotReady, res)
|
|
|
}
|
|
|
}
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (r Reconciler) checkEndpoints() error {
|
|
|
var eps corev1.Endpoints
|
|
|
err := r.Get(context.TODO(), types.NamespacedName{
|
|
|
Name: r.SvcName,
|