in backend/operations_scanner.go [505:564]
func (s *OperationsScanner) pollBreakGlassCredentialRevoke(ctx context.Context, op operation) {
var opStatus = arm.ProvisioningStateSucceeded
var opError *arm.CloudErrorBody
// XXX Error handling here is tricky. Since the operation applies to multiple
// Cluster Service objects, we can find a mix of successes and failures.
// And with only a Failed status for each object, it's difficult to make
// intelligent decisions like whether to retry. This is just to say the
// error handling policy here may need revising once Cluster Service
// offers more detail to accompany BreakGlassCredentialStatusFailed.
iterator := s.clusterService.ListBreakGlassCredentials(op.doc.InternalID, "")
loop:
for breakGlassCredential := range iterator.Items(ctx) {
// An expired credential is as good as a revoked credential
// for this operation, regardless of the credential status.
if breakGlassCredential.ExpirationTimestamp().After(time.Now()) {
switch status := breakGlassCredential.Status(); status {
case cmv1.BreakGlassCredentialStatusAwaitingRevocation:
opStatus = arm.ProvisioningStateDeleting
// break alone just breaks out of select.
// Use a label to break out of the loop.
break loop
case cmv1.BreakGlassCredentialStatusRevoked:
// maintain ProvisioningStateSucceeded
case cmv1.BreakGlassCredentialStatusFailed:
// XXX Cluster Service does not provide a reason for the failure,
// so we have no choice but to use a generic error message.
opStatus = arm.ProvisioningStateFailed
opError = &arm.CloudErrorBody{
Code: arm.CloudErrorCodeInternalServerError,
Message: "Failed to revoke cluster credential",
}
// break alone just breaks out of select.
// Use a label to break out of the loop.
break loop
default:
op.logger.Error(fmt.Sprintf("Unhandled BreakGlassCredentialStatus '%s'", status))
}
}
}
err := iterator.GetError()
if err != nil {
op.logger.Error(fmt.Sprintf("Error while paging through Cluster Service query results: %v", err.Error()))
return
}
updated, err := s.dbClient.UpdateOperationDoc(ctx, op.pk, op.id, func(updateDoc *database.OperationDocument) bool {
return updateDoc.UpdateStatus(opStatus, opError)
})
if err != nil {
op.logger.Error(fmt.Sprintf("Failed to update operation status: %v", err))
}
if updated {
op.logger.Info(fmt.Sprintf("Updated status to '%s'", opStatus))
s.maybePostAsyncNotification(ctx, op)
}
}