Skip to content

Commit f3736c5

Browse files
committed
Minor fixes + test cases
1 parent 7f6590a commit f3736c5

4 files changed

Lines changed: 481 additions & 1 deletion

File tree

pkg/controllers/workapplier/controller_integration_test.go

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
269303
func 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+
447502
func 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

10931336
var _ = Describe("drift detection and takeover", func() {

pkg/controllers/workapplier/controller_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ var (
9494
nsUnstructured *unstructured.Unstructured
9595
nsJSON []byte
9696

97+
configMap = &corev1.ConfigMap{
98+
TypeMeta: metav1.TypeMeta{
99+
APIVersion: "v1",
100+
Kind: "ConfigMap",
101+
},
102+
ObjectMeta: metav1.ObjectMeta{
103+
Namespace: nsName,
104+
Name: configMapName,
105+
},
106+
Data: map[string]string{
107+
dummyLabelKey: dummyLabelValue1,
108+
},
109+
}
110+
97111
dummyOwnerRef = metav1.OwnerReference{
98112
APIVersion: "dummy.owner/v1",
99113
Kind: "DummyOwner",

pkg/controllers/workapplier/process.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (r *Reconciler) processManifests(
3232
for _, bundle := range bundles {
3333
if bundle.applyErr != nil {
3434
// Skip a manifest if it has failed pre-processing.
35-
return
35+
continue
3636
}
3737
r.processOneManifest(ctx, bundle, work, expectedAppliedWorkOwnerRef)
3838
klog.V(2).InfoS("Processed a manifest", "manifestObj", klog.KObj(bundle.manifestObj), "work", klog.KObj(work))

0 commit comments

Comments
 (0)