Skip to content

Commit 69b7af0

Browse files
Merge pull request #5786 from HarshwardhanPatil07/MCO-2168-Deleting-shared-PIS-testcase
MCO-2168: Deleting a PinnedImageSet does not affect images pinned by another PinnedImageSet
2 parents 7571581 + 162428e commit 69b7af0

1 file changed

Lines changed: 114 additions & 8 deletions

File tree

test/extended-priv/mco_pinnedimages.go

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,7 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati
285285
defer nodeList.PrintDebugCommand() // for debugging purpose in case of failed deployment
286286

287287
exutil.By("Remove the image from all nodes in the pool")
288-
for _, node := range allNodes {
289-
// We ignore errors, since the image can be present or not in the nodes
290-
_ = NewRemoteImage(node, pinnedImage).Rmi()
291-
}
288+
removeImageFromNodes(allNodes, pinnedImage)
292289
logger.Infof("OK!\n")
293290

294291
exutil.By("Create pinnedimageset")
@@ -516,6 +513,91 @@ var _ = g.Describe("[sig-mco][Suite:openshift/machine-config-operator/longdurati
516513
basicPinnedImageTest(infraMcp, pinnedImageSetName)
517514

518515
})
516+
517+
g.It("[PolarionID:88378][OTP] Deleting a PinnedImageSet does not affect images pinned by another PinnedImageSet", func() {
518+
var (
519+
waitForPinned = 10 * time.Minute
520+
pinnedImage = AlpineImage
521+
allNodes = mcp.GetNodesOrFail()
522+
pisOneName = fmt.Sprintf("tc-%s-pis-one", GetCurrentTestPolarionIDNumber())
523+
pisTwoName = fmt.Sprintf("tc-%s-pis-two", GetCurrentTestPolarionIDNumber())
524+
pisDupName = fmt.Sprintf("tc-%s-pis-duplicate", GetCurrentTestPolarionIDNumber())
525+
)
526+
527+
exutil.By("Remove the test image from all nodes in the pool")
528+
removeImageFromNodes(allNodes, pinnedImage)
529+
logger.Infof("OK!\n")
530+
531+
exutil.By("Create first PinnedImageSet with alpine image and verify it is pinned")
532+
pisOne := createPinnedImageSetAndWait(oc.AsAdmin(), pisOneName, mcp, []string{pinnedImage}, allNodes, waitForPinned)
533+
defer pisOne.DeleteAndWait(waitForPinned)
534+
logger.Infof("OK!\n")
535+
536+
exutil.By("Create second PinnedImageSet with the same alpine image and verify it is pinned")
537+
pisTwo := createPinnedImageSetAndWait(oc.AsAdmin(), pisTwoName, mcp, []string{pinnedImage}, allNodes, waitForPinned)
538+
defer pisTwo.DeleteAndWait(waitForPinned)
539+
logger.Infof("OK!\n")
540+
541+
exutil.By("Verify all MachineConfigNodes report healthy pinned image conditions")
542+
for _, node := range allNodes {
543+
mcn := node.GetMachineConfigNode()
544+
o.Eventually(mcn, "2m", "20s").Should(HaveConditionField("PinnedImageSetsDegraded", "status", FalseString),
545+
"MachineConfigNode %s should not be PinnedImageSetsDegraded.\n%s", node.GetName(), mcn.PrettyString())
546+
o.Eventually(mcn, "2m", "20s").Should(HaveConditionField("PinnedImageSetsProgressing", "status", FalseString),
547+
"MachineConfigNode %s should not be PinnedImageSetsProgressing.\n%s", node.GetName(), mcn.PrettyString())
548+
}
549+
logger.Infof("OK!\n")
550+
551+
exutil.By("Delete the first PinnedImageSet")
552+
o.Expect(pisOne.Delete()).To(o.Succeed(), "Error deleting %s", pisOne)
553+
logger.Infof("OK!\n")
554+
555+
exutil.By("Wait for the pool to reconcile after deleting the first PinnedImageSet")
556+
o.Expect(mcp.waitForPinComplete(waitForPinned)).To(o.Succeed(),
557+
"Pinned image operation is not completed in %s after deleting %s", mcp, pisOne)
558+
logger.Infof("OK!\n")
559+
560+
exutil.By("Verify the first PinnedImageSet is deleted and the second still exists")
561+
o.Expect(pisOne.Exists()).To(o.BeFalse(),
562+
"%s should not exist after deletion", pisOne)
563+
o.Expect(pisTwo.Exists()).To(o.BeTrue(),
564+
"%s should still exist", pisTwo)
565+
logger.Infof("OK!\n")
566+
567+
exutil.By("Verify the image is STILL pinned on all nodes after deleting the first PinnedImageSet")
568+
for _, node := range allNodes {
569+
ri := NewRemoteImage(node, pinnedImage)
570+
o.Expect(ri.IsPinned()).To(o.BeTrue(),
571+
"%s should still be pinned because %s still references it", ri, pisTwo)
572+
}
573+
logger.Infof("OK!\n")
574+
575+
exutil.By("Verify MachineConfigNodes remain healthy after the deletion")
576+
for _, node := range allNodes {
577+
mcn := node.GetMachineConfigNode()
578+
o.Eventually(mcn, "2m", "20s").Should(HaveConditionField("PinnedImageSetsDegraded", "status", FalseString),
579+
"MachineConfigNode %s should not be PinnedImageSetsDegraded after deleting %s.\n%s", node.GetName(), pisOne, mcn.PrettyString())
580+
o.Eventually(mcn, "2m", "20s").Should(HaveConditionField("PinnedImageSetsProgressing", "status", FalseString),
581+
"MachineConfigNode %s should not be PinnedImageSetsProgressing after deleting %s.\n%s", node.GetName(), pisOne, mcn.PrettyString())
582+
}
583+
logger.Infof("OK!\n")
584+
585+
exutil.By("Verify that a PinnedImageSet with duplicate images is rejected by the API")
586+
_, err := CreateGenericPinnedImageSet(oc.AsAdmin(), pisDupName, mcp.GetName(), []string{pinnedImage, pinnedImage})
587+
o.Expect(err).To(o.HaveOccurred(),
588+
"Creating a PinnedImageSet with duplicate images should fail, but it succeeded")
589+
o.Expect(err).To(o.BeAssignableToTypeOf(&exutil.ExitError{}),
590+
"Expected an ExitError from the API server rejection")
591+
o.Expect(err.(*exutil.ExitError).StdErr).To(o.ContainSubstring("Duplicate value"),
592+
"API error should indicate duplicate image entries")
593+
logger.Infof("OK!\n")
594+
595+
exutil.By("Verify the duplicate PinnedImageSet was not created")
596+
pisDup := NewPinnedImageSet(oc.AsAdmin(), pisDupName)
597+
o.Expect(pisDup.Exists()).To(o.BeFalse(),
598+
"%s should not exist because the API rejected it", pisDup)
599+
logger.Infof("OK!\n")
600+
})
519601
})
520602

521603
// getReleaseInfoPullspecOrFail returns a list of strings containing the names of the pullspec images
@@ -601,10 +683,7 @@ func DigestMirrorTest(oc *exutil.CLI, mcp *MachineConfigPool, idmsName, idmsMirr
601683
)
602684

603685
exutil.By("Remove the image from all nodes in the pool")
604-
for _, node := range allNodes {
605-
// We ignore errors, since the image can be present or not in the nodes
606-
_ = NewRemoteImage(node, pinnedImage).Rmi()
607-
}
686+
removeImageFromNodes(allNodes, pinnedImage)
608687
logger.Infof("OK!\n")
609688

610689
exutil.By("Create new machine config to deploy a ImageDigestMirrorSet configuring a mirror registry")
@@ -696,3 +775,30 @@ func basicPinnedImageTest(mcp *MachineConfigPool, pinnedImageSetName string) {
696775
o.Expect(secondPinnedImage.IsPinned()).To(o.BeFalse(), "%s is pinned, but it should NOT", secondPinnedImage)
697776
logger.Infof("OK!\n")
698777
}
778+
779+
// removeImageFromNodes removes the given image from all provided nodes, ignoring errors since the image may not be present
780+
func removeImageFromNodes(nodes []*Node, image string) {
781+
for _, node := range nodes {
782+
_ = NewRemoteImage(node, image).Rmi()
783+
}
784+
}
785+
786+
// createPinnedImageSetAndWait creates a PinnedImageSet, waits for the pool to complete pinning,
787+
// and verifies the images are pinned on all provided nodes
788+
func createPinnedImageSetAndWait(oc *exutil.CLI, name string, mcp *MachineConfigPool, images []string, nodes []*Node, waitForPinned time.Duration) *PinnedImageSet {
789+
pis, err := CreateGenericPinnedImageSet(oc, name, mcp.GetName(), images)
790+
o.Expect(err).NotTo(o.HaveOccurred(), "Error creating pinnedimageset %s", pis)
791+
792+
o.Expect(mcp.waitForPinComplete(waitForPinned)).To(o.Succeed(),
793+
"Pinned image operation is not completed in %s", mcp)
794+
795+
for _, node := range nodes {
796+
for _, image := range images {
797+
ri := NewRemoteImage(node, image)
798+
o.Expect(ri.IsPinned()).To(o.BeTrue(),
799+
"%s is not pinned, but it should be", ri)
800+
}
801+
}
802+
803+
return pis
804+
}

0 commit comments

Comments
 (0)