Skip to content

Commit 4221b88

Browse files
authored
test: add e2e tests for rollout strategy transitions (#135)
1 parent e7d7077 commit 4221b88

File tree

1 file changed

+248
-3
lines changed

1 file changed

+248
-3
lines changed

test/e2e/updaterun_test.go

Lines changed: 248 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const (
4444
policySnapshotIndex1st = "0"
4545
policySnapshotIndex2nd = "1"
4646
policySnapshotIndex3rd = "2"
47+
48+
testConfigMapDataValue = "new"
4749
)
4850

4951
// Note that this container will run in parallel with other containers.
@@ -86,7 +88,7 @@ var _ = Describe("test CRP rollout with staged update run", func() {
8688

8789
oldConfigMap = appConfigMap()
8890
newConfigMap = appConfigMap()
89-
newConfigMap.Data["data"] = "new"
91+
newConfigMap.Data["data"] = testConfigMapDataValue
9092
})
9193

9294
AfterAll(func() {
@@ -149,7 +151,7 @@ var _ = Describe("test CRP rollout with staged update run", func() {
149151
})
150152

151153
It("Should update the configmap successfully on hub but not change member clusters", func() {
152-
Eventually(func() error { return hubClient.Update(ctx, &newConfigMap) }, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update configmap on hub")
154+
updateConfigMapSucceed(&newConfigMap)
153155

154156
for _, cluster := range allMemberClusters {
155157
configMapActual := configMapPlacedOnClusterActual(cluster, &oldConfigMap)
@@ -904,6 +906,241 @@ var _ = Describe("test CRP rollout with staged update run", func() {
904906

905907
It("Should not rollout any resources to member clusters as it's reportDiff mode", checkIfRemovedWorkResourcesFromAllMemberClustersConsistently)
906908
})
909+
910+
Context("Test CRP rollout strategy transition from rollingUpdate to external", Ordered, func() {
911+
var strategy *placementv1beta1.ClusterStagedUpdateStrategy
912+
updateRunName := fmt.Sprintf(updateRunNameWithSubIndexTemplate, GinkgoParallelProcess(), 0)
913+
var oldConfigMap, newConfigMap corev1.ConfigMap
914+
915+
BeforeAll(func() {
916+
// Create a test namespace and a configMap inside it on the hub cluster.
917+
createWorkResources()
918+
919+
// Create the CRP with rollingUpdate strategy initially.
920+
crp := &placementv1beta1.ClusterResourcePlacement{
921+
ObjectMeta: metav1.ObjectMeta{
922+
Name: crpName,
923+
// Add a custom finalizer; this would allow us to better observe
924+
// the behavior of the controllers.
925+
Finalizers: []string{customDeletionBlockerFinalizer},
926+
},
927+
Spec: placementv1beta1.PlacementSpec{
928+
ResourceSelectors: workResourceSelector(),
929+
Strategy: placementv1beta1.RolloutStrategy{
930+
Type: placementv1beta1.RollingUpdateRolloutStrategyType,
931+
},
932+
},
933+
}
934+
Expect(hubClient.Create(ctx, crp)).To(Succeed(), "Failed to create CRP")
935+
936+
// Create the clusterStagedUpdateStrategy for later use.
937+
strategy = createStagedUpdateStrategySucceed(strategyName)
938+
939+
oldConfigMap = appConfigMap()
940+
newConfigMap = appConfigMap()
941+
newConfigMap.Data["data"] = testConfigMapDataValue
942+
})
943+
944+
AfterAll(func() {
945+
// Remove the custom deletion blocker finalizer from the CRP.
946+
ensureCRPAndRelatedResourcesDeleted(crpName, allMemberClusters)
947+
948+
// Delete the clusterStagedUpdateRun.
949+
ensureUpdateRunDeletion(updateRunName)
950+
951+
// Delete the clusterStagedUpdateStrategy.
952+
ensureUpdateRunStrategyDeletion(strategyName)
953+
})
954+
955+
It("Should rollout resources to all member clusters with rollingUpdate strategy", func() {
956+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex1st)
957+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
958+
checkIfPlacedWorkResourcesOnMemberClustersInUpdateRun(allMemberClusters)
959+
})
960+
961+
It("Update CRP to use external rollout strategy", func() {
962+
Eventually(func() error {
963+
crp := &placementv1beta1.ClusterResourcePlacement{}
964+
if err := hubClient.Get(ctx, client.ObjectKey{Name: crpName}, crp); err != nil {
965+
return fmt.Errorf("failed to get the crp: %w", err)
966+
}
967+
crp.Spec.Strategy = placementv1beta1.RolloutStrategy{
968+
Type: placementv1beta1.ExternalRolloutStrategyType,
969+
}
970+
return hubClient.Update(ctx, crp)
971+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP strategy to external rollout")
972+
})
973+
974+
It("Should update crp status to reflect external rollout strategy", func() {
975+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
976+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
977+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status for external strategy", crpName)
978+
})
979+
980+
It("Update the configmap on hub but should not rollout to member clusters", func() {
981+
updateConfigMapSucceed(&newConfigMap)
982+
983+
// Verify old configmap is still on all member clusters
984+
for _, cluster := range allMemberClusters {
985+
configMapActual := configMapPlacedOnClusterActual(cluster, &oldConfigMap)
986+
Consistently(configMapActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep old configmap %s data on cluster %s", oldConfigMap.Name, cluster.ClusterName)
987+
}
988+
})
989+
990+
It("Should have the new resource snapshot but CRP status should remain completed with old snapshot", func() {
991+
validateLatestResourceSnapshot(crpName, resourceSnapshotIndex2nd)
992+
993+
// CRP status should still show completed with old snapshot
994+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
995+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
996+
Consistently(crpStatusUpdatedActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep CRP %s status as expected", crpName)
997+
})
998+
999+
It("Create a staged update run with new resourceSnapshotIndex and verify rollout happens", func() {
1000+
createStagedUpdateRunSucceed(updateRunName, crpName, resourceSnapshotIndex2nd, strategyName)
1001+
1002+
// Verify rollout to canary cluster first
1003+
By("Verify that the new configmap is updated on member-cluster-2 during canary stage")
1004+
configMapActual := configMapPlacedOnClusterActual(allMemberClusters[1], &newConfigMap)
1005+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, allMemberClusterNames[1])
1006+
1007+
validateAndApproveClusterApprovalRequests(updateRunName, envCanary)
1008+
1009+
// Verify complete rollout
1010+
updateRunSucceededActual := updateRunStatusSucceededActual(updateRunName, policySnapshotIndex1st, len(allMemberClusters), nil, &strategy.Spec, [][]string{{allMemberClusterNames[1]}, {allMemberClusterNames[0], allMemberClusterNames[2]}}, nil, nil, nil)
1011+
Eventually(updateRunSucceededActual, updateRunEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to validate updateRun %s succeeded", updateRunName)
1012+
1013+
// Verify new configmap is on all member clusters
1014+
for _, cluster := range allMemberClusters {
1015+
configMapActual := configMapPlacedOnClusterActual(cluster, &newConfigMap)
1016+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, cluster.ClusterName)
1017+
}
1018+
})
1019+
1020+
It("Should update crp status as completed with new snapshot", func() {
1021+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex2nd, true, allMemberClusterNames,
1022+
[]string{resourceSnapshotIndex2nd, resourceSnapshotIndex2nd, resourceSnapshotIndex2nd}, []bool{true, true, true}, nil, nil)
1023+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
1024+
})
1025+
})
1026+
1027+
Context("Test CRP rollout strategy transition from external to rollingUpdate", Ordered, func() {
1028+
var strategy *placementv1beta1.ClusterStagedUpdateStrategy
1029+
updateRunName := fmt.Sprintf(updateRunNameWithSubIndexTemplate, GinkgoParallelProcess(), 0)
1030+
var oldConfigMap, newConfigMap corev1.ConfigMap
1031+
1032+
BeforeAll(func() {
1033+
// Create a test namespace and a configMap inside it on the hub cluster.
1034+
createWorkResources()
1035+
1036+
// Create the CRP with external rollout strategy initially.
1037+
crp := &placementv1beta1.ClusterResourcePlacement{
1038+
ObjectMeta: metav1.ObjectMeta{
1039+
Name: crpName,
1040+
// Add a custom finalizer; this would allow us to better observe
1041+
// the behavior of the controllers.
1042+
Finalizers: []string{customDeletionBlockerFinalizer},
1043+
},
1044+
Spec: placementv1beta1.PlacementSpec{
1045+
ResourceSelectors: workResourceSelector(),
1046+
Strategy: placementv1beta1.RolloutStrategy{
1047+
Type: placementv1beta1.ExternalRolloutStrategyType,
1048+
},
1049+
},
1050+
}
1051+
Expect(hubClient.Create(ctx, crp)).To(Succeed(), "Failed to create CRP")
1052+
1053+
// Create the clusterStagedUpdateStrategy.
1054+
strategy = createStagedUpdateStrategySucceed(strategyName)
1055+
1056+
oldConfigMap = appConfigMap()
1057+
newConfigMap = appConfigMap()
1058+
newConfigMap.Data["data"] = testConfigMapDataValue
1059+
})
1060+
1061+
AfterAll(func() {
1062+
// Remove the custom deletion blocker finalizer from the CRP.
1063+
ensureCRPAndRelatedResourcesDeleted(crpName, allMemberClusters)
1064+
1065+
// Delete the clusterStagedUpdateRun.
1066+
ensureUpdateRunDeletion(updateRunName)
1067+
1068+
// Delete the clusterStagedUpdateStrategy.
1069+
ensureUpdateRunStrategyDeletion(strategyName)
1070+
})
1071+
1072+
It("Should not rollout any resources to member clusters with external strategy", checkIfRemovedWorkResourcesFromAllMemberClustersConsistently)
1073+
1074+
It("Should have the latest resource snapshot", func() {
1075+
validateLatestResourceSnapshot(crpName, resourceSnapshotIndex1st)
1076+
})
1077+
1078+
It("Should update crp status as pending rollout", func() {
1079+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(nil, "", false, allMemberClusterNames, []string{"", "", ""}, []bool{false, false, false}, nil, nil)
1080+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
1081+
})
1082+
1083+
It("Create updateRun and verify resources are rolled out", func() {
1084+
createStagedUpdateRunSucceed(updateRunName, crpName, resourceSnapshotIndex1st, strategyName)
1085+
1086+
validateAndApproveClusterApprovalRequests(updateRunName, envCanary)
1087+
1088+
updateRunSucceededActual := updateRunStatusSucceededActual(updateRunName, policySnapshotIndex1st, len(allMemberClusters), nil, &strategy.Spec, [][]string{{allMemberClusterNames[1]}, {allMemberClusterNames[0], allMemberClusterNames[2]}}, nil, nil, nil)
1089+
Eventually(updateRunSucceededActual, updateRunEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to validate updateRun %s succeeded", updateRunName)
1090+
1091+
checkIfPlacedWorkResourcesOnMemberClustersInUpdateRun(allMemberClusters)
1092+
})
1093+
1094+
It("Should update crp status as completed", func() {
1095+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
1096+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
1097+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
1098+
})
1099+
1100+
It("Update the configmap on hub but should not rollout to member clusters with external strategy", func() {
1101+
updateConfigMapSucceed(&newConfigMap)
1102+
1103+
// Verify old configmap is still on all member clusters
1104+
for _, cluster := range allMemberClusters {
1105+
configMapActual := configMapPlacedOnClusterActual(cluster, &oldConfigMap)
1106+
Consistently(configMapActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep old configmap %s data on cluster %s", oldConfigMap.Name, cluster.ClusterName)
1107+
}
1108+
})
1109+
1110+
It("Should have new resource snapshot but CRP status should remain completed with old snapshot", func() {
1111+
validateLatestResourceSnapshot(crpName, resourceSnapshotIndex2nd)
1112+
1113+
// CRP status should still show completed with old snapshot
1114+
crpStatusUpdatedActual := crpStatusWithExternalStrategyActual(workResourceIdentifiers(), resourceSnapshotIndex1st, true, allMemberClusterNames,
1115+
[]string{resourceSnapshotIndex1st, resourceSnapshotIndex1st, resourceSnapshotIndex1st}, []bool{true, true, true}, nil, nil)
1116+
Consistently(crpStatusUpdatedActual, consistentlyDuration, consistentlyInterval).Should(Succeed(), "Failed to keep CRP %s status as expected", crpName)
1117+
})
1118+
1119+
It("Update CRP to use rollingUpdate strategy", func() {
1120+
Eventually(func() error {
1121+
crp := &placementv1beta1.ClusterResourcePlacement{}
1122+
if err := hubClient.Get(ctx, client.ObjectKey{Name: crpName}, crp); err != nil {
1123+
return fmt.Errorf("failed to get the crp: %w", err)
1124+
}
1125+
crp.Spec.Strategy = placementv1beta1.RolloutStrategy{
1126+
Type: placementv1beta1.RollingUpdateRolloutStrategyType,
1127+
}
1128+
return hubClient.Update(ctx, crp)
1129+
}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP strategy to rollingUpdate")
1130+
})
1131+
1132+
It("Should automatically rollout new resources to all member clusters with rollingUpdate strategy", func() {
1133+
// Verify CRP status shows all clusters with new resource snapshot
1134+
crpStatusUpdatedActual := crpStatusUpdatedActual(workResourceIdentifiers(), allMemberClusterNames, nil, resourceSnapshotIndex2nd)
1135+
Eventually(crpStatusUpdatedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status with rollingUpdate strategy", crpName)
1136+
1137+
// Verify new configmap is on all member clusters
1138+
for _, cluster := range allMemberClusters {
1139+
configMapActual := configMapPlacedOnClusterActual(cluster, &newConfigMap)
1140+
Eventually(configMapActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update to the new configmap %s on cluster %s", newConfigMap.Name, cluster.ClusterName)
1141+
}
1142+
})
1143+
})
9071144
})
9081145

9091146
// Note that this container cannot run in parallel with other containers.
@@ -1098,7 +1335,7 @@ var _ = Describe("Test member cluster join and leave flow with updateRun", Order
10981335
})
10991336

11001337
It("Should update the resources on hub cluster", func() {
1101-
Eventually(func() error { return hubClient.Update(ctx, &newConfigMap) }, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update configmap on hub")
1338+
updateConfigMapSucceed(&newConfigMap)
11021339
})
11031340

11041341
It("Should have the latest resource snapshot with updated resources", func() {
@@ -1336,3 +1573,11 @@ func validateAndApproveClusterApprovalRequests(updateRunName, stageName string)
13361573
return hubClient.Status().Update(ctx, appReq)
13371574
}, updateRunEventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to get or approve approval request")
13381575
}
1576+
1577+
func updateConfigMapSucceed(newConfigMap *corev1.ConfigMap) {
1578+
cm := &corev1.ConfigMap{}
1579+
key := client.ObjectKey{Namespace: newConfigMap.Namespace, Name: newConfigMap.Name}
1580+
Expect(hubClient.Get(ctx, key, cm)).To(Succeed(), "Failed to get configmap %s in namespace %s", newConfigMap.Name, newConfigMap.Namespace)
1581+
cm.Data = newConfigMap.Data
1582+
Expect(hubClient.Update(ctx, cm)).To(Succeed(), "Failed to update configmap %s in namespace %s", newConfigMap.Name, newConfigMap.Namespace)
1583+
}

0 commit comments

Comments
 (0)