@@ -189,23 +189,23 @@ func (r *AWSMachineReconciler) reconcileDelete(machineScope *scope.MachineScope,
189
189
// and AWSMachine
190
190
// 3. Issue a delete
191
191
// 4. Scale controller deployment to 1
192
- machineScope .V (2 ).Info ("Unable to locate instance by ID or tags" )
192
+ machineScope .V (2 ).Info ("Unable to locate EC2 instance by ID or tags" )
193
193
r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "NoInstanceFound" , "Unable to find matching EC2 instance" )
194
194
machineScope .AWSMachine .Finalizers = util .Filter (machineScope .AWSMachine .Finalizers , infrav1 .MachineFinalizer )
195
195
return reconcile.Result {}, nil
196
196
}
197
197
198
- machineScope .V (3 ).Info ("Instance found matching deleted AWSMachine" , "instanceID " , instance .ID )
198
+ machineScope .V (3 ).Info ("EC2 instance found matching deleted AWSMachine" , "instance-id " , instance .ID )
199
199
200
200
// Check the instance state. If it's already shutting down or terminated,
201
201
// do nothing. Otherwise attempt to delete it.
202
202
// This decision is based on the ec2-instance-lifecycle graph at
203
203
// https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
204
204
switch instance .State {
205
205
case infrav1 .InstanceStateShuttingDown , infrav1 .InstanceStateTerminated :
206
- machineScope .Info ("Instance is shutting down or already terminated" , "instanceID " , instance .ID )
206
+ machineScope .Info ("EC2 instance is shutting down or already terminated" , "instance-id " , instance .ID )
207
207
default :
208
- machineScope .Info ("Terminating instance" , "instanceID " , instance .ID )
208
+ machineScope .Info ("Terminating EC2 instance" , "instance-id " , instance .ID )
209
209
if err := ec2Service .TerminateInstanceAndWait (instance .ID ); err != nil {
210
210
r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "FailedTerminate" , "Failed to terminate instance %q: %v" , instance .ID , err )
211
211
return reconcile.Result {}, errors .Wrap (err , "failed to terminate instance" )
@@ -231,6 +231,7 @@ func (r *AWSMachineReconciler) reconcileDelete(machineScope *scope.MachineScope,
231
231
}
232
232
}
233
233
234
+ machineScope .Info ("EC2 instance successfully terminated" , "instance-id" , instance .ID )
234
235
r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeNormal , "SuccessfulTerminate" , "Terminated instance %q" , instance .ID )
235
236
}
236
237
@@ -276,6 +277,7 @@ func (r *AWSMachineReconciler) reconcileNormal(ctx context.Context, machineScope
276
277
277
278
// If the AWSMachine doesn't have our finalizer, add it.
278
279
if ! util .Contains (machineScope .AWSMachine .Finalizers , infrav1 .MachineFinalizer ) {
280
+ machineScope .V (1 ).Info ("Adding Cluster API Provider AWS finalizer" )
279
281
machineScope .AWSMachine .Finalizers = append (machineScope .AWSMachine .Finalizers , infrav1 .MachineFinalizer )
280
282
}
281
283
@@ -300,6 +302,7 @@ func (r *AWSMachineReconciler) reconcileNormal(ctx context.Context, machineScope
300
302
301
303
// Set an error message if we couldn't find the instance.
302
304
if instance == nil {
305
+ machineScope .Info ("EC2 instance cannot be found" )
303
306
machineScope .SetErrorReason (capierrors .UpdateMachineError )
304
307
machineScope .SetErrorMessage (errors .New ("EC2 instance cannot be found" ))
305
308
return reconcile.Result {}, nil
@@ -308,28 +311,44 @@ func (r *AWSMachineReconciler) reconcileNormal(ctx context.Context, machineScope
308
311
// TODO(ncdc): move this validation logic into a validating webhook
309
312
if errs := r .validateUpdate (& machineScope .AWSMachine .Spec , instance ); len (errs ) > 0 {
310
313
agg := kerrors .NewAggregate (errs )
314
+ machineScope .Info ("Invalid update" , "failedUpdates" , agg .Error ())
311
315
r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "InvalidUpdate" , "Invalid update: %s" , agg .Error ())
312
316
return reconcile.Result {}, nil
313
317
}
314
318
315
319
// Make sure Spec.ProviderID is always set.
316
320
machineScope .SetProviderID (fmt .Sprintf ("aws:////%s" , instance .ID ))
317
321
318
- // Proceed to reconcile the AWSMachine state.
322
+ // See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html
323
+
324
+ existingInstanceState := machineScope .GetInstanceState ()
319
325
machineScope .SetInstanceState (instance .State )
320
326
321
- // TODO(vincepri): Remove this annotation when clusterctl is no longer relevant.
322
- machineScope .SetAnnotation ("cluster-api-provider-aws" , "true" )
327
+ // Proceed to reconcile the AWSMachine state.
328
+ if existingInstanceState == nil || * existingInstanceState != instance .State {
329
+ machineScope .Info ("EC2 instance state changed" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
330
+ }
323
331
324
332
machineScope .SetAddresses (instance .Addresses )
325
333
326
334
switch instance .State {
335
+ case infrav1 .InstanceStatePending , infrav1 .InstanceStateStopping , infrav1 .InstanceStateStopped :
336
+ machineScope .SetNotReady ()
327
337
case infrav1 .InstanceStateRunning :
328
- machineScope .Info ("Machine instance is running" , "instance-id" , * machineScope .GetInstanceID ())
329
338
machineScope .SetReady ()
330
- case infrav1 .InstanceStatePending :
331
- machineScope .Info ("Machine instance is pending" , "instance-id" , * machineScope .GetInstanceID ())
339
+ case infrav1 .InstanceStateShuttingDown , infrav1 .InstanceStateTerminated :
340
+ machineScope .SetNotReady ()
341
+ machineScope .Info ("Unexpected EC2 instance termination" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
342
+ r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "InstanceUnexpectedTermination" , "Unexpected EC2 instance termination" )
332
343
default :
344
+ machineScope .SetNotReady ()
345
+ machineScope .Info ("EC2 instance state is undefined" , "state" , instance .State , "instance-id" , * machineScope .GetInstanceID ())
346
+ r .Recorder .Eventf (machineScope .AWSMachine , corev1 .EventTypeWarning , "InstanceUnhandledState" , "EC2 instance state is undefined" )
347
+ machineScope .SetErrorReason (capierrors .UpdateMachineError )
348
+ machineScope .SetErrorMessage (errors .Errorf ("EC2 instance state %q is undefined" , instance .State ))
349
+ }
350
+
351
+ if instance .State == infrav1 .InstanceStateTerminated {
333
352
machineScope .SetErrorReason (capierrors .UpdateMachineError )
334
353
machineScope .SetErrorMessage (errors .Errorf ("EC2 instance state %q is unexpected" , instance .State ))
335
354
}
@@ -338,6 +357,9 @@ func (r *AWSMachineReconciler) reconcileNormal(ctx context.Context, machineScope
338
357
return reconcile.Result {}, errors .Errorf ("failed to reconcile LB attachment: %+v" , err )
339
358
}
340
359
360
+ // TODO(vincepri): Remove this annotation when clusterctl is no longer relevant.
361
+ machineScope .SetAnnotation ("cluster-api-provider-aws" , "true" )
362
+
341
363
existingSecurityGroups , err := ec2svc .GetInstanceSecurityGroups (* machineScope .GetInstanceID ())
342
364
if err != nil {
343
365
return reconcile.Result {}, err
@@ -365,10 +387,11 @@ func (r *AWSMachineReconciler) getOrCreate(scope *scope.MachineScope, ec2svc ser
365
387
}
366
388
367
389
if instance == nil {
390
+ scope .Info ("Creating EC2 instance" )
368
391
// Create a new AWSMachine instance if we couldn't find a running instance.
369
392
instance , err = ec2svc .CreateInstance (scope )
370
393
if err != nil {
371
- return nil , errors .Wrapf (err , "failed to create AWSMachine instance" )
394
+ return nil , errors .Wrapf (err , "failed to create EC2 instance" )
372
395
}
373
396
}
374
397
@@ -392,14 +415,21 @@ func (r *AWSMachineReconciler) reconcileLBAttachment(machineScope *scope.Machine
392
415
// validateUpdate checks that no immutable fields have been updated and
393
416
// returns a slice of errors representing attempts to change immutable state.
394
417
func (r * AWSMachineReconciler ) validateUpdate (spec * infrav1.AWSMachineSpec , i * infrav1.Instance ) (errs []error ) {
418
+
419
+ // EC2 instance attributes start disapearing during shutdown and termination, so do not
420
+ // perform more checks
421
+ if i .State == infrav1 .InstanceStateTerminated || i .State == infrav1 .InstanceStateShuttingDown {
422
+ return nil
423
+ }
424
+
395
425
// Instance Type
396
426
if spec .InstanceType != i .Type {
397
- errs = append (errs , errors .Errorf ("instance type cannot be mutated from %q to %q" , i .Type , spec .InstanceType ))
427
+ errs = append (errs , errors .Errorf ("EC2 instance type cannot be mutated from %q to %q" , i .Type , spec .InstanceType ))
398
428
}
399
429
400
430
// IAM Profile
401
431
if spec .IAMInstanceProfile != i .IAMProfile {
402
- errs = append (errs , errors .Errorf ("instance IAM profile cannot be mutated from %q to %q" , i .IAMProfile , spec .IAMInstanceProfile ))
432
+ errs = append (errs , errors .Errorf ("EC2 instance IAM profile cannot be mutated from %q to %q" , i .IAMProfile , spec .IAMInstanceProfile ))
403
433
}
404
434
405
435
// SSH Key Name (also account for default)
0 commit comments