Skip to content

Commit 11a7637

Browse files
authored
test: add rollout strategy transition E2Es for staged update run (#305)
1 parent 6e0501f commit 11a7637

File tree

2 files changed

+233
-6
lines changed

2 files changed

+233
-6
lines changed

test/e2e/cluster_staged_updaterun_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -981,10 +981,9 @@ var _ = Describe("test CRP rollout with staged update run", func() {
981981
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP strategy to external rollout")
982982
})
983983

984-
It("Should update crp status to reflect external rollout strategy", func() {
985-
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
986-
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
987-
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status for external strategy", crpName)
984+
It("Should update crp status to reflect external rollout strategy with new observed generation and no other change", func() {
985+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
986+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
988987
})
989988

990989
It("Update the configmap on hub but should not rollout to member clusters", func() {
@@ -1001,8 +1000,7 @@ var _ = Describe("test CRP rollout with staged update run", func() {
10011000
validateLatestClusterResourceSnapshot(crpName, resourceSnapshotIndex2nd)
10021001

10031002
// CRP status should still show completed with old snapshot
1004-
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
1005-
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
1003+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
10061004
Consistently(crpStatusUpdatedActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep CRP %s status as expected", crpName)
10071005
})
10081006

test/e2e/staged_updaterun_test.go

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,235 @@ var _ = Describe("test RP rollout with staged update run", Label("resourceplacem
872872

873873
It("Should not rollout any resources to member clusters as it's reportDiff mode", checkIfRemovedConfigMapFromAllMemberClustersConsistently)
874874
})
875+
876+
Context("Test RP rollout strategy transition from rollingUpdate to external", Ordered, func() {
877+
var strategy *placementv1beta1.StagedUpdateStrategy
878+
updateRunName := fmt.Sprintf(stagedUpdateRunNameWithSubIndexTemplate, GinkgoParallelProcess(), 0)
879+
var oldConfigMap, newConfigMap corev1.ConfigMap
880+
881+
BeforeAll(func() {
882+
// Create the RP with rollingUpdate strategy initially.
883+
rp := &placementv1beta1.ResourcePlacement{
884+
ObjectMeta: metav1.ObjectMeta{
885+
Name: rpName,
886+
Namespace: testNamespace,
887+
// Add a custom finalizer; this would allow us to better observe
888+
// the behavior of the controllers.
889+
Finalizers: []string{customDeletionBlockerFinalizer},
890+
},
891+
Spec: placementv1beta1.PlacementSpec{
892+
ResourceSelectors: configMapSelector(),
893+
Strategy: placementv1beta1.RolloutStrategy{
894+
Type: placementv1beta1.RollingUpdateRolloutStrategyType,
895+
},
896+
},
897+
}
898+
Expect(hubClient.Create(ctx, rp)).To(Succeed(), "Failed to create RP")
899+
900+
// Create the stagedUpdateStrategy for later use.
901+
strategy = createStagedUpdateStrategySucceed(strategyName, testNamespace)
902+
903+
oldConfigMap = appConfigMap()
904+
newConfigMap = appConfigMap()
905+
newConfigMap.Data["data"] = testConfigMapDataValue
906+
})
907+
908+
AfterAll(func() {
909+
// Remove the custom deletion blocker finalizer from the RP.
910+
ensureRPAndRelatedResourcesDeleted(types.NamespacedName{Name: rpName, Namespace: testNamespace}, allMemberClusters)
911+
912+
// Delete the stagedUpdateRun.
913+
ensureStagedUpdateRunDeletion(updateRunName, testNamespace)
914+
915+
// Delete the stagedUpdateStrategy.
916+
ensureStagedUpdateRunStrategyDeletion(strategyName, testNamespace)
917+
})
918+
919+
It("Should rollout resources to all member clusters with rollingUpdate strategy", func() {
920+
rpStatusUpdatedActual := rpStatusUpdatedActual(appConfigMapIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
921+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status as expected", testNamespace, rpName)
922+
checkIfPlacedWorkResourcesOnMemberClustersInUpdateRun(allMemberClusters)
923+
})
924+
925+
It("Update RP to use external rollout strategy", func() {
926+
Eventually(func() error {
927+
rp := &placementv1beta1.ResourcePlacement{}
928+
if err := hubClient.Get(ctx, client.ObjectKey{Name: rpName, Namespace: testNamespace}, rp); err != nil {
929+
return fmt.Errorf("failed to get the rp: %w", err)
930+
}
931+
rp.Spec.Strategy = placementv1beta1.RolloutStrategy{
932+
Type: placementv1beta1.ExternalRolloutStrategyType,
933+
}
934+
return hubClient.Update(ctx, rp)
935+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP strategy to external rollout")
936+
})
937+
938+
It("Should update rp status to reflect external rollout strategy with new observed generation and no other change", func() {
939+
rpStatusUpdatedActual := rpStatusUpdatedActual(appConfigMapIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
940+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status as expected", testNamespace, rpName)
941+
})
942+
943+
It("Update the configmap on hub but should not rollout to member clusters", func() {
944+
updateConfigMapSucceed(&newConfigMap)
945+
946+
// Verify old configmap is still on all member clusters.
947+
for _, cluster := range allMemberClusters {
948+
configMapActual := configMapPlacedOnClusterActual(cluster, &oldConfigMap)
949+
Consistently(configMapActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep old configmap %s data on cluster %s", oldConfigMap.Name, cluster.ClusterName)
950+
}
951+
})
952+
953+
It("Should have the new resource snapshot but RP status should remain completed with old snapshot", func() {
954+
validateLatestResourceSnapshot(rpName, testNamespace, resourceSnapshotIndex2nd)
955+
956+
// RP status should still show completed with old snapshot.
957+
rpStatusUpdatedActual := rpStatusUpdatedActual(appConfigMapIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
958+
Consistently(rpStatusUpdatedActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep RP %s/%s status as expected", testNamespace, rpName)
959+
})
960+
961+
It("Create a staged update run with new resourceSnapshotIndex and verify rollout happens", func() {
962+
createStagedUpdateRunSucceed(updateRunName, testNamespace, rpName, resourceSnapshotIndex2nd, strategyName)
963+
964+
// Verify rollout to canary cluster first.
965+
By("Verify that the new configmap is updated on member-cluster-2 during canary stage")
966+
configMapActual := configMapPlacedOnClusterActual(allMemberClusters[1], &newConfigMap)
967+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, allMemberClusterNames[1])
968+
969+
validateAndApproveNamespacedApprovalRequests(updateRunName, testNamespace, envCanary)
970+
971+
// Verify complete rollout.
972+
surSucceededActual := stagedUpdateRunStatusSucceededActual(updateRunName, testNamespace, policySnapshotIndex1st, len(allMemberClusters), defaultApplyStrategy, &strategy.Spec, [][]string{{allMemberClusterNames[1]}, {allMemberClusterNames[0], allMemberClusterNames[2]}}, nil, nil, nil)
973+
Eventually(surSucceededActual, updateRunEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to validate updateRun %s/%s succeeded", testNamespace, updateRunName)
974+
975+
// Verify new configmap is on all member clusters.
976+
for _, cluster := range allMemberClusters {
977+
configMapActual := configMapPlacedOnClusterActual(cluster, &newConfigMap)
978+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, cluster.ClusterName)
979+
}
980+
})
981+
982+
It("Should update rp status as completed with new snapshot", func() {
983+
rpStatusUpdatedActual := rpStatusWithExternalStrategyActual(appConfigMapIdentifiers(), resourceSnapshotIndex2nd, true, allMemberClusterNames,
984+
[]string{resourceSnapshotIndex2nd, resourceSnapshotIndex2nd, resourceSnapshotIndex2nd}, []bool{true, true, true}, nil, nil)
985+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status as expected", testNamespace, rpName)
986+
})
987+
})
988+
989+
Context("Test RP rollout strategy transition from external to rollingUpdate", Ordered, func() {
990+
var strategy *placementv1beta1.StagedUpdateStrategy
991+
updateRunName := fmt.Sprintf(stagedUpdateRunNameWithSubIndexTemplate, GinkgoParallelProcess(), 0)
992+
var oldConfigMap, newConfigMap corev1.ConfigMap
993+
994+
BeforeAll(func() {
995+
// Create the RP with external rollout strategy initially.
996+
rp := &placementv1beta1.ResourcePlacement{
997+
ObjectMeta: metav1.ObjectMeta{
998+
Name: rpName,
999+
Namespace: testNamespace,
1000+
// Add a custom finalizer; this would allow us to better observe
1001+
// the behavior of the controllers.
1002+
Finalizers: []string{customDeletionBlockerFinalizer},
1003+
},
1004+
Spec: placementv1beta1.PlacementSpec{
1005+
ResourceSelectors: configMapSelector(),
1006+
Strategy: placementv1beta1.RolloutStrategy{
1007+
Type: placementv1beta1.ExternalRolloutStrategyType,
1008+
},
1009+
},
1010+
}
1011+
Expect(hubClient.Create(ctx, rp)).To(Succeed(), "Failed to create RP")
1012+
1013+
// Create the stagedUpdateStrategy.
1014+
strategy = createStagedUpdateStrategySucceed(strategyName, testNamespace)
1015+
1016+
oldConfigMap = appConfigMap()
1017+
newConfigMap = appConfigMap()
1018+
newConfigMap.Data["data"] = testConfigMapDataValue
1019+
})
1020+
1021+
AfterAll(func() {
1022+
// Remove the custom deletion blocker finalizer from the RP.
1023+
ensureRPAndRelatedResourcesDeleted(types.NamespacedName{Name: rpName, Namespace: testNamespace}, allMemberClusters)
1024+
1025+
// Delete the stagedUpdateRun.
1026+
ensureStagedUpdateRunDeletion(updateRunName, testNamespace)
1027+
1028+
// Delete the stagedUpdateStrategy.
1029+
ensureStagedUpdateRunStrategyDeletion(strategyName, testNamespace)
1030+
})
1031+
1032+
It("Should not rollout any resources to member clusters with external strategy", checkIfRemovedConfigMapFromAllMemberClustersConsistently)
1033+
1034+
It("Should have the latest resource snapshot", func() {
1035+
validateLatestResourceSnapshot(rpName, testNamespace, resourceSnapshotIndex1st)
1036+
})
1037+
1038+
It("Should update rp status as pending rollout", func() {
1039+
rpStatusUpdatedActual := rpStatusWithExternalStrategyActual(nil, "", false, allMemberClusterNames, []string{"", "", ""}, []bool{false, false, false}, nil, nil)
1040+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status as expected", testNamespace, rpName)
1041+
})
1042+
1043+
It("Create updateRun and verify resources are rolled out", func() {
1044+
createStagedUpdateRunSucceed(updateRunName, testNamespace, rpName, resourceSnapshotIndex1st, strategyName)
1045+
1046+
validateAndApproveNamespacedApprovalRequests(updateRunName, testNamespace, envCanary)
1047+
1048+
surSucceededActual := stagedUpdateRunStatusSucceededActual(updateRunName, testNamespace, policySnapshotIndex1st, len(allMemberClusters), defaultApplyStrategy, &strategy.Spec, [][]string{{allMemberClusterNames[1]}, {allMemberClusterNames[0], allMemberClusterNames[2]}}, nil, nil, nil)
1049+
Eventually(surSucceededActual, updateRunEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to validate updateRun %s/%s succeeded", testNamespace, updateRunName)
1050+
1051+
checkIfPlacedWorkResourcesOnMemberClustersInUpdateRun(allMemberClusters)
1052+
})
1053+
1054+
It("Should update rp status as completed", func() {
1055+
rpStatusUpdatedActual := rpStatusWithExternalStrategyActual(appConfigMapIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
1056+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
1057+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status as expected", testNamespace, rpName)
1058+
})
1059+
1060+
It("Update the configmap on hub but should not rollout to member clusters with external strategy", func() {
1061+
updateConfigMapSucceed(&newConfigMap)
1062+
1063+
// Verify old configmap is still on all member clusters.
1064+
for _, cluster := range allMemberClusters {
1065+
configMapActual := configMapPlacedOnClusterActual(cluster, &oldConfigMap)
1066+
Consistently(configMapActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep old configmap %s data on cluster %s", oldConfigMap.Name, cluster.ClusterName)
1067+
}
1068+
})
1069+
1070+
It("Should have new resource snapshot but RP status should remain completed with old snapshot", func() {
1071+
validateLatestResourceSnapshot(rpName, testNamespace, resourceSnapshotIndex2nd)
1072+
1073+
// RP status should still show completed with old snapshot.
1074+
rpStatusUpdatedActual := rpStatusWithExternalStrategyActual(appConfigMapIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
1075+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
1076+
Consistently(rpStatusUpdatedActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep RP %s/%s status as expected", testNamespace, rpName)
1077+
})
1078+
1079+
It("Update RP to use rollingUpdate strategy", func() {
1080+
Eventually(func() error {
1081+
rp := &placementv1beta1.ResourcePlacement{}
1082+
if err := hubClient.Get(ctx, client.ObjectKey{Name: rpName, Namespace: testNamespace}, rp); err != nil {
1083+
return fmt.Errorf("failed to get the rp: %w", err)
1084+
}
1085+
rp.Spec.Strategy = placementv1beta1.RolloutStrategy{
1086+
Type: placementv1beta1.RollingUpdateRolloutStrategyType,
1087+
}
1088+
return hubClient.Update(ctx, rp)
1089+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP strategy to rollingUpdate")
1090+
})
1091+
1092+
It("Should automatically rollout new resources to all member clusters with rollingUpdate strategy", func() {
1093+
// Verify RP status shows all clusters with new resource snapshot.
1094+
rpStatusUpdatedActual := rpStatusUpdatedActual(appConfigMapIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex2nd)
1095+
Eventually(rpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update RP %s/%s status with rollingUpdate strategy", testNamespace, rpName)
1096+
1097+
// Verify new configmap is on all member clusters.
1098+
for _, cluster := range allMemberClusters {
1099+
configMapActual := configMapPlacedOnClusterActual(cluster, &newConfigMap)
1100+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, cluster.ClusterName)
1101+
}
1102+
})
1103+
})
8751104
})
8761105

8771106
func createStagedUpdateStrategySucceed(strategyName, namespace string) *placementv1beta1.StagedUpdateStrategy {

0 commit comments

Comments
 (0)