diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionRunner.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/ExecutionRunner.java similarity index 92% rename from orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionRunner.java rename to orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/ExecutionRunner.java index b6b2a7a76c3..ced9e4e10f9 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionRunner.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/ExecutionRunner.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.netflix.spinnaker.orca.pipeline; +package com.netflix.spinnaker.orca.api.pipeline; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; import javax.annotation.Nonnull; import javax.annotation.Nullable; +/** The touch point into running a {@link PipelineExecution}. */ public interface ExecutionRunner { void start(@Nonnull PipelineExecution execution); diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/ExecutionEngineVersion.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/ExecutionEngineVersion.java new file mode 100644 index 00000000000..11f53790818 --- /dev/null +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/ExecutionEngineVersion.java @@ -0,0 +1,16 @@ +package com.netflix.spinnaker.orca.api.pipeline.models; + +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Signals that the annotated element supports a specific {@link ExecutionEngine} version. */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Documented +public @interface ExecutionEngineVersion { + ExecutionEngine value(); +} diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/PipelineExecution.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/PipelineExecution.java index 38e81a3ac75..e2a67973be1 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/PipelineExecution.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/pipeline/models/PipelineExecution.java @@ -89,6 +89,10 @@ public interface PipelineExecution { void setStatus(ExecutionStatus status); + ExecutionEngine getExecutionEngine(); + + void setExecutionEngine(ExecutionEngine executionEngine); + AuthenticationDetails getAuthentication(); void setAuthentication(AuthenticationDetails authentication); @@ -252,4 +256,21 @@ public void setVersion(@Nonnull String version) { this.version = version; } } + + ExecutionEngine DEFAULT_EXECUTION_ENGINE = ExecutionEngine.v3; + + enum ExecutionEngine { + /** + * v2 is obsolete, but it is here as a failsafe in case it is present in a pipeline + * configuration and needs to be deserialized. If v2 is specified, the default execution engine + * (v3) will be used instead. + */ + v2, + + /** v3 execution engine is the keiko execution engine. */ + v3, + + /** v4 execution engine does not yet exist, early prototyping is underway. */ + v4 + } } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/config/OrcaConfiguration.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/config/OrcaConfiguration.java index 183956c0253..f707f5558b7 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/config/OrcaConfiguration.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/config/OrcaConfiguration.java @@ -28,6 +28,7 @@ import com.netflix.spinnaker.orca.DynamicStageResolver; import com.netflix.spinnaker.orca.StageResolver; import com.netflix.spinnaker.orca.TaskResolver; +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner; import com.netflix.spinnaker.orca.api.pipeline.Task; import com.netflix.spinnaker.orca.api.pipeline.graph.StageDefinitionBuilder; import com.netflix.spinnaker.orca.commands.ForceExecutionCancellationCommand; @@ -40,7 +41,7 @@ import com.netflix.spinnaker.orca.listeners.*; import com.netflix.spinnaker.orca.pipeline.CompoundExecutionOperator; import com.netflix.spinnaker.orca.pipeline.DefaultStageDefinitionBuilderFactory; -import com.netflix.spinnaker.orca.pipeline.ExecutionRunner; +import com.netflix.spinnaker.orca.pipeline.ExecutionEngineRunner; import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilderFactory; import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository; import com.netflix.spinnaker.orca.pipeline.util.ContextParameterProcessor; @@ -236,9 +237,14 @@ public ForceExecutionCancellationCommand forceExecutionCancellationCommand( return new ForceExecutionCancellationCommand(executionRepository, clock); } + @Bean + public ExecutionEngineRunner executionEngineRunner(List executionRunners) { + return new ExecutionEngineRunner(executionRunners); + } + @Bean public CompoundExecutionOperator compoundExecutionOperator( - ExecutionRepository repository, ExecutionRunner runner, RetrySupport retrySupport) { + ExecutionRepository repository, ExecutionEngineRunner runner, RetrySupport retrySupport) { return new CompoundExecutionOperator(repository, runner, retrySupport); } } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperator.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperator.java index 569baec3a0e..0d311613032 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperator.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperator.java @@ -17,6 +17,7 @@ package com.netflix.spinnaker.orca.pipeline; import com.netflix.spinnaker.kork.core.RetrySupport; +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution; diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunner.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunner.java new file mode 100644 index 00000000000..c226f371f9a --- /dev/null +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunner.java @@ -0,0 +1,75 @@ +package com.netflix.spinnaker.orca.pipeline; + +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.DEFAULT_EXECUTION_ENGINE; + +import com.netflix.spinnaker.kork.annotations.VisibleForTesting; +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner; +import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionEngineVersion; +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine; +import java.util.List; +import javax.annotation.Nonnull; +import org.jetbrains.annotations.Nullable; + +/** + * Executes the {@link PipelineExecution} based on the specified {@link ExecutionEngine}. The {@link + * ExecutionEngine} is expected to be specified via the {@link ExecutionEngineVersion} annotation. + */ +public class ExecutionEngineRunner implements ExecutionRunner { + + private final List executionRunners; + + public ExecutionEngineRunner(List executionRunners) { + this.executionRunners = executionRunners; + } + + @Override + public void start(@Nonnull PipelineExecution execution) { + executionRunner(execution.getExecutionEngine()).start(execution); + } + + @Override + public void restart(@Nonnull PipelineExecution execution, @Nonnull String stageId) { + executionRunner(execution.getExecutionEngine()).restart(execution, stageId); + } + + @Override + public void reschedule(@Nonnull PipelineExecution execution) { + executionRunner(execution.getExecutionEngine()).reschedule(execution); + } + + @Override + public void unpause(@Nonnull PipelineExecution execution) { + executionRunner(execution.getExecutionEngine()).unpause(execution); + } + + @Override + public void cancel( + @Nonnull PipelineExecution execution, @Nonnull String user, @Nullable String reason) { + executionRunner(execution.getExecutionEngine()).cancel(execution, user, reason); + } + + @VisibleForTesting + protected ExecutionRunner executionRunner(ExecutionEngine executionEngine) { + return executionRunners.stream() + .filter(it -> it.getClass().isAnnotationPresent(ExecutionEngineVersion.class)) + .filter( + it -> + it.getClass().getAnnotation(ExecutionEngineVersion.class).value() + == executionEngine) + .findFirst() + .orElseGet( + () -> + executionRunners.stream() + .filter(it -> it.getClass().isAnnotationPresent(ExecutionEngineVersion.class)) + .filter( + it -> + it.getClass().getAnnotation(ExecutionEngineVersion.class).value() + == DEFAULT_EXECUTION_ENGINE) + .findFirst() + .orElseThrow( + () -> + new UnsupportedOperationException( + "No execution engine runner found!"))); + } +} diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionLauncher.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionLauncher.java index a8eb04d51b6..ed57b438cc0 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionLauncher.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ExecutionLauncher.java @@ -26,9 +26,11 @@ import com.netflix.spectator.api.Registry; import com.netflix.spinnaker.kork.exceptions.UserException; import com.netflix.spinnaker.kork.web.exceptions.ValidationException; +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus; import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine; import com.netflix.spinnaker.orca.api.pipeline.models.Trigger; import com.netflix.spinnaker.orca.events.BeforeInitialExecutionPersist; import com.netflix.spinnaker.orca.pipeline.model.PipelineBuilder; @@ -67,7 +69,7 @@ public class ExecutionLauncher { public ExecutionLauncher( ObjectMapper objectMapper, ExecutionRepository executionRepository, - ExecutionRunner executionRunner, + ExecutionEngineRunner executionRunner, Clock clock, ApplicationEventPublisher applicationEventPublisher, Optional pipelineValidator, @@ -215,6 +217,7 @@ private PipelineExecution parsePipeline(String configJson) throws IOException { .withStages((List>) config.get("stages")) .withLimitConcurrent(getBoolean(config, "limitConcurrent")) .withKeepWaitingPipelines(getBoolean(config, "keepWaitingPipelines")) + .withExecutionEngine(getEnum(config, "executionEngine", ExecutionEngine.class)) .withNotifications((List>) config.get("notifications")) .withInitialConfig((Map) config.get("initialConfig")) .withOrigin(getString(config, "origin")) @@ -240,6 +243,9 @@ private PipelineExecution parseOrchestration(String configJson) throws IOExcepti if (config.containsKey("description")) { orchestration.setDescription(getString(config, "description")); } + if (config.containsKey("executionEngine")) { + orchestration.setExecutionEngine(getEnum(config, "executionEngine", ExecutionEngine.class)); + } for (Map context : getList(config, "stages")) { String type = context.remove("type").toString(); @@ -299,6 +305,14 @@ private final List> getList(Map map, String key) private final > E getEnum(Map map, String key, Class type) { String value = (String) map.get(key); - return value != null ? Enum.valueOf(type, value) : null; + if (value != null) { + try { + return Enum.valueOf(type, value); + } catch (IllegalArgumentException e) { + log.error(e.getMessage()); + return null; + } + } + return null; } } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineBuilder.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineBuilder.java index ccb3a9d2aaa..f859d87bcdd 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineBuilder.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineBuilder.java @@ -16,8 +16,11 @@ package com.netflix.spinnaker.orca.pipeline.model; +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.DEFAULT_EXECUTION_ENGINE; + import com.google.common.base.Strings; import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution; +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine; import com.netflix.spinnaker.orca.api.pipeline.models.Trigger; import java.util.Arrays; import java.util.HashMap; @@ -117,6 +120,12 @@ public PipelineBuilder withKeepWaitingPipelines(boolean waiting) { return this; } + public PipelineBuilder withExecutionEngine(ExecutionEngine executionEngine) { + pipeline.setExecutionEngine( + executionEngine != null ? executionEngine : DEFAULT_EXECUTION_ENGINE); + return this; + } + public PipelineBuilder withOrigin(String origin) { pipeline.setOrigin(origin); return this; diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineExecutionImpl.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineExecutionImpl.java index bacc5e5e7ae..79783c8edc6 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineExecutionImpl.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/model/PipelineExecutionImpl.java @@ -237,6 +237,18 @@ public void setStatus(@Nonnull ExecutionStatus status) { this.status = status; } + private ExecutionEngine executionEngine = DEFAULT_EXECUTION_ENGINE; + + @Override + public ExecutionEngine getExecutionEngine() { + return executionEngine; + } + + @Override + public void setExecutionEngine(ExecutionEngine executionEngine) { + this.executionEngine = executionEngine; + } + private AuthenticationDetails authentication; public @Nullable AuthenticationDetails getAuthentication() { diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperatorSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperatorSpec.groovy index 21338df4d85..636fc5d7adf 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperatorSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/CompoundExecutionOperatorSpec.groovy @@ -17,6 +17,7 @@ package com.netflix.spinnaker.orca.pipeline import com.netflix.spinnaker.kork.core.RetrySupport +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunnerSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunnerSpec.groovy new file mode 100644 index 00000000000..8bb5ff29938 --- /dev/null +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ExecutionEngineRunnerSpec.groovy @@ -0,0 +1,88 @@ +package com.netflix.spinnaker.orca.pipeline + +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner +import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionEngineVersion +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution +import org.jetbrains.annotations.Nullable +import spock.lang.Specification +import spock.lang.Unroll + +import javax.annotation.Nonnull + +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v2 +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v3 +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v4 + +class ExecutionEngineRunnerSpec extends Specification { + + @Unroll + def "Finds the correct execution runner based on the execution engine"() { + given: + ExecutionEngineRunner executionEngineRunner = new ExecutionEngineRunner([new V3EngineRunner(), new V4EngineRunner()]) + + when: + def runner = executionEngineRunner.executionRunner(supplied) + + then: + runner.class == expected + + where: + supplied | expected + v2 | V3EngineRunner.class //v2 is obsolete, use v3 engine + v3 | V3EngineRunner.class + v4 | V4EngineRunner.class + } + + @Unroll + def "Throws UnsupportedOperationException when execution engine runner can not be found"() { + given: + ExecutionEngineRunner executionEngineRunner = new ExecutionEngineRunner([new UnsupportedRunner()]) + + when: + executionEngineRunner.executionRunner(v3) + + then: + thrown(UnsupportedOperationException) + } +} + +@ExecutionEngineVersion(v3) +class V3EngineRunner implements ExecutionRunner { + @Override + void start(@Nonnull PipelineExecution execution) {} + @Override + void restart(@Nonnull PipelineExecution execution, @Nonnull String stageId) {} + @Override + void reschedule(@Nonnull PipelineExecution execution) {} + @Override + void unpause(@Nonnull PipelineExecution execution) {} + @Override + void cancel(@Nonnull PipelineExecution execution, @Nonnull String user, @Nullable String reason) {} +} + +@ExecutionEngineVersion(v4) +class V4EngineRunner implements ExecutionRunner { + @Override + void start(@Nonnull PipelineExecution execution) {} + @Override + void restart(@Nonnull PipelineExecution execution, @Nonnull String stageId) {} + @Override + void reschedule(@Nonnull PipelineExecution execution) {} + @Override + void unpause(@Nonnull PipelineExecution execution) {} + @Override + void cancel(@Nonnull PipelineExecution execution, @Nonnull String user, @Nullable String reason) {} +} + +class UnsupportedRunner implements ExecutionRunner { + @Override + void start(@Nonnull PipelineExecution execution) {} + @Override + void restart(@Nonnull PipelineExecution execution, @Nonnull String stageId) {} + @Override + void reschedule(@Nonnull PipelineExecution execution) {} + @Override + void unpause(@Nonnull PipelineExecution execution) {} + @Override + void cancel(@Nonnull PipelineExecution execution, @Nonnull String user, @Nullable String reason) {} +} diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/PipelineExecutionLauncherSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/PipelineExecutionLauncherSpec.groovy index e91de78c31e..c8a026b7254 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/PipelineExecutionLauncherSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/PipelineExecutionLauncherSpec.groovy @@ -17,8 +17,13 @@ package com.netflix.spinnaker.orca.pipeline import com.netflix.spinnaker.orca.api.pipeline.graph.StageDefinitionBuilder +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.DEFAULT_EXECUTION_ENGINE +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v2 +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v3 +import static com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v4 import com.netflix.spinnaker.orca.events.BeforeInitialExecutionPersist import org.springframework.context.ApplicationEventPublisher +import spock.lang.Unroll import javax.annotation.Nonnull import java.time.Clock @@ -34,8 +39,9 @@ import static com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType.PIPEL class PipelineExecutionLauncherSpec extends Specification { - @Shared def objectMapper = new ObjectMapper() - def executionRunner = Mock(ExecutionRunner) + @Shared + def objectMapper = new ObjectMapper() + def executionRunner = Mock(ExecutionEngineRunner) def executionRepository = Mock(ExecutionRepository) def pipelineValidator = Stub(PipelineValidator) def applicationEventPublisher = Mock(ApplicationEventPublisher) @@ -119,4 +125,29 @@ class PipelineExecutionLauncherSpec extends Specification { config = [id: "whatever", stages: []] json = objectMapper.writeValueAsString(config) } + + @Unroll + def "sets executionEngine correctly"() { + given: + @Subject def launcher = create() + + when: + launcher.start(PIPELINE, json) + + then: + 1 * executionRepository.store({ + it.executionEngine == expected + }) + + where: + supplied | expected + [executionEngine: "v2"] | v2 + [executionEngine: "v3"] | v3 + [executionEngine: "v4"] | v4 + [executionEngine: null] | DEFAULT_EXECUTION_ENGINE + [:] | DEFAULT_EXECUTION_ENGINE + + config = [id: "1", stages: []] + supplied + json = objectMapper.writeValueAsString(config) + } } diff --git a/orca-interlink/src/test/groovy/com/netflix/spinnaker/orca/interlink/InterlinkSpec.groovy b/orca-interlink/src/test/groovy/com/netflix/spinnaker/orca/interlink/InterlinkSpec.groovy index 6cd5efffdb2..86ec7ae8817 100644 --- a/orca-interlink/src/test/groovy/com/netflix/spinnaker/orca/interlink/InterlinkSpec.groovy +++ b/orca-interlink/src/test/groovy/com/netflix/spinnaker/orca/interlink/InterlinkSpec.groovy @@ -18,11 +18,11 @@ package com.netflix.spinnaker.orca.interlink import com.fasterxml.jackson.databind.ObjectMapper import com.netflix.spinnaker.kork.core.RetrySupport +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution import com.netflix.spinnaker.orca.interlink.events.* import com.netflix.spinnaker.orca.pipeline.CompoundExecutionOperator -import com.netflix.spinnaker.orca.pipeline.ExecutionRunner import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository import spock.lang.Shared diff --git a/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/V1SchemaExecutionGenerator.java b/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/V1SchemaExecutionGenerator.java index c3822144d76..f8cc5ba4389 100644 --- a/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/V1SchemaExecutionGenerator.java +++ b/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/V1SchemaExecutionGenerator.java @@ -52,6 +52,10 @@ public Map generate( "name", Optional.ofNullable(configuration.getPipeline().getName()).orElse("Unnamed Execution")); + if (configuration.getPipeline().getExecutionEngine() != null) { + pipeline.put("executionEngine", configuration.getPipeline().getExecutionEngine()); + } + Configuration c = template.getConfiguration(); if (c.getConcurrentExecutions().isEmpty()) { pipeline.put("limitConcurrent", request.isLimitConcurrent()); diff --git a/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/model/TemplateConfiguration.java b/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/model/TemplateConfiguration.java index 274deb5ebbd..b9b0944b04a 100644 --- a/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/model/TemplateConfiguration.java +++ b/orca-pipelinetemplate/src/main/java/com/netflix/spinnaker/orca/pipelinetemplate/v1schema/model/TemplateConfiguration.java @@ -40,6 +40,7 @@ public static class PipelineDefinition { private String application; private String pipelineConfigId; + private String executionEngine; private String name; private TemplateSource template; private Map variables = new HashMap<>(); @@ -83,6 +84,10 @@ public Map getVariables() { public void setVariables(Map variables) { this.variables = variables; } + + public String getExecutionEngine() { + return executionEngine; + } } @NoArgsConstructor diff --git a/orca-queue/src/main/kotlin/com/netflix/spinnaker/orca/q/QueueExecutionRunner.kt b/orca-queue/src/main/kotlin/com/netflix/spinnaker/orca/q/QueueExecutionRunner.kt index c53c176f36e..eb39b21a62b 100644 --- a/orca-queue/src/main/kotlin/com/netflix/spinnaker/orca/q/QueueExecutionRunner.kt +++ b/orca-queue/src/main/kotlin/com/netflix/spinnaker/orca/q/QueueExecutionRunner.kt @@ -16,13 +16,16 @@ package com.netflix.spinnaker.orca.q +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner +import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionEngineVersion import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution -import com.netflix.spinnaker.orca.pipeline.ExecutionRunner +import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution.ExecutionEngine.v3 import com.netflix.spinnaker.q.Queue import com.netflix.spinnaker.security.AuthenticatedRequest import org.springframework.stereotype.Component @Component +@ExecutionEngineVersion(v3) class QueueExecutionRunner( private val queue: Queue ) : ExecutionRunner { diff --git a/orca-web/src/main/groovy/com/netflix/spinnaker/orca/controllers/TaskController.groovy b/orca-web/src/main/groovy/com/netflix/spinnaker/orca/controllers/TaskController.groovy index 8ec6e53f4c5..01bcfa3b775 100644 --- a/orca-web/src/main/groovy/com/netflix/spinnaker/orca/controllers/TaskController.groovy +++ b/orca-web/src/main/groovy/com/netflix/spinnaker/orca/controllers/TaskController.groovy @@ -20,12 +20,13 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.google.common.annotations.VisibleForTesting import com.netflix.spectator.api.Registry import com.netflix.spinnaker.kork.web.exceptions.NotFoundException +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner import com.netflix.spinnaker.orca.api.pipeline.graph.StageDefinitionBuilder import com.netflix.spinnaker.orca.api.pipeline.models.* import com.netflix.spinnaker.orca.front50.Front50Service import com.netflix.spinnaker.orca.model.OrchestrationViewModel import com.netflix.spinnaker.orca.pipeline.CompoundExecutionOperator -import com.netflix.spinnaker.orca.pipeline.ExecutionRunner +import com.netflix.spinnaker.orca.pipeline.ExecutionEngineRunner import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilderFactory import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionNotFoundException import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository @@ -67,7 +68,7 @@ class TaskController { ExecutionRepository executionRepository @Autowired - ExecutionRunner executionRunner + ExecutionEngineRunner executionRunner @Autowired CompoundExecutionOperator executionOperator; diff --git a/orca-web/src/test/groovy/com/netflix/spinnaker/orca/controllers/TaskControllerSpec.groovy b/orca-web/src/test/groovy/com/netflix/spinnaker/orca/controllers/TaskControllerSpec.groovy index 8dee3526af4..b1e439de212 100644 --- a/orca-web/src/test/groovy/com/netflix/spinnaker/orca/controllers/TaskControllerSpec.groovy +++ b/orca-web/src/test/groovy/com/netflix/spinnaker/orca/controllers/TaskControllerSpec.groovy @@ -20,12 +20,13 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.google.common.collect.Collections2 import com.netflix.spectator.api.NoopRegistry import com.netflix.spinnaker.kork.artifacts.model.Artifact +import com.netflix.spinnaker.orca.api.pipeline.ExecutionRunner import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType import com.netflix.spinnaker.orca.front50.Front50Service import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper import com.netflix.spinnaker.orca.pipeline.CompoundExecutionOperator -import com.netflix.spinnaker.orca.pipeline.ExecutionRunner +import com.netflix.spinnaker.orca.pipeline.ExecutionEngineRunner import com.netflix.spinnaker.orca.pipeline.model.* import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository import com.netflix.spinnaker.orca.pipeline.util.ContextParameterProcessor @@ -54,7 +55,7 @@ class TaskControllerSpec extends Specification { MockMvc mockMvc def executionRepository = Mock(ExecutionRepository) def front50Service = Mock(Front50Service) - def executionRunner = Mock(ExecutionRunner) + def executionRunner = Mock(ExecutionEngineRunner) def executionOperator = Mock(CompoundExecutionOperator) def mapper = OrcaObjectMapper.getInstance() def registry = new NoopRegistry()