Skip to content

Commit

Permalink
fix(error handling): add endpoint to mark executions failed (#3126)
Browse files Browse the repository at this point in the history
* fix(error handling): add endpoint to mark executions failed

When an execution fails in to start (e.g. before the execution is persisted) in `orca`,
`orca` will mark and store the execution as failed.
Since the artifact resolution is being moved to `echo`, `echo` needs the same ability
to mark executions as failed - otherwise any failures during artifact resolution in
`echo` will turn into silent failures for the user (if no execution is persisted then
the UI can't show any failures associated with that execution).

This change adds an endpoint that `echo` can call to mark the execution failed
  • Loading branch information
marchello2000 committed Sep 4, 2019
1 parent 2a39bb8 commit 0faa664
Showing 1 changed file with 43 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.netflix.spinnaker.fiat.model.UserPermission
import com.netflix.spinnaker.fiat.model.resources.Role
import com.netflix.spinnaker.fiat.shared.FiatService
import com.netflix.spinnaker.fiat.shared.FiatStatus
import com.netflix.spinnaker.kork.exceptions.SpinnakerException
import com.netflix.spinnaker.kork.web.exceptions.InvalidRequestException
import com.netflix.spinnaker.kork.web.exceptions.ValidationException
import com.netflix.spinnaker.orca.clouddriver.service.JobService
Expand Down Expand Up @@ -123,6 +124,19 @@ class OperationsController {
return planPipeline(pipelineConfig, resolveArtifacts)
}

/**
* Used by echo to mark an execution failure if it fails to materialize the pipeline
* (e.g. because the artifacts couldn't be resolved)
*
* @param pipeline pipeline json
*/
@RequestMapping(value = '/fail', method = RequestMethod.POST)
void failPipeline(@RequestBody Map pipeline) {
String errorMessage = pipeline.remove("errorMessage")

recordPipelineFailure(pipeline, errorMessage)
}

private Map buildPipelineConfig(String pipelineConfigId, Map trigger) {
if (front50Service == null) {
throw new UnsupportedOperationException("Front50 is not enabled, no way to retrieve pipeline configs. Fix this by setting front50.enabled: true")
Expand Down Expand Up @@ -179,6 +193,35 @@ class OperationsController {
}
}

private void recordPipelineFailure(Map pipeline, String errorMessage) {
// While we are recording the failure for this execution, we still want to
// parse/validate/realize the pipeline as best as we can. This way the UI
// can visualize the pipeline as best as possible.
// Additionally, if there are any failures we will record all errors for the
// user to be aware of and address
Exception pipelineError = null
try {
pipeline = parseAndValidatePipeline(pipeline)
} catch (Exception e) {
pipelineError = e
}

def augmentedContext = [
trigger: pipeline.trigger,
templateVariables: pipeline.templateVariables ?: [:]
]
def processedPipeline = contextParameterProcessor.process(pipeline, augmentedContext, false)
processedPipeline.trigger = objectMapper.convertValue(processedPipeline.trigger, Trigger)

if (pipelineError != null) {
pipelineError = new SpinnakerException(errorMessage, pipelineError)
} else {
pipelineError = new SpinnakerException(errorMessage)
}

markPipelineFailed(processedPipeline, pipelineError)
}

public Map parseAndValidatePipeline(Map pipeline) {
return parseAndValidatePipeline(pipeline, true)
}
Expand Down

0 comments on commit 0faa664

Please sign in to comment.