refactor: consolidate Instance phase handlers
E2E Tests / Run on Ubuntu (pull_request) Failing after 1m28s
Tests / Run on Ubuntu (pull_request) Successful in 4m35s
Lint / Run on Ubuntu (pull_request) Successful in 4m58s

This commit is contained in:
2026-09-11 15:04:15 +00:00
parent 212ca4be99
commit 89d9e2316b
3 changed files with 164 additions and 103 deletions
+71 -12
View File
@@ -34,6 +34,8 @@ type fakeInstanceInitializer struct {
err error
}
const testPostgreSQLVersion = "17.6"
func (f fakeInstanceInitializer) Validate(context.Context, *databasev1alpha1.PostgreSQLInstance) (string, error) {
return f.validateVersion, f.err
}
@@ -43,19 +45,74 @@ func (f fakeInstanceInitializer) InitializeRegistry(context.Context, *databasev1
}
var _ = Describe("phase handler state machines", func() {
It("persists validation intent before touching unavailable dependencies", func() {
instance := &databasev1alpha1.PostgreSQLInstance{}
machine := newInstanceStateMachine(fakeInstanceInitializer{err: errors.New("must not be called")})
result, err := machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(result.RequeueAfter).To(BeNumerically(">", 0))
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseValidating))
Expect(instance.Status.Conditions[0].Status).To(Equal(metav1.ConditionUnknown))
})
It("persists a new validation checkpoint when a Ready Instance generation changes", func() {
instance := &databasev1alpha1.PostgreSQLInstance{
ObjectMeta: metav1.ObjectMeta{Generation: 4},
Status: databasev1alpha1.PostgreSQLInstanceStatus{
Phase: databasev1alpha1.PostgreSQLInstancePhaseReady, ObservedGeneration: 3,
},
}
machine := newInstanceStateMachine(fakeInstanceInitializer{err: errors.New("must not be called")})
_, err := machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseValidating))
Expect(instance.Status.ObservedGeneration).To(Equal(int64(3)))
})
It("detects a dependency outage after Ready and recovers through registry initialization", func() {
instance := &databasev1alpha1.PostgreSQLInstance{
ObjectMeta: metav1.ObjectMeta{Generation: 3},
Status: databasev1alpha1.PostgreSQLInstanceStatus{
Phase: databasev1alpha1.PostgreSQLInstancePhaseReady, ObservedGeneration: 3,
},
}
machine := newInstanceStateMachine(fakeInstanceInitializer{err: errors.New("unavailable")})
_, err := machine.reconcile(context.Background(), instance)
Expect(err).To(MatchError("unavailable"))
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseValidating))
Expect(instance.Status.Conditions[0].Status).To(Equal(metav1.ConditionFalse))
machine.initializer = fakeInstanceInitializer{
validateVersion: testPostgreSQLVersion,
registryVersion: testPostgreSQLVersion,
}
_, err = machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseInitializingRegistry))
_, err = machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Conditions[0].Status).To(Equal(metav1.ConditionTrue))
result, err := machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseReady))
Expect(result.RequeueAfter).To(Equal(time.Minute))
})
It("advances an Instance through external validation and registry initialization", func() {
instance := &databasev1alpha1.PostgreSQLInstance{
ObjectMeta: metav1.ObjectMeta{Generation: 3},
Status: databasev1alpha1.PostgreSQLInstanceStatus{Phase: databasev1alpha1.PostgreSQLInstancePhaseValidating},
}
reconciler := &PostgreSQLInstanceReconciler{Initializer: fakeInstanceInitializer{
validateVersion: "17.6", registryVersion: "17.6",
}}
Expect(reconciler.reconcileDependencies(context.Background(), instance)).To(Succeed())
machine := newInstanceStateMachine(fakeInstanceInitializer{
validateVersion: testPostgreSQLVersion,
registryVersion: testPostgreSQLVersion,
})
_, err := machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseInitializingRegistry))
Expect(reconciler.reconcileDependencies(context.Background(), instance)).To(Succeed())
_, err = machine.reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseReady))
Expect(instance.Status.PostgreSQLVersion).To(Equal("17.6"))
Expect(instance.Status.PostgreSQLVersion).To(Equal(testPostgreSQLVersion))
Expect(instance.Status.ObservedGeneration).To(Equal(int64(3)))
Expect(instance.Status.Conditions).To(ConsistOf(And(
HaveField("Status", metav1.ConditionTrue), HaveField("Reason", databasev1alpha1.ReasonReady),
@@ -67,8 +124,9 @@ var _ = Describe("phase handler state machines", func() {
ObjectMeta: metav1.ObjectMeta{Generation: 2},
Status: databasev1alpha1.PostgreSQLInstanceStatus{Phase: databasev1alpha1.PostgreSQLInstancePhaseValidating},
}
reconciler := &PostgreSQLInstanceReconciler{Initializer: fakeInstanceInitializer{err: errors.New("unavailable")}}
Expect(reconciler.reconcileDependencies(context.Background(), instance)).To(MatchError("unavailable"))
machine := newInstanceStateMachine(fakeInstanceInitializer{err: errors.New("unavailable")})
_, err := machine.reconcile(context.Background(), instance)
Expect(err).To(MatchError("unavailable"))
Expect(instance.Status.Phase).To(Equal(databasev1alpha1.PostgreSQLInstancePhaseValidating))
Expect(instance.Status.Conditions).To(ConsistOf(And(
HaveField("Status", metav1.ConditionFalse), HaveField("Reason", databasev1alpha1.ReasonDependencyUnavailable),
@@ -77,12 +135,13 @@ var _ = Describe("phase handler state machines", func() {
DescribeTable("dispatches Instance phases",
func(instance *databasev1alpha1.PostgreSQLInstance, expected databasev1alpha1.PostgreSQLInstancePhase, hasMessage bool) {
result := newInstanceStateMachine().reconcile(instance)
Expect(result.phase).To(Equal(expected))
_, err := newInstanceStateMachine(nil).reconcile(context.Background(), instance)
Expect(err).NotTo(HaveOccurred())
Expect(instance.Status.Phase).To(Equal(expected))
if hasMessage {
Expect(result.reconcilingMessage).NotTo(BeEmpty())
Expect(instance.Status.Conditions).NotTo(BeEmpty())
} else {
Expect(result.reconcilingMessage).To(BeEmpty())
Expect(instance.Status.Conditions).To(BeEmpty())
}
},
Entry("starts validation from an empty checkpoint",