@@ -15,8 +15,11 @@ package runtime_test
1515
1616import  (
1717	"context" 
18+ 	"errors" 
1819	"testing" 
20+ 	"time" 
1921
22+ 	"github.com/stretchr/testify/assert" 
2023	"github.com/stretchr/testify/require" 
2124	"go.uber.org/zap/zapcore" 
2225	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 
@@ -29,6 +32,7 @@ import (
2932	ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 
3033	ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 
3134	ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 
35+ 	"github.com/aws-controllers-k8s/runtime/pkg/requeue" 
3236	ackrt "github.com/aws-controllers-k8s/runtime/pkg/runtime" 
3337	ackrtcache "github.com/aws-controllers-k8s/runtime/pkg/runtime/cache" 
3438	acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 
@@ -152,6 +156,9 @@ func TestReconcilerUpdate(t *testing.T) {
152156	).Once ()
153157	rd .On ("Delta" , desired , latest ).Return (ackcompare .NewDelta ())
154158
159+ 	rm .On ("LateInitialize" , ctx , latest ).Return (latest , nil )
160+ 	rd .On ("Delta" , latest , latest ).Return (ackcompare .NewDelta ())
161+ 
155162	r , kc  :=  reconcilerMocks (rmf )
156163
157164	kc .On ("Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj )).Return (nil )
@@ -170,6 +177,7 @@ func TestReconcilerUpdate(t *testing.T) {
170177	kc .AssertNotCalled (t , "Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj ))
171178	// Only the HandleReconcilerError wrapper function ever calls patchResourceStatus 
172179	kc .AssertNotCalled (t , "Status" )
180+ 	rm .AssertCalled (t , "LateInitialize" , ctx , latest )
173181}
174182
175183func  TestReconcilerUpdate_PatchMetadataAndSpec_DiffInMetadata (t  * testing.T ) {
@@ -206,6 +214,8 @@ func TestReconcilerUpdate_PatchMetadataAndSpec_DiffInMetadata(t *testing.T) {
206214	rm .On ("Update" , ctx , desired , latest , delta ).Return (
207215		latest , nil ,
208216	)
217+ 	rm .On ("LateInitialize" , ctx , latest ).Return (latest , nil )
218+ 	rd .On ("Delta" , latest , latest ).Return (ackcompare .NewDelta ())
209219
210220	r , kc  :=  reconcilerMocks (rmf )
211221
@@ -219,6 +229,7 @@ func TestReconcilerUpdate_PatchMetadataAndSpec_DiffInMetadata(t *testing.T) {
219229	kc .AssertCalled (t , "Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj ))
220230	// Only the HandleReconcilerError wrapper function ever calls patchResourceStatus 
221231	kc .AssertNotCalled (t , "Status" )
232+ 	rm .AssertCalled (t , "LateInitialize" , ctx , latest )
222233}
223234
224235func  TestReconcilerUpdate_PatchMetadataAndSpec_DiffInSpec (t  * testing.T ) {
@@ -252,6 +263,8 @@ func TestReconcilerUpdate_PatchMetadataAndSpec_DiffInSpec(t *testing.T) {
252263	rm .On ("Update" , ctx , desired , latest , delta ).Return (
253264		latest , nil ,
254265	)
266+ 	rm .On ("LateInitialize" , ctx , latest ).Return (latest , nil )
267+ 	rd .On ("Delta" , latest , latest ).Return (ackcompare .NewDelta ())
255268
256269	r , kc  :=  reconcilerMocks (rmf )
257270
@@ -265,6 +278,7 @@ func TestReconcilerUpdate_PatchMetadataAndSpec_DiffInSpec(t *testing.T) {
265278	kc .AssertCalled (t , "Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj ))
266279	// Only the HandleReconcilerError wrapper function ever calls patchResourceStatus 
267280	kc .AssertNotCalled (t , "Status" )
281+ 	rm .AssertCalled (t , "LateInitialize" , ctx , latest )
268282}
269283
270284func  TestReconcilerHandleReconcilerError_PatchStatus_Latest (t  * testing.T ) {
@@ -326,3 +340,56 @@ func TestReconcilerHandleReconcilerError_NoPatchStatus_NoLatest(t *testing.T) {
326340	// patch the spec/metadata... 
327341	kc .AssertNotCalled (t , "Patch" )
328342}
343+ 
344+ func  TestReconcilerUpdate_ErrorInLateInitialization (t  * testing.T ) {
345+ 	require  :=  require .New (t )
346+ 	assert  :=  assert .New (t )
347+ 
348+ 	ctx  :=  context .TODO ()
349+ 	arn  :=  ackv1alpha1 .AWSResourceName ("mybook-arn" )
350+ 
351+ 	delta  :=  ackcompare .NewDelta ()
352+ 	delta .Add ("Spec.A" , "val1" , "val2" )
353+ 
354+ 	desired , desiredRTObj , _  :=  resourceMocks ()
355+ 
356+ 	ids  :=  & ackmocks.AWSResourceIdentifiers {}
357+ 	ids .On ("ARN" ).Return (& arn )
358+ 
359+ 	latest , latestRTObj , _  :=  resourceMocks ()
360+ 	latest .On ("Identifiers" ).Return (ids )
361+ 	latest .On ("Conditions" ).Return ([]* ackv1alpha1.Condition {})
362+ 
363+ 	rm  :=  & ackmocks.AWSResourceManager {}
364+ 	rm .On ("ReadOne" , ctx , desired ).Return (
365+ 		latest , nil ,
366+ 	)
367+ 	rm .On ("Update" , ctx , desired , latest , delta ).Return (
368+ 		latest , nil ,
369+ 	)
370+ 
371+ 	rmf , rd  :=  managerFactoryMocks (desired , latest , delta )
372+ 	rd .On ("Delta" , desired , latest ).Return (
373+ 		delta ,
374+ 	).Once ()
375+ 	rd .On ("Delta" , desired , latest ).Return (ackcompare .NewDelta ())
376+ 
377+ 	requeueError  :=  requeue .NeededAfter (errors .New ("error from late initialization" ), time .Duration (0 )* time .Second )
378+ 	rm .On ("LateInitialize" , ctx , latest ).Return (latest , requeueError )
379+ 	rd .On ("Delta" , latest , latest ).Return (ackcompare .NewDelta ())
380+ 
381+ 	r , kc  :=  reconcilerMocks (rmf )
382+ 
383+ 	kc .On ("Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj )).Return (nil )
384+ 
385+ 	_ , err  :=  r .Sync (ctx , rm , desired )
386+ 	// Assert the error from late initialization 
387+ 	require .NotNil (err )
388+ 	assert .Equal (requeueError , err )
389+ 	rm .AssertCalled (t , "ReadOne" , ctx , desired )
390+ 	rd .AssertCalled (t , "Delta" , desired , latest )
391+ 	rm .AssertCalled (t , "Update" , ctx , desired , latest , delta )
392+ 	// No difference in desired, latest metadata and spec 
393+ 	kc .AssertNotCalled (t , "Patch" , ctx , latestRTObj , client .MergeFrom (desiredRTObj ))
394+ 	rm .AssertCalled (t , "LateInitialize" , ctx , latest )
395+ }
0 commit comments