@@ -266,6 +266,40 @@ func regularDeploymentObjectAppliedActual(nsName, deployName string, appliedWork
266266 }
267267}
268268
269+ func regularConfigMapObjectAppliedActual (nsName , configMapName string , appliedWorkOwnerRef * metav1.OwnerReference ) func () error {
270+ return func () error {
271+ // Retrieve the ConfigMap object.
272+ gotConfigMap := & corev1.ConfigMap {}
273+ if err := memberClient .Get (ctx , client.ObjectKey {Namespace : nsName , Name : configMapName }, gotConfigMap ); err != nil {
274+ return fmt .Errorf ("failed to retrieve the ConfigMap object: %w" , err )
275+ }
276+
277+ // Check that the ConfigMap object has been created as expected.
278+
279+ // To ignore default values automatically, here the test suite rebuilds the objects.
280+ wantConfigMap := configMap .DeepCopy ()
281+ wantConfigMap .TypeMeta = metav1.TypeMeta {}
282+ wantConfigMap .Namespace = nsName
283+ wantConfigMap .Name = configMapName
284+ wantConfigMap .OwnerReferences = []metav1.OwnerReference {
285+ * appliedWorkOwnerRef ,
286+ }
287+
288+ rebuiltGotConfigMap := & corev1.ConfigMap {
289+ ObjectMeta : metav1.ObjectMeta {
290+ Name : gotConfigMap .Name ,
291+ Namespace : gotConfigMap .Namespace ,
292+ OwnerReferences : gotConfigMap .OwnerReferences ,
293+ },
294+ Data : gotConfigMap .Data ,
295+ }
296+ if diff := cmp .Diff (rebuiltGotConfigMap , wantConfigMap ); diff != "" {
297+ return fmt .Errorf ("configmap diff (-got +want):\n %s" , diff )
298+ }
299+ return nil
300+ }
301+ }
302+
269303func markDeploymentAsAvailable (nsName , deployName string ) {
270304 // Retrieve the Deployment object.
271305 gotDeploy := & appsv1.Deployment {}
@@ -444,6 +478,27 @@ func regularDeployRemovedActual(nsName, deployName string) func() error {
444478 }
445479}
446480
481+ func regularConfigMapRemovedActual (nsName , configMapName string ) func () error {
482+ return func () error {
483+ // Retrieve the ConfigMap object.
484+ configMap := & corev1.ConfigMap {
485+ ObjectMeta : metav1.ObjectMeta {
486+ Namespace : nsName ,
487+ Name : configMapName ,
488+ },
489+ }
490+ if err := memberClient .Delete (ctx , configMap ); err != nil && ! errors .IsNotFound (err ) {
491+ return fmt .Errorf ("failed to delete the ConfigMap object: %w" , err )
492+ }
493+
494+ // Check that the ConfigMap object has been deleted.
495+ if err := memberClient .Get (ctx , client.ObjectKey {Namespace : nsName , Name : configMapName }, configMap ); ! errors .IsNotFound (err ) {
496+ return fmt .Errorf ("configMap object still exists or an unexpected error occurred: %w" , err )
497+ }
498+ return nil
499+ }
500+ }
501+
447502func regularNSObjectNotAppliedActual (nsName string ) func () error {
448503 return func () error {
449504 // Retrieve the NS object.
@@ -1088,6 +1143,194 @@ var _ = Describe("applying manifests", func() {
10881143 // deletion; consequently this test suite would not attempt so verify its deletion.
10891144 })
10901145 })
1146+
1147+ Context ("can handle partial failures (pre-processing, decoding error)" , Ordered , func () {
1148+ workName := fmt .Sprintf (workNameTemplate , utils .RandStr ())
1149+ // The environment prepared by the envtest package does not support namespace
1150+ // deletion; each test case would use a new namespace.
1151+ nsName := fmt .Sprintf (nsNameTemplate , utils .RandStr ())
1152+
1153+ var appliedWorkOwnerRef * metav1.OwnerReference
1154+ var regularNS * corev1.Namespace
1155+ var decodingErredDeploy * appsv1.Deployment
1156+ var regularConfigMap * corev1.ConfigMap
1157+
1158+ BeforeAll (func () {
1159+ // Prepare a NS object.
1160+ regularNS = ns .DeepCopy ()
1161+ regularNS .Name = nsName
1162+ regularNSJSON := marshalK8sObjJSON (regularNS )
1163+
1164+ // Prepare a mal-formed Deployment object.
1165+ decodingErredDeploy = deploy .DeepCopy ()
1166+ decodingErredDeploy .TypeMeta = metav1.TypeMeta {
1167+ APIVersion : "dummy/v10" ,
1168+ Kind : "Fake" ,
1169+ }
1170+ decodingErredDeploy .Namespace = nsName
1171+ decodingErredDeploy .Name = deployName
1172+ decodingErredDeployJSON := marshalK8sObjJSON (decodingErredDeploy )
1173+
1174+ // Prepare a ConfigMap object.
1175+ regularConfigMap = configMap .DeepCopy ()
1176+ regularConfigMap .Namespace = nsName
1177+ regularConfigMapJSON := marshalK8sObjJSON (regularConfigMap )
1178+
1179+ // Create a new Work object with all the manifest JSONs.
1180+ createWorkObject (workName , nil , regularNSJSON , decodingErredDeployJSON , regularConfigMapJSON )
1181+ })
1182+
1183+ It ("should add cleanup finalizer to the Work object" , func () {
1184+ finalizerAddedActual := workFinalizerAddedActual (workName )
1185+ Eventually (finalizerAddedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to add cleanup finalizer to the Work object" )
1186+ })
1187+
1188+ It ("should prepare an AppliedWork object" , func () {
1189+ appliedWorkCreatedActual := appliedWorkCreatedActual (workName )
1190+ Eventually (appliedWorkCreatedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to prepare an AppliedWork object" )
1191+
1192+ appliedWorkOwnerRef = prepareAppliedWorkOwnerRef (workName )
1193+ })
1194+
1195+ It ("should apply the manifests" , func () {
1196+ // Ensure that the NS object has been applied as expected.
1197+ regularNSObjectAppliedActual := regularNSObjectAppliedActual (nsName , appliedWorkOwnerRef )
1198+ Eventually (regularNSObjectAppliedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to apply the namespace object" )
1199+
1200+ Expect (memberClient .Get (ctx , client.ObjectKey {Name : nsName }, regularNS )).To (Succeed (), "Failed to retrieve the NS object" )
1201+
1202+ // Ensure that the ConfigMap object has been applied as expected.
1203+ regularConfigMapObjectAppliedActual := regularConfigMapObjectAppliedActual (nsName , configMapName , appliedWorkOwnerRef )
1204+ Eventually (regularConfigMapObjectAppliedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to apply the ConfigMap object" )
1205+ Expect (memberClient .Get (ctx , client.ObjectKey {Namespace : nsName , Name : configMapName }, regularConfigMap )).To (Succeed (), "Failed to retrieve the Deployment object" )
1206+ })
1207+
1208+ It ("should update the Work object status" , func () {
1209+ // Prepare the status information.
1210+ workConds := []metav1.Condition {
1211+ {
1212+ Type : fleetv1beta1 .WorkConditionTypeApplied ,
1213+ Status : metav1 .ConditionFalse ,
1214+ Reason : WorkNotAllManifestsAppliedReason ,
1215+ },
1216+ }
1217+ manifestConds := []fleetv1beta1.ManifestCondition {
1218+ {
1219+ Identifier : fleetv1beta1.WorkResourceIdentifier {
1220+ Ordinal : 0 ,
1221+ Group : "" ,
1222+ Version : "v1" ,
1223+ Kind : "Namespace" ,
1224+ Resource : "namespaces" ,
1225+ Name : nsName ,
1226+ },
1227+ Conditions : []metav1.Condition {
1228+ {
1229+ Type : fleetv1beta1 .WorkConditionTypeApplied ,
1230+ Status : metav1 .ConditionTrue ,
1231+ Reason : string (ManifestProcessingApplyResultTypeApplied ),
1232+ ObservedGeneration : 0 ,
1233+ },
1234+ {
1235+ Type : fleetv1beta1 .WorkConditionTypeAvailable ,
1236+ Status : metav1 .ConditionTrue ,
1237+ Reason : string (ManifestProcessingAvailabilityResultTypeAvailable ),
1238+ ObservedGeneration : 0 ,
1239+ },
1240+ },
1241+ },
1242+ {
1243+ Identifier : fleetv1beta1.WorkResourceIdentifier {
1244+ Ordinal : 1 ,
1245+ Group : "dummy" ,
1246+ Version : "v10" ,
1247+ Kind : "Fake" ,
1248+ Name : deployName ,
1249+ Namespace : nsName ,
1250+ },
1251+ Conditions : []metav1.Condition {
1252+ {
1253+ Type : fleetv1beta1 .WorkConditionTypeApplied ,
1254+ Status : metav1 .ConditionFalse ,
1255+ Reason : string (ManifestProcessingApplyResultTypeDecodingErred ),
1256+ },
1257+ },
1258+ },
1259+ {
1260+ Identifier : fleetv1beta1.WorkResourceIdentifier {
1261+ Ordinal : 2 ,
1262+ Version : "v1" ,
1263+ Kind : "ConfigMap" ,
1264+ Resource : "configmaps" ,
1265+ Name : configMapName ,
1266+ Namespace : nsName ,
1267+ },
1268+ Conditions : []metav1.Condition {
1269+ {
1270+ Type : fleetv1beta1 .WorkConditionTypeApplied ,
1271+ Status : metav1 .ConditionTrue ,
1272+ Reason : string (ManifestProcessingApplyResultTypeApplied ),
1273+ },
1274+ {
1275+ Type : fleetv1beta1 .WorkConditionTypeAvailable ,
1276+ Status : metav1 .ConditionTrue ,
1277+ Reason : string (ManifestProcessingAvailabilityResultTypeAvailable ),
1278+ },
1279+ },
1280+ },
1281+ }
1282+
1283+ workStatusUpdatedActual := workStatusUpdated (workName , workConds , manifestConds , nil , nil )
1284+ Eventually (workStatusUpdatedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to update work status" )
1285+ })
1286+
1287+ It ("should update the AppliedWork object status" , func () {
1288+ // Prepare the status information.
1289+ appliedResourceMeta := []fleetv1beta1.AppliedResourceMeta {
1290+ {
1291+ WorkResourceIdentifier : fleetv1beta1.WorkResourceIdentifier {
1292+ Ordinal : 0 ,
1293+ Group : "" ,
1294+ Version : "v1" ,
1295+ Kind : "Namespace" ,
1296+ Resource : "namespaces" ,
1297+ Name : nsName ,
1298+ },
1299+ UID : regularNS .UID ,
1300+ },
1301+ {
1302+ WorkResourceIdentifier : fleetv1beta1.WorkResourceIdentifier {
1303+ Ordinal : 2 ,
1304+ Group : "" ,
1305+ Version : "v1" ,
1306+ Kind : "ConfigMap" ,
1307+ Resource : "configmaps" ,
1308+ Name : configMapName ,
1309+ Namespace : nsName ,
1310+ },
1311+ UID : regularConfigMap .UID ,
1312+ },
1313+ }
1314+
1315+ appliedWorkStatusUpdatedActual := appliedWorkStatusUpdated (workName , appliedResourceMeta )
1316+ Eventually (appliedWorkStatusUpdatedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to update appliedWork status" )
1317+ })
1318+
1319+ AfterAll (func () {
1320+ // Delete the Work object and related resources.
1321+ cleanupWorkObject (workName )
1322+
1323+ // Ensure that all applied manifests have been removed.
1324+ appliedWorkRemovedActual := appliedWorkRemovedActual (workName )
1325+ Eventually (appliedWorkRemovedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to remove the AppliedWork object" )
1326+
1327+ regularConfigMapRemovedActual := regularConfigMapRemovedActual (nsName , configMapName )
1328+ Eventually (regularConfigMapRemovedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to remove the ConfigMap object" )
1329+
1330+ // The environment prepared by the envtest package does not support namespace
1331+ // deletion; consequently this test suite would not attempt so verify its deletion.
1332+ })
1333+ })
10911334})
10921335
10931336var _ = Describe ("drift detection and takeover" , func () {
0 commit comments