in frontend/pkg/frontend/frontend.go [775:881]
func (f *Frontend) ArmResourceActionRevokeCredentials(writer http.ResponseWriter, request *http.Request) {
const operationRequest = database.OperationRequestRevokeCredentials
ctx := request.Context()
logger := LoggerFromContext(ctx)
resourceID, err := ResourceIDFromContext(ctx)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
// Parent resource is the hcpOpenShiftCluster.
resourceID = resourceID.Parent
pk := database.NewPartitionKey(resourceID.SubscriptionID)
resourceDoc, err := f.dbClient.GetResourceDoc(ctx, resourceID)
if err != nil {
logger.Error(err.Error())
if errors.Is(err, database.ErrNotFound) {
arm.WriteResourceNotFoundError(writer, resourceID)
} else {
arm.WriteInternalServerError(writer)
}
return
}
// CheckForProvisioningStateConflict does not log conflict errors
// but does log unexpected errors like database failures.
cloudError := f.CheckForProvisioningStateConflict(ctx, operationRequest, resourceDoc)
if cloudError != nil {
arm.WriteCloudError(writer, cloudError)
return
}
// Credential revocation cannot be requested while another revocation is in progress.
iterator := f.dbClient.ListActiveOperationDocs(pk, &database.DBClientListActiveOperationDocsOptions{
Request: api.Ptr(database.OperationRequestRevokeCredentials),
ExternalID: resourceID,
})
for _, _ = range iterator.Items(ctx) {
writer.Header().Set("Retry-After", strconv.Itoa(10))
arm.WriteConflictError(
writer, resourceID,
"Credentials are already being revoked")
return
}
err = iterator.GetError()
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
err = f.clusterServiceClient.DeleteBreakGlassCredentials(ctx, resourceDoc.InternalID)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
// Just as deleting an ARM resource cancels any other operations on the resource,
// revoking credentials cancels any credential requests in progress.
iterator = f.dbClient.ListActiveOperationDocs(pk, &database.DBClientListActiveOperationDocsOptions{
Request: api.Ptr(database.OperationRequestRequestCredential),
ExternalID: resourceID,
})
for operationID, _ := range iterator.Items(ctx) {
err := f.CancelOperation(ctx, pk, operationID)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
}
err = iterator.GetError()
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
operationDoc := database.NewOperationDocument(operationRequest, resourceID, resourceDoc.InternalID)
operationID, err := f.dbClient.CreateOperationDoc(ctx, operationDoc)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
err = f.ExposeOperation(writer, request, pk, operationID)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(writer)
return
}
writer.WriteHeader(http.StatusAccepted)
}