@@ -57,6 +57,10 @@ const (
57
57
// resource if the CARM cache is not synced yet, or if the roleARN is not
58
58
// available.
59
59
roleARNNotAvailableRequeueDelay = 15 * time .Second
60
+ // adoptOrCreate is an annotation field that decides whether to create the
61
+ // resource if it doesn't exist, or adopt the resource if it exists.
62
+ // value comes from getAdoptionPolicy
63
+ // adoptOrCreate = "adopt-or-create"
60
64
)
61
65
62
66
// reconciler describes a generic reconciler within ACK.
@@ -298,6 +302,70 @@ func (r *resourceReconciler) handleCacheError(
298
302
return r .HandleReconcileError (ctx , desired , latest , requeue .NeededAfter (err , roleARNNotAvailableRequeueDelay ))
299
303
}
300
304
305
+ func (r * resourceReconciler ) handleAdoption (
306
+ ctx context.Context ,
307
+ rm acktypes.AWSResourceManager ,
308
+ desired acktypes.AWSResource ,
309
+ rlog acktypes.Logger ,
310
+ ) (acktypes.AWSResource , error ) {
311
+ // If the resource is being adopted by force, we need to access
312
+ // the required field passed by annotation and attempt a read.
313
+
314
+ rlog .Info ("Adopting Resource" )
315
+ extractedFields , err := ExtractAdoptionFields (desired )
316
+ if err != nil {
317
+ return desired , ackerr .NewTerminalError (err )
318
+ }
319
+ if len (extractedFields ) == 0 {
320
+ // TODO(michaelhtm) Here we need to figure out if we want to have an
321
+ // error or not. should we consider accepting values from Spec?
322
+ // And then we can let the ReadOne figure out if we have missing
323
+ // required fields for a Read
324
+ return nil , fmt .Errorf ("failed extracting fields from annotation" )
325
+ }
326
+ resolved := desired .DeepCopy ()
327
+ err = resolved .PopulateResourceFromAnnotation (extractedFields )
328
+ if err != nil {
329
+ return nil , err
330
+ }
331
+
332
+ rlog .Enter ("rm.EnsureTags" )
333
+ err = rm .EnsureTags (ctx , resolved , r .sc .GetMetadata ())
334
+ rlog .Exit ("rm.EnsureTags" , err )
335
+ if err != nil {
336
+ return resolved , err
337
+ }
338
+ rlog .Enter ("rm.ReadOne" )
339
+ latest , err := rm .ReadOne (ctx , resolved )
340
+ if err != nil {
341
+ return latest , err
342
+ }
343
+
344
+ if err = r .setResourceManaged (ctx , rm , latest ); err != nil {
345
+ return latest , err
346
+ }
347
+
348
+ // Ensure tags again after adding the finalizer and patching the
349
+ // resource. Patching desired resource omits the controller tags
350
+ // because they are not persisted in etcd. So we again ensure
351
+ // that tags are present before performing the create operation.
352
+ rlog .Enter ("rm.EnsureTags" )
353
+ err = rm .EnsureTags (ctx , latest , r .sc .GetMetadata ())
354
+ rlog .Exit ("rm.EnsureTags" , err )
355
+ if err != nil {
356
+ return latest , err
357
+ }
358
+ r .rd .MarkAdopted (latest )
359
+ rlog .WithValues ("is_adopted" , "true" )
360
+ latest , err = r .patchResourceMetadataAndSpec (ctx , rm , desired , latest )
361
+ if err != nil {
362
+ return latest , err
363
+ }
364
+
365
+ rlog .Info ("Resource Adopted" )
366
+ return latest , nil
367
+ }
368
+
301
369
// reconcile either cleans up a deleted resource or ensures that the supplied
302
370
// AWSResource's backing API resource matches the supplied desired state.
303
371
//
@@ -360,13 +428,30 @@ func (r *resourceReconciler) Sync(
360
428
isAdopted := IsAdopted (desired )
361
429
rlog .WithValues ("is_adopted" , isAdopted )
362
430
431
+ if r .cfg .FeatureGates .IsEnabled (featuregate .ResourceAdoption ) {
432
+ if NeedAdoption (desired ) && ! r .rd .IsManaged (desired ) {
433
+ latest , err := r .handleAdoption (ctx , rm , desired , rlog )
434
+
435
+ if err != nil {
436
+ // If we get an error, we want to return here
437
+ // TODO(michaelhtm): Change the handling of
438
+ // the error to allow Adopt or Create here
439
+ // when supported
440
+ return latest , err
441
+ }
442
+ return latest , nil
443
+ }
444
+ }
445
+
363
446
if r .cfg .FeatureGates .IsEnabled (featuregate .ReadOnlyResources ) {
364
447
isReadOnly := IsReadOnly (desired )
365
448
rlog .WithValues ("is_read_only" , isReadOnly )
366
449
367
450
// NOTE(a-hilaly): When the time comes to support adopting resources
368
451
// using annotations, we will need to think a little bit more about
369
452
// the case where a user, wants to adopt a resource as read-only.
453
+ //
454
+ // NOTE(michaelhtm): Done, tnx :)
370
455
371
456
// If the resource is read-only, we enter a different code path where we
372
457
// only read the resource and patch the metadata and spec.
0 commit comments