@@ -76,11 +76,26 @@ func NewApplyWorkReconciler(hubClient client.Client, spokeDynamicClient dynamic.
7676 }
7777}
7878
79+ // applyAction represents the action we take to apply the manifest
80+ // +enum
81+ type applyAction string
82+
83+ const (
84+ // ManifestCreatedAction indicates that we created the manifest for the first time.
85+ ManifestCreatedAction applyAction = "ManifestCreated"
86+
87+ // ManifestUpdatedAction indicates that we updated the manifest.
88+ ManifestUpdatedAction applyAction = "ManifestUpdated"
89+
90+ // ManifestNoChangeAction indicates that we don't need to change the manifest.
91+ ManifestNoChangeAction applyAction = "ManifestNoChange"
92+ )
93+
7994// applyResult contains the result of a manifest being applied.
8095type applyResult struct {
8196 identifier workv1alpha1.ResourceIdentifier
8297 generation int64
83- updated bool
98+ action applyAction
8499 err error
85100}
86101
@@ -266,19 +281,16 @@ func (r *ApplyWorkReconciler) applyManifests(ctx context.Context, manifests []wo
266281
267282 default :
268283 addOwnerRef (owner , rawObj )
269- appliedObj , result .updated , result .err = r .applyUnstructured (ctx , gvr , rawObj )
284+ appliedObj , result .action , result .err = r .applyUnstructured (ctx , gvr , rawObj )
270285 result .identifier = buildResourceIdentifier (index , rawObj , gvr )
271286 logObjRef := klog.ObjectRef {
272287 Name : result .identifier .Name ,
273288 Namespace : result .identifier .Namespace ,
274289 }
275290 if result .err == nil {
276291 result .generation = appliedObj .GetGeneration ()
277- if result .updated {
278- klog .V (2 ).InfoS ("manifest upsert succeeded" , "gvr" , gvr , "manifest" , logObjRef , "new ObservedGeneration" , result .generation )
279- } else {
280- klog .V (2 ).InfoS ("manifest upsert unwarranted" , "gvr" , gvr , "manifest" , logObjRef )
281- }
292+ klog .V (2 ).InfoS ("apply manifest succeeded" , "gvr" , gvr , "manifest" , logObjRef ,
293+ "apply action" , result .action , "new ObservedGeneration" , result .generation )
282294 } else {
283295 klog .ErrorS (result .err , "manifest upsert failed" , "gvr" , gvr , "manifest" , logObjRef )
284296 }
@@ -305,29 +317,30 @@ func (r *ApplyWorkReconciler) decodeManifest(manifest workv1alpha1.Manifest) (sc
305317}
306318
307319// Determines if an unstructured manifest object can & should be applied. If so, it applies (creates) the resource on the cluster.
308- func (r * ApplyWorkReconciler ) applyUnstructured (ctx context.Context , gvr schema.GroupVersionResource , manifestObj * unstructured.Unstructured ) (* unstructured.Unstructured , bool , error ) {
320+ func (r * ApplyWorkReconciler ) applyUnstructured (ctx context.Context , gvr schema.GroupVersionResource ,
321+ manifestObj * unstructured.Unstructured ) (* unstructured.Unstructured , applyAction , error ) {
309322 manifestRef := klog.ObjectRef {
310323 Name : manifestObj .GetName (),
311324 Namespace : manifestObj .GetNamespace (),
312325 }
313326 // compute the hash without taking into consider the last applied annotation
314327 if err := setManifestHashAnnotation (manifestObj ); err != nil {
315- return nil , false , err
328+ return nil , ManifestNoChangeAction , err
316329 }
317330
318331 // extract the common create procedure to reuse
319- var createFunc = func () (* unstructured.Unstructured , bool , error ) {
332+ var createFunc = func () (* unstructured.Unstructured , applyAction , error ) {
320333 // record the raw manifest with the hash annotation in the manifest
321334 if err := setModifiedConfigurationAnnotation (manifestObj ); err != nil {
322- return nil , false , err
335+ return nil , ManifestNoChangeAction , err
323336 }
324337 actual , err := r .spokeDynamicClient .Resource (gvr ).Namespace (manifestObj .GetNamespace ()).Create (
325338 ctx , manifestObj , metav1.CreateOptions {FieldManager : workFieldManagerName })
326339 if err == nil {
327340 klog .V (2 ).InfoS ("successfully created the manifest" , "gvr" , gvr , "manifest" , manifestRef )
328- return actual , true , nil
341+ return actual , ManifestCreatedAction , nil
329342 }
330- return nil , false , err
343+ return nil , ManifestNoChangeAction , err
331344 }
332345
333346 // support resources with generated name
@@ -342,27 +355,27 @@ func (r *ApplyWorkReconciler) applyUnstructured(ctx context.Context, gvr schema.
342355 case apierrors .IsNotFound (err ):
343356 return createFunc ()
344357 case err != nil :
345- return nil , false , err
358+ return nil , ManifestNoChangeAction , err
346359 }
347360
348361 // check if the existing manifest is managed by the work
349362 if ! isManifestManagedByWork (curObj .GetOwnerReferences ()) {
350363 err = fmt .Errorf ("resource is not managed by the work controller" )
351364 klog .ErrorS (err , "skip applying a not managed manifest" , "gvr" , gvr , "obj" , manifestRef )
352- return nil , false , err
365+ return nil , ManifestNoChangeAction , err
353366 }
354367
355368 // We only try to update the object if its spec hash value has changed.
356369 if manifestObj .GetAnnotations ()[manifestHashAnnotation ] != curObj .GetAnnotations ()[manifestHashAnnotation ] {
357370 return r .patchCurrentResource (ctx , gvr , manifestObj , curObj )
358371 }
359372
360- return curObj , false , nil
373+ return curObj , ManifestNoChangeAction , nil
361374}
362375
363376// patchCurrentResource uses three way merge to patch the current resource with the new manifest we get from the work.
364377func (r * ApplyWorkReconciler ) patchCurrentResource (ctx context.Context , gvr schema.GroupVersionResource ,
365- manifestObj , curObj * unstructured.Unstructured ) (* unstructured.Unstructured , bool , error ) {
378+ manifestObj , curObj * unstructured.Unstructured ) (* unstructured.Unstructured , applyAction , error ) {
366379 manifestRef := klog.ObjectRef {
367380 Name : manifestObj .GetName (),
368381 Namespace : manifestObj .GetNamespace (),
@@ -376,28 +389,28 @@ func (r *ApplyWorkReconciler) patchCurrentResource(ctx context.Context, gvr sche
376389 manifestObj .SetOwnerReferences (mergeOwnerReference (curObj .GetOwnerReferences (), manifestObj .GetOwnerReferences ()))
377390 // record the raw manifest with the hash annotation in the manifest
378391 if err := setModifiedConfigurationAnnotation (manifestObj ); err != nil {
379- return nil , false , err
392+ return nil , ManifestNoChangeAction , err
380393 }
381394 // create the three-way merge patch between the current, original and manifest similar to how kubectl apply does
382395 patch , err := threeWayMergePatch (curObj , manifestObj )
383396 if err != nil {
384397 klog .ErrorS (err , "failed to generate the three way patch" , "gvr" , gvr , "manifest" , manifestRef )
385- return nil , false , err
398+ return nil , ManifestNoChangeAction , err
386399 }
387400 data , err := patch .Data (manifestObj )
388401 if err != nil {
389402 klog .ErrorS (err , "failed to generate the three way patch" , "gvr" , gvr , "manifest" , manifestRef )
390- return nil , false , err
403+ return nil , ManifestNoChangeAction , err
391404 }
392405 // Use client side apply the patch to the member cluster
393406 manifestObj , patchErr := r .spokeDynamicClient .Resource (gvr ).Namespace (manifestObj .GetNamespace ()).
394407 Patch (ctx , manifestObj .GetName (), patch .Type (), data , metav1.PatchOptions {FieldManager : workFieldManagerName })
395408 if patchErr != nil {
396409 klog .ErrorS (patchErr , "failed to patch the manifest" , "gvr" , gvr , "manifest" , manifestRef )
397- return nil , false , patchErr
410+ return nil , ManifestNoChangeAction , patchErr
398411 }
399412 klog .V (2 ).InfoS ("manifest patch succeeded" , "gvr" , gvr , "manifest" , manifestRef )
400- return manifestObj , true , nil
413+ return manifestObj , ManifestUpdatedAction , nil
401414}
402415
403416// generateWorkCondition constructs the work condition based on the apply result
@@ -409,7 +422,7 @@ func (r *ApplyWorkReconciler) generateWorkCondition(results []applyResult, work
409422 if result .err != nil {
410423 errs = append (errs , result .err )
411424 }
412- appliedCondition := buildManifestAppliedCondition (result .err , result .updated , result .generation )
425+ appliedCondition := buildManifestAppliedCondition (result .err , result .action , result .generation )
413426 manifestCondition := workv1alpha1.ManifestCondition {
414427 Identifier : result .identifier ,
415428 Conditions : []metav1.Condition {appliedCondition },
@@ -577,7 +590,7 @@ func buildResourceIdentifier(index int, object *unstructured.Unstructured, gvr s
577590 }
578591}
579592
580- func buildManifestAppliedCondition (err error , updated bool , observedGeneration int64 ) metav1.Condition {
593+ func buildManifestAppliedCondition (err error , action applyAction , observedGeneration int64 ) metav1.Condition {
581594 if err != nil {
582595 return metav1.Condition {
583596 Type : ConditionTypeApplied ,
@@ -589,27 +602,17 @@ func buildManifestAppliedCondition(err error, updated bool, observedGeneration i
589602 }
590603 }
591604
592- if updated {
593- return metav1.Condition {
594- Type : ConditionTypeApplied ,
595- Status : metav1 .ConditionTrue ,
596- LastTransitionTime : metav1 .Now (),
597- ObservedGeneration : observedGeneration ,
598- Reason : "appliedManifestUpdated" ,
599- Message : "appliedManifest updated" ,
600- }
601- }
602605 return metav1.Condition {
603606 Type : ConditionTypeApplied ,
604607 Status : metav1 .ConditionTrue ,
605608 LastTransitionTime : metav1 .Now (),
606609 ObservedGeneration : observedGeneration ,
607- Reason : "appliedManifestComplete" ,
608- Message : "Apply manifest complete" ,
610+ Reason : string ( action ) ,
611+ Message : string ( action ) ,
609612 }
610613}
611614
612- // generateWorkAppliedCondition generate appied status condition for work.
615+ // generateWorkAppliedCondition generate applied status condition for work.
613616// If one of the manifests is applied failed on the spoke, the applied status condition of the work is false.
614617func generateWorkAppliedCondition (manifestConditions []workv1alpha1.ManifestCondition , observedGeneration int64 ) metav1.Condition {
615618 for _ , manifestCond := range manifestConditions {
0 commit comments