Skip to content

Commit 5f5481e

Browse files
authored
fix: do not infinitely reconcile in case of exit code > 0 (#284)
1 parent 3af65a0 commit 5f5481e

4 files changed

Lines changed: 8 additions & 151 deletions

File tree

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ spec:
4646
authSecret:
4747
name: keycloak-admin
4848
interval: 1h
49-
timeout: 5m0s
5049
realm:
5150
accessCodeLifespan: 60
5251
accessCodeLifespanLogin: 1800
@@ -170,7 +169,6 @@ spec:
170169
passwordField: password
171170
userField: username
172171
interval: 1h
173-
timeout: 5m0s
174172
suspend: false
175173
realm:
176174
accessCodeLifespan: 60
@@ -211,7 +209,6 @@ spec:
211209
authSecret:
212210
name: keycloak-admin
213211
interval: 1h
214-
timeout: 5m0s
215212
realm:
216213
accessCodeLifespan: 60
217214
accessCodeLifespanLogin: 1800
@@ -268,7 +265,6 @@ spec:
268265
authSecret:
269266
name: keycloak-admin
270267
interval: 1h
271-
timeout: 5m0s
272268
realm:
273269
accessCodeLifespan: 60
274270
accessCodeLifespanLogin: 1800

api/v1beta1/keycloakrealm_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type KeycloakRealmSpec struct {
6464

6565
// Timeout
6666
// +optional
67+
// +deprecated
6768
Timeout *metav1.Duration `json:"timeout,omitempty"`
6869

6970
// Suspend reconciliation

internal/controllers/keycloakrealm_controller.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,13 @@ func (r *KeycloakRealmReconciler) reconcile(ctx context.Context, realm infrav1be
324324
// cleanup reconciler pod if stale
325325
if needUpdate {
326326
logger.V(1).Info("realm checksum changed, delete stale reconciler", "pod-name", realm.Status.Reconciler)
327-
return realm, ctrl.Result{}, cleanup()
327+
return realm, ctrl.Result{Requeue: true}, cleanup()
328328
}
329329

330330
// garbage collect reconciler pod
331-
if progressingCondition != nil && readyCondition != nil && readyCondition.Status != metav1.ConditionUnknown && podErr == nil && realm.Status.Reconciler != "" {
331+
if progressingCondition != nil && readyCondition != nil && readyCondition.Status == metav1.ConditionTrue && podErr == nil && realm.Status.Reconciler != "" {
332332
logger.V(1).Info("garbage collect reconciler pod", "pod-name", realm.Status.Reconciler)
333-
return realm, ctrl.Result{}, cleanup()
333+
return realm, ctrl.Result{Requeue: true}, cleanup()
334334
}
335335

336336
// rate limiter
@@ -374,12 +374,9 @@ func (r *KeycloakRealmReconciler) handlerReconcilerState(realm infrav1beta1.Keyc
374374
return realm, ctrl.Result{Requeue: true}, nil
375375

376376
case containerStatus.State.Terminated != nil:
377-
realm = infrav1beta1.KeycloakRealmReady(realm, metav1.ConditionFalse, "ReconciliationFailed", fmt.Sprintf("reconciler terminated with code %d", containerStatus.State.Terminated.ExitCode))
378-
return realm, ctrl.Result{Requeue: true}, nil
379-
380-
case containerStatus.State.Running != nil && realm.Spec.Timeout != nil && time.Since(containerStatus.State.Running.StartedAt.Time) >= realm.Spec.Timeout.Duration:
381-
conditions.Delete(&realm, infrav1beta1.ConditionReconciling)
382-
return realm, reconcile.Result{}, errors.New("reconciler timeout reached")
377+
err := fmt.Errorf("reconciler terminated with code %d", containerStatus.State.Terminated.ExitCode)
378+
realm = infrav1beta1.KeycloakRealmReady(realm, metav1.ConditionFalse, "ReconciliationFailed", err.Error())
379+
return realm, ctrl.Result{}, nil
383380
}
384381

385382
return realm, ctrl.Result{}, nil
@@ -522,7 +519,7 @@ func (r *KeycloakRealmReconciler) createReconciler(ctx context.Context, realm in
522519
return realm, ctrl.Result{}, err
523520
}
524521

525-
template.Spec.RestartPolicy = corev1.RestartPolicyNever
522+
template.Spec.RestartPolicy = corev1.RestartPolicyOnFailure
526523
template.Spec.Containers = containers
527524
template.Spec.Volumes = append(template.Spec.Volumes, corev1.Volume{
528525
Name: "realm",
@@ -799,8 +796,6 @@ func (r *KeycloakRealmReconciler) patchStatus(ctx context.Context, realm *infrav
799796
return err
800797
}
801798

802-
// logger.V(1).Info("update .status", "new", realm.Status, "current", latest.Status)
803-
804799
return r.Client.Status().Patch(ctx, realm, client.MergeFrom(latest))
805800
}
806801

internal/controllers/keycloakrealm_controller_test.go

Lines changed: 0 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,139 +1703,4 @@ var _ = Describe("KeycloakRealm controller", func() {
17031703
Expect(string(secret.Data["realm.json"])).Should(Equal(fmt.Sprintf(`{"realm":"%s","users":[{"username":"%s","enabled":true}],"components":null,"requiredActions":null}`, realm.Name, userName)))
17041704
})
17051705
})
1706-
/*
1707-
TODO: this test is flaky as the controller already progresses into another reconcile if the timeout occurs.
1708-
1709-
When("a realm reconciler runs into spec.timeout", func() {
1710-
realmName := fmt.Sprintf("realm-%s", rand.String(5))
1711-
1712-
It("recreates the reconciler with a new secret", func() {
1713-
By("creating a new KeycloakRealm")
1714-
ctx := context.Background()
1715-
1716-
authSecret := &corev1.Secret{
1717-
ObjectMeta: metav1.ObjectMeta{
1718-
Name: fmt.Sprintf("auth-%s", rand.String(5)),
1719-
Namespace: "default",
1720-
},
1721-
StringData: map[string]string{
1722-
"username": "kc-user",
1723-
"password": "kc-password",
1724-
},
1725-
}
1726-
1727-
Expect(k8sClient.Create(ctx, authSecret)).Should(Succeed())
1728-
1729-
realm := &v1beta1.KeycloakRealm{
1730-
ObjectMeta: metav1.ObjectMeta{
1731-
Name: realmName,
1732-
Namespace: "default",
1733-
},
1734-
Spec: v1beta1.KeycloakRealmSpec{
1735-
Interval: &metav1.Duration{Duration: time.Second * 100},
1736-
Timeout: &metav1.Duration{Duration: time.Second * 100},
1737-
Version: "22.0.1",
1738-
AuthSecret: v1beta1.SecretReference{
1739-
Name: authSecret.Name,
1740-
},
1741-
},
1742-
}
1743-
Expect(k8sClient.Create(ctx, realm)).Should(Succeed())
1744-
1745-
By("waiting for the reconciliation")
1746-
instanceLookupKey := types.NamespacedName{Name: realmName, Namespace: "default"}
1747-
reconciledInstance := &v1beta1.KeycloakRealm{}
1748-
1749-
expectedStatus := &v1beta1.KeycloakRealmStatus{
1750-
ObservedGeneration: 1,
1751-
Conditions: []metav1.Condition{
1752-
{
1753-
Type: v1beta1.ConditionReady,
1754-
Status: metav1.ConditionUnknown,
1755-
Reason: "Progressing",
1756-
Message: "Reconciliation in progress",
1757-
},
1758-
{
1759-
Type: v1beta1.ConditionReconciling,
1760-
Status: metav1.ConditionTrue,
1761-
Reason: "Progressing",
1762-
},
1763-
},
1764-
}
1765-
1766-
Eventually(func() bool {
1767-
err := k8sClient.Get(ctx, instanceLookupKey, reconciledInstance)
1768-
if err != nil {
1769-
return false
1770-
}
1771-
1772-
return needStatus(reconciledInstance, expectedStatus)
1773-
}, timeout, interval).Should(BeTrue())
1774-
1775-
})
1776-
1777-
It("transitions into unready once the reconciler pod reached the timeout", func() {
1778-
reconciledInstance := &v1beta1.KeycloakRealm{}
1779-
instanceLookupKey := types.NamespacedName{Name: realmName, Namespace: "default"}
1780-
Expect(k8sClient.Get(ctx, instanceLookupKey, reconciledInstance)).Should(Succeed())
1781-
1782-
By("container shall be running for 500s")
1783-
pod := &corev1.Pod{}
1784-
Expect(k8sClient.Get(ctx, types.NamespacedName{
1785-
Name: reconciledInstance.Status.Reconciler,
1786-
Namespace: reconciledInstance.Namespace,
1787-
}, pod)).Should(Succeed())
1788-
1789-
pod.Status.ContainerStatuses = []corev1.ContainerStatus{
1790-
{
1791-
Name: "keycloak-config-cli",
1792-
State: corev1.ContainerState{
1793-
Running: &corev1.ContainerStateRunning{
1794-
StartedAt: metav1.NewTime(time.Now().Add(time.Second * -500)),
1795-
},
1796-
},
1797-
},
1798-
}
1799-
1800-
Expect(k8sClient.Status().Update(ctx, pod)).Should(Succeed())
1801-
1802-
By("waiting for the reconciliation")
1803-
expectedStatus := &v1beta1.KeycloakRealmStatus{
1804-
ObservedGeneration: 1,
1805-
Conditions: []metav1.Condition{
1806-
{
1807-
Type: v1beta1.ConditionReady,
1808-
Status: metav1.ConditionFalse,
1809-
Reason: "ReconciliationFailed",
1810-
Message: "reconciler timeout reached",
1811-
},
1812-
},
1813-
}
1814-
1815-
Eventually(func() bool {
1816-
err := k8sClient.Get(ctx, instanceLookupKey, reconciledInstance)
1817-
if err != nil {
1818-
return false
1819-
}
1820-
1821-
return needStatus(reconciledInstance, expectedStatus)
1822-
}, timeout, interval).Should(BeTrue())
1823-
1824-
By("making sure the reconciler pod is gone")
1825-
Expect(k8sClient.Get(ctx, types.NamespacedName{
1826-
Name: reconciledInstance.Status.Reconciler,
1827-
Namespace: reconciledInstance.Namespace,
1828-
}, pod)).Should(Not(BeNil()))
1829-
1830-
Expect(reconciledInstance.Status.Reconciler).Should(Equal(""))
1831-
1832-
By("making sure the realm secret is gone")
1833-
var secret *corev1.Secret
1834-
Expect(k8sClient.Get(ctx, types.NamespacedName{
1835-
Name: reconciledInstance.Status.Reconciler,
1836-
Namespace: reconciledInstance.Namespace,
1837-
}, secret)).Should(Not(BeNil()))
1838-
})
1839-
})
1840-
*/
18411706
})

0 commit comments

Comments
 (0)