Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix creation of custom image clusters and correctly handles upgrades … #2149

Merged
merged 1 commit into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions pkg/reconcile/pipeline/infinispan/handler/manage/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,24 @@ func UpgradeRequired(i *ispnv1.Infinispan, ctx pipeline.Context) bool {
return false
}

// If the Operand is marked as a CVE base-image release, then we perform the upgrade as a StatefulSet rolling upgrade
// as the server components are not changed.
customImage := i.Status.Operand.CustomImage
if !customImage && requestedOperand.CVE && installedOperand.UpstreamVersion.EQ(*requestedOperand.UpstreamVersion) {
// If the Operand is marked as a CVE base-image release and no custom image is installed/requested, then we perform the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing something here?
the comment says 'perform upgrade' but the return value is false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method returns true if a Graceful/HR Rolling upgrade is required. In this case we turn false, as the statefulset_updates.go handler will trigger a StatefulSet rolling upgrade instead.

// upgrade as a StatefulSet rolling upgrade as the server components are not changed.
if requestedOperand.CVE &&
installedOperand.UpstreamVersion.EQ(*requestedOperand.UpstreamVersion) &&
i.Spec.Image == nil &&
!i.Status.Operand.CustomImage {
return false
}

if requestedOperand.EQ(installedOperand) {
if i.Spec.Image == nil {
// If the currently installed Operand was a custom image, but spec.Image is now nil, then we need to
// initiate a new upgrade to ensure that the default image associated with the Operand is installed
return customImage
return i.Status.Operand.CustomImage
}
// If operand versions match, but the FQN of the image differ, then we must schedule an upgrade so the user
// can transition to a custom/patched version of the Operand without having to recreate the Infinispan CR
return *i.Spec.Image != installedOperand.Image
return *i.Spec.Image != i.Status.Operand.Image
}
return true
}
Expand Down
51 changes: 42 additions & 9 deletions test/e2e/infinispan/upgrade_operand_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,28 @@ func TestOperandCVEHotRodRolling(t *testing.T) {
genericTestForContainerUpdated(*spec, modifier, verifier)
}

func TestSpecImage(t *testing.T) {
defer testKube.CleanNamespaceAndLogOnPanic(t, tutils.Namespace)

// Create Infinispan Cluster using the latest Operand version, but using the image of the preceding Operand
// Ensures that creating a cluster with an initial spec.image value does not cause infinite StatefulSet updates
versionManager := tutils.VersionManager()
operand := versionManager.Operands[len(versionManager.Operands)-2]
spec := tutils.DefaultSpec(t, testKube, func(i *ispnv1.Infinispan) {
i.Spec.Image = pointer.String(operand.Image)
})
testKube.CreateInfinispan(spec, tutils.Namespace)
testKube.WaitForInfinispanPods(1, tutils.SinglePodTimeout, spec.Name, tutils.Namespace)
testKube.WaitForInfinispanCondition(spec.Name, spec.Namespace, ispnv1.ConditionWellFormed)
testKube.WaitForInfinispanState(spec.Name, spec.Namespace, func(i *ispnv1.Infinispan) bool {
return i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
i.Status.Operand.CustomImage &&
i.Status.Operand.Version == versionManager.Latest().Ref() &&
i.Status.Operand.Image == operand.Image &&
i.Status.Operand.Phase == ispnv1.OperandPhaseRunning
})
}

func TestSpecImageUpdate(t *testing.T) {
defer testKube.CleanNamespaceAndLogOnPanic(t, tutils.Namespace)

Expand All @@ -237,15 +259,10 @@ func TestSpecImageUpdate(t *testing.T) {
ispn.Spec.Image = pointer.String(customImage)
}),
)
testKube.WaitForInfinispanState(spec.Name, spec.Namespace, func(i *ispnv1.Infinispan) bool {
return !i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
i.Status.Operand.Version == operand.Ref() &&
i.Status.Operand.Image == customImage &&
i.Status.Operand.Phase == ispnv1.OperandPhasePending
})

testKube.WaitForInfinispanState(spec.Name, spec.Namespace, func(i *ispnv1.Infinispan) bool {
return i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
i.Status.Operand.CustomImage &&
i.Status.Operand.Version == operand.Ref() &&
i.Status.Operand.Image == customImage &&
i.Status.Operand.Phase == ispnv1.OperandPhaseRunning
Expand All @@ -272,17 +289,33 @@ func TestSpecImageUpdate(t *testing.T) {
ispn.Spec.Version = latestOperand.Ref()
}),
)

testKube.WaitForInfinispanState(spec.Name, spec.Namespace, func(i *ispnv1.Infinispan) bool {
return !i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
return i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
!i.Status.Operand.CustomImage &&
i.Status.Operand.Version == latestOperand.Ref() &&
i.Status.Operand.Image == latestOperand.Image &&
i.Status.Operand.Phase == ispnv1.OperandPhasePending
i.Status.Operand.Phase == ispnv1.OperandPhaseRunning
})

// Ensure that the StatefulSet is on its first generation, i.e. a RollingUpgrade has not been performed
ss = appsv1.StatefulSet{}
tutils.ExpectNoError(testKube.Kubernetes.Client.Get(context.TODO(), types.NamespacedName{Namespace: ispn.Namespace, Name: ispn.GetStatefulSetName()}, &ss))
assert.EqualValues(t, 1, ss.Status.ObservedGeneration)

tutils.ExpectNoError(
testKube.UpdateInfinispan(ispn, func() {
// Update the spec to move to back to the penultimate Operand version to ensure that an upgrade is still
// triggered when the Operand is marked as CVE=true
ispn.Spec.Image = pointer.String(operand.Image)
}),
)

testKube.WaitForInfinispanState(spec.Name, spec.Namespace, func(i *ispnv1.Infinispan) bool {
return i.IsConditionTrue(ispnv1.ConditionWellFormed) &&
i.Status.Operand.CustomImage &&
i.Status.Operand.Version == latestOperand.Ref() &&
i.Status.Operand.Image == latestOperand.Image &&
i.Status.Operand.Image == operand.Image &&
i.Status.Operand.Phase == ispnv1.OperandPhaseRunning
})

Expand Down
Loading