Skip to content

Commit

Permalink
fix(stages/bakery): Fix bake stage, ensure deploymentDetails is added…
Browse files Browse the repository at this point in the history
… to context

- Refactor Check Preconditions stage type for parallel stages
  • Loading branch information
christopherthielen committed Sep 20, 2017
1 parent 50b708e commit ae66a6b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.stereotype.Component

import static com.netflix.spinnaker.orca.pipeline.model.SyntheticStageOwner.STAGE_BEFORE

@Slf4j
Expand All @@ -43,20 +44,35 @@ class BakeStage implements StageDefinitionBuilder, RestartableStage {

@Override
<T extends Execution<T>> void taskGraph(Stage<T> stage, TaskNode.Builder builder) {
builder
.withTask("completeParallel", CompleteParallelBakeTask)
if (isTopLevelStage(stage)) {
builder
.withTask("completeParallel", CompleteParallelBakeTask)
} else {
builder
.withTask("createBake", CreateBakeTask)
.withTask("monitorBake", MonitorBakeTask)
.withTask("completedBake", CompletedBakeTask)
}
}

@Override
@Nonnull
<T extends Execution<T>> List<Stage<T>> parallelStages(
@Nonnull Stage<T> stage
) {
parallelContexts(stage).collect { context ->
newStage(stage.execution, "${type}.parallel", "Bake in ${context.region}", context, stage, STAGE_BEFORE)
if (isTopLevelStage(stage)) {
return parallelContexts(stage).collect { context ->
newStage(stage.execution, type, "Bake in ${context.region}", context, stage, STAGE_BEFORE)
}
} else {
return Collections.emptyList()
}
}

private boolean isTopLevelStage(Stage<?> stage) {
stage.parentStageId == null
}

@CompileDynamic
<T extends Execution<T>> Collection<Map<String, Object>> parallelContexts(Stage<T> stage) {
Set<String> deployRegions = stage.context.region ? [stage.context.region] as Set<String> : []
Expand Down Expand Up @@ -103,23 +119,6 @@ class BakeStage implements StageDefinitionBuilder, RestartableStage {
}
}

@Component
@CompileStatic
static class Parallel implements StageDefinitionBuilder {
@Override
<T extends Execution<T>> void taskGraph(Stage<T> stage, TaskNode.Builder builder) {
builder
.withTask("createBake", CreateBakeTask)
.withTask("monitorBake", MonitorBakeTask)
.withTask("completedBake", CompletedBakeTask)
}

@Override
String getType() {
return "${PIPELINE_CONFIG_TYPE}.parallel"
}
}

@Component
@CompileStatic
static class CompleteParallelBakeTask implements Task {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,40 +84,28 @@ class BakeStageSpec extends Specification {
stage {
id = "1"
type = "bake"
status = ExecutionStatus.RUNNING
}
stage {
parentStageId = "1"
type = "bake"
name = "Bake"
context = ["ami": 1]
status = ExecutionStatus.RUNNING
}
stage {
parentStageId = "1"
type = "bake"
name = "Bake"
context = ["ami": 2]
status = ExecutionStatus.RUNNING
}
stage {
parentStageId = "1"
type = "bake"
name = "Bake"
context = ["ami": 3]
context = [
"region": "us-east-1",
"regions": ["us-east-1", "us-west-2", "eu-east-1"]
]
status = ExecutionStatus.RUNNING
}
}

def bakeStage = pipeline.stageById("1")
def parallelStages = new BakeStage().parallelStages(bakeStage)
parallelStages.eachWithIndex { it, idx -> it.context.ami = idx + 1 }
pipeline.stages.addAll(parallelStages)

when:
def taskResult = new BakeStage.CompleteParallelBakeTask().execute(pipeline.stageById("1"))

then:
taskResult.outputs == [
deploymentDetails: [
["ami": 1], ["ami": 2], ["ami": 3]
]
]
with(taskResult.outputs) {
deploymentDetails[0].ami == 1
deploymentDetails[1].ami == 2
deploymentDetails[2].ami == 3
}
}

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,54 @@ import groovy.transform.CompileStatic
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import static com.netflix.spinnaker.orca.pipeline.model.SyntheticStageOwner.STAGE_BEFORE
import static java.util.Collections.emptyList

@Component
@CompileStatic
class CheckPreconditionsStage implements StageDefinitionBuilder {

static final String PIPELINE_CONFIG_TYPE = "checkPreconditions"

@Nonnull <T extends Execution<T>> List<Stage<T>> parallelStages(
private final List<? extends PreconditionTask> preconditionTasks

@Autowired
CheckPreconditionsStage(List<? extends PreconditionTask> preconditionTasks) {
this.preconditionTasks = preconditionTasks
}

@Override
def <T extends Execution<T>> void taskGraph(Stage<T> stage, TaskNode.Builder builder) {
if (!isTopLevelStage(stage)) {
String preconditionType = stage.context.preconditionType
if (!preconditionType) {
throw new IllegalStateException("no preconditionType specified for stage $stage.id")
}
Task preconditionTask = preconditionTasks.find {
it.preconditionType == preconditionType
}
if (!preconditionTask) {
throw new IllegalStateException("no Precondition implementation for type $preconditionType")
}
builder.withTask("checkPrecondition", preconditionTask.getClass() as Class<? extends Task>)
}
}

@Nonnull
<T extends Execution<T>> List<Stage<T>> parallelStages(
@Nonnull Stage<T> stage) {
parallelContexts(stage).collect { context ->
newStage(stage.execution, "${type}.parallel", "Check precondition (${context.preconditionType})", context, stage, STAGE_BEFORE)
if (isTopLevelStage(stage)) {
return parallelContexts(stage).collect { context ->
newStage(stage.execution, type, "Check precondition (${context.preconditionType})", context, stage, STAGE_BEFORE)
}
} else {
return emptyList()
}
}

private boolean isTopLevelStage(Stage stage) {
return stage.parentStageId == null
}

private <T extends Execution<T>> Collection<Map<String, Object>> parallelContexts(Stage<T> stage) {
stage.resolveStrategyParams()
def baseContext = new HashMap(stage.context)
Expand All @@ -58,34 +92,4 @@ class CheckPreconditionsStage implements StageDefinitionBuilder {
return context
}
}

@Component
static class Parallel implements StageDefinitionBuilder {
private final List<? extends PreconditionTask> preconditionTasks

@Autowired
Parallel(List<? extends PreconditionTask> preconditionTasks) {
this.preconditionTasks = preconditionTasks
}

@Override
def <T extends Execution<T>> void taskGraph(Stage<T> stage, TaskNode.Builder builder) {
String preconditionType = stage.context.preconditionType
if (!preconditionType) {
throw new IllegalStateException("no preconditionType specified for stage $stage.id")
}
Task preconditionTask = preconditionTasks.find {
it.preconditionType == preconditionType
}
if (!preconditionTask) {
throw new IllegalStateException("no Precondition implementation for type $preconditionType")
}
builder.withTask("checkPrecondition", preconditionTask.getClass() as Class<? extends Task>)
}

@Override
String getType() {
return "${PIPELINE_CONFIG_TYPE}.parallel"
}
}
}

0 comments on commit ae66a6b

Please sign in to comment.