From cd4a3c2a009d1124a2bc0a3bb7d2c275360c7afe Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Wed, 7 Aug 2019 17:57:56 -0700 Subject: [PATCH 01/18] feat(plugins): start of API for new stages --- .../com/netflix/spinnaker/orca/api/Stage.java | 8 ++++++ .../spinnaker/orca/api/StageInput.java | 17 ++++++++++++ .../spinnaker/orca/api/StageOutput.java | 27 +++++++++++++++++++ .../spinnaker/orca/api/StageStatus.java | 11 ++++++++ 4 files changed, 63 insertions(+) create mode 100644 orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java create mode 100644 orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java create mode 100644 orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java create mode 100644 orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java new file mode 100644 index 0000000000..a04bf17723 --- /dev/null +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java @@ -0,0 +1,8 @@ +package com.netflix.spinnaker.orca.api; + +import com.google.common.annotations.Beta; + +@Beta +public interface Stage { + StageOutput execute(StageInput stageInput); +} diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java new file mode 100644 index 0000000000..d9cdcf4287 --- /dev/null +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java @@ -0,0 +1,17 @@ +package com.netflix.spinnaker.orca.api; + +import com.google.common.annotations.Beta; +import java.util.Map; + +@Beta +public class StageInput { + private Map input; + + public void setInput(Map input) { + this.input = input; + } + + public Map getInput() { + return this.input; + } +} diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java new file mode 100644 index 0000000000..872a491efb --- /dev/null +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java @@ -0,0 +1,27 @@ +package com.netflix.spinnaker.orca.api; + +import com.google.common.annotations.Beta; +import java.util.Map; + +@Beta +public class StageOutput { + private StageStatus status; + + public void setStatus(StageStatus status) { + this.status = status; + } + + public StageStatus getStatus() { + return this.status; + } + + private Map outputs; + + public void setOutputs(Map outputs) { + this.outputs = outputs; + } + + public Map getOutputs() { + return this.outputs; + } +} diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java new file mode 100644 index 0000000000..22cc649535 --- /dev/null +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java @@ -0,0 +1,11 @@ +package com.netflix.spinnaker.orca.api; + +import com.google.common.annotations.Beta; + +@Beta +public enum StageStatus { + TERMINAL, + RUNNING, + COMPLETED, + NOT_STARTED +} From 53209545115a3dadd0c73f7b1e297b273e9b9e95 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 8 Aug 2019 14:45:47 -0700 Subject: [PATCH 02/18] feat(plugins): scaffolding setup for plugins --- orca-api/orca-api.gradle | 29 +++++++++++++++++++ orca-core/orca-core.gradle | 1 + .../netflix/spinnaker/orca/StageResolver.java | 12 +++++++- .../orca/config/OrcaConfiguration.java | 6 ++-- orca-web/orca-web.gradle | 1 + settings.gradle | 1 + 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 orca-api/orca-api.gradle diff --git a/orca-api/orca-api.gradle b/orca-api/orca-api.gradle new file mode 100644 index 0000000000..8ac8baa879 --- /dev/null +++ b/orca-api/orca-api.gradle @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply from: "$rootDir/gradle/kotlin.gradle" +apply from: "$rootDir/gradle/spock.gradle" + +test { + useJUnitPlatform { + includeEngines "junit-vintage", "junit-jupiter" + } +} + +dependencies { + api("de.huxhorn.sulky:de.huxhorn.sulky.ulid") + implementation("com.google.guava:guava") +} diff --git a/orca-core/orca-core.gradle b/orca-core/orca-core.gradle index 0c9b3931a9..fe68437f31 100644 --- a/orca-core/orca-core.gradle +++ b/orca-core/orca-core.gradle @@ -32,6 +32,7 @@ dependencies { api("io.reactivex:rxjava") implementation(project(":orca-extensionpoint")) + implementation(project(":orca-api")) implementation("com.github.ben-manes.caffeine:guava") implementation("org.slf4j:slf4j-api") implementation("com.fasterxml.jackson.core:jackson-annotations") diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java index 3f6fce064b..6287be5659 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java @@ -18,10 +18,12 @@ import static java.lang.String.format; +import com.netflix.spinnaker.orca.api.Stage; import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import javax.annotation.Nonnull; /** @@ -32,7 +34,8 @@ public class StageResolver { private final Map stageDefinitionBuilderByAlias = new HashMap<>(); - public StageResolver(Collection stageDefinitionBuilders) { + public StageResolver( + Collection stageDefinitionBuilders, Collection apiStages) { for (StageDefinitionBuilder stageDefinitionBuilder : stageDefinitionBuilders) { stageDefinitionBuilderByAlias.put(stageDefinitionBuilder.getType(), stageDefinitionBuilder); for (String alias : stageDefinitionBuilder.aliases()) { @@ -48,6 +51,13 @@ public StageResolver(Collection stageDefinitionBuilders) stageDefinitionBuilderByAlias.put(alias, stageDefinitionBuilder); } } + + if (!Objects.equals(apiStages, null)) { + for (Stage stage : apiStages) { + // TODO if the scaffolding makes sense this is where Stage will be converted to + // StageDefinitionBuilder + } + } } /** 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 0d2098f833..0ab3bcd828 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 @@ -25,6 +25,7 @@ import com.netflix.spinnaker.orca.StageResolver; import com.netflix.spinnaker.orca.Task; import com.netflix.spinnaker.orca.TaskResolver; +import com.netflix.spinnaker.orca.api.Stage; import com.netflix.spinnaker.orca.commands.ForceExecutionCancellationCommand; import com.netflix.spinnaker.orca.events.ExecutionEvent; import com.netflix.spinnaker.orca.events.ExecutionListenerAdapter; @@ -187,8 +188,9 @@ public TaskResolver taskResolver(Collection tasks) { } @Bean - public StageResolver stageResolver(Collection stageDefinitionBuilders) { - return new StageResolver(stageDefinitionBuilders); + public StageResolver stageResolver( + Collection stageDefinitionBuilders, Collection apiStages) { + return new StageResolver(stageDefinitionBuilders, apiStages); } @Bean(name = EVENT_LISTENER_FACTORY_BEAN_NAME) diff --git a/orca-web/orca-web.gradle b/orca-web/orca-web.gradle index 28557d7a64..bfa9b437f1 100644 --- a/orca-web/orca-web.gradle +++ b/orca-web/orca-web.gradle @@ -33,6 +33,7 @@ dependencies { implementation("net.logstash.logback:logstash-logback-encoder") implementation(project(":orca-core")) + implementation(project(":orca-api")) implementation(project(":orca-redis")) implementation(project(":orca-bakery")) implementation(project(":orca-clouddriver")) diff --git a/settings.gradle b/settings.gradle index b331447c04..0b0b8cfa99 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,6 +16,7 @@ include "orca-extensionpoint", "orca-core", + "orca-api", "orca-core-tck", "orca-redis", "orca-test-redis", From 0581af4986cd2fb6842a9556eb4df7bc180e4637 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 8 Aug 2019 15:42:57 -0700 Subject: [PATCH 03/18] fix(plugins): removed ulid dep --- orca-api/orca-api.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/orca-api/orca-api.gradle b/orca-api/orca-api.gradle index 8ac8baa879..8be4734f3e 100644 --- a/orca-api/orca-api.gradle +++ b/orca-api/orca-api.gradle @@ -24,6 +24,5 @@ test { } dependencies { - api("de.huxhorn.sulky:de.huxhorn.sulky.ulid") implementation("com.google.guava:guava") } From 442e40453ed0462ba9343fe07fc4746495ee863d Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 8 Aug 2019 15:46:42 -0700 Subject: [PATCH 04/18] chore(plugins): added copyright --- .../com/netflix/spinnaker/orca/api/Stage.java | 16 ++++++++++++++++ .../netflix/spinnaker/orca/api/StageInput.java | 16 ++++++++++++++++ .../netflix/spinnaker/orca/api/StageOutput.java | 16 ++++++++++++++++ .../netflix/spinnaker/orca/api/StageStatus.java | 16 ++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java index a04bf17723..83d8f50df1 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.netflix.spinnaker.orca.api; import com.google.common.annotations.Beta; diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java index d9cdcf4287..eb173421b4 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.netflix.spinnaker.orca.api; import com.google.common.annotations.Beta; diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java index 872a491efb..5ad8e4e9a9 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.netflix.spinnaker.orca.api; import com.google.common.annotations.Beta; diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java index 22cc649535..8bfa7502d0 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java @@ -1,3 +1,19 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.netflix.spinnaker.orca.api; import com.google.common.annotations.Beta; From c0f6c4c1402332e58be940fa4e5360e9840a2360 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 8 Aug 2019 17:40:15 -0700 Subject: [PATCH 05/18] feat(plugins): filled in scaffolding --- .../com/netflix/spinnaker/orca/api/Stage.java | 2 + .../netflix/spinnaker/orca/StageResolver.java | 5 +- .../pipeline/ApiStageDefinitionBuilder.java | 33 ++++++++++ .../spinnaker/orca/pipeline/ApiTask.java | 62 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java create mode 100644 orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java index 83d8f50df1..a44ba08f22 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java @@ -21,4 +21,6 @@ @Beta public interface Stage { StageOutput execute(StageInput stageInput); + + String getName(); } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java index 6287be5659..09e4fa7279 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java @@ -19,6 +19,7 @@ import static java.lang.String.format; import com.netflix.spinnaker.orca.api.Stage; +import com.netflix.spinnaker.orca.pipeline.ApiStageDefinitionBuilder; import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder; import java.util.Collection; import java.util.HashMap; @@ -54,8 +55,8 @@ public StageResolver( if (!Objects.equals(apiStages, null)) { for (Stage stage : apiStages) { - // TODO if the scaffolding makes sense this is where Stage will be converted to - // StageDefinitionBuilder + ApiStageDefinitionBuilder builder = new ApiStageDefinitionBuilder(stage); + stageDefinitionBuilderByAlias.put(stage.getName(), builder); } } } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java new file mode 100644 index 0000000000..2a589e9f40 --- /dev/null +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.netflix.spinnaker.orca.pipeline; + +import com.netflix.spinnaker.orca.pipeline.model.Stage; +import javax.annotation.Nonnull; + +public class ApiStageDefinitionBuilder implements StageDefinitionBuilder { + private com.netflix.spinnaker.orca.api.Stage apiStage; + + public ApiStageDefinitionBuilder(com.netflix.spinnaker.orca.api.Stage apiStage) { + this.apiStage = apiStage; + } + + public void taskGraph(@Nonnull Stage stage, @Nonnull TaskNode.Builder builder) { + ApiTask task = new ApiTask(apiStage); + builder.withTask(apiStage.getName(), task.getClass()); + } +} diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java new file mode 100644 index 0000000000..e8f268e4d9 --- /dev/null +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Armory, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.netflix.spinnaker.orca.pipeline; + +import com.netflix.spinnaker.orca.ExecutionStatus; +import com.netflix.spinnaker.orca.Task; +import com.netflix.spinnaker.orca.TaskResult; +import com.netflix.spinnaker.orca.api.StageInput; +import com.netflix.spinnaker.orca.api.StageOutput; +import com.netflix.spinnaker.orca.pipeline.model.Stage; +import javax.annotation.Nonnull; +import org.springframework.stereotype.Component; + +@Component +public class ApiTask implements Task { + private com.netflix.spinnaker.orca.api.Stage apiStage; + + ApiTask(com.netflix.spinnaker.orca.api.Stage apiStage) { + this.apiStage = apiStage; + } + + @Nonnull + public TaskResult execute(@Nonnull Stage stage) { + TaskResult result; + StageInput stageInput = new StageInput(); + stageInput.setInput(stage.getContext()); + StageOutput outputs = apiStage.execute(stageInput); + switch (outputs.getStatus()) { + case TERMINAL: + result = TaskResult.ofStatus(ExecutionStatus.TERMINAL); + break; + case RUNNING: + result = TaskResult.ofStatus(ExecutionStatus.RUNNING); + break; + case COMPLETED: + result = TaskResult.ofStatus(ExecutionStatus.SUCCEEDED); + break; + case NOT_STARTED: + result = TaskResult.ofStatus(ExecutionStatus.NOT_STARTED); + break; + default: + result = TaskResult.ofStatus(ExecutionStatus.FAILED_CONTINUE); + break; + } + + return result; + } +} From 895a5c804d837865f327c7402282431399e5b651 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Fri, 9 Aug 2019 12:41:40 -0700 Subject: [PATCH 06/18] fix(plugins): changed StageInputs to be generic --- .../netflix/spinnaker/orca/api/StageInput.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java index eb173421b4..b0e64d6120 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java @@ -17,17 +17,20 @@ package com.netflix.spinnaker.orca.api; import com.google.common.annotations.Beta; -import java.util.Map; @Beta -public class StageInput { - private Map input; +public class StageInput { + private T value; - public void setInput(Map input) { - this.input = input; + public StageInput(T value) { + this.value = value; } - public Map getInput() { - return this.input; + public void setValue(T value) { + this.value = value; + } + + public T getValue() { + return this.value; } } From 7d6239340852fa9ec6a6be972d8153b887b9fd33 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Fri, 9 Aug 2019 12:45:05 -0700 Subject: [PATCH 07/18] fix(plugins): make use of generic StageInput --- .../netflix/spinnaker/orca/pipeline/ApiTask.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index e8f268e4d9..e60ff747e9 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -16,13 +16,16 @@ package com.netflix.spinnaker.orca.pipeline; +import com.fasterxml.jackson.databind.ObjectMapper; import com.netflix.spinnaker.orca.ExecutionStatus; import com.netflix.spinnaker.orca.Task; import com.netflix.spinnaker.orca.TaskResult; import com.netflix.spinnaker.orca.api.StageInput; import com.netflix.spinnaker.orca.api.StageOutput; +import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper; import com.netflix.spinnaker.orca.pipeline.model.Stage; import javax.annotation.Nonnull; +import org.springframework.core.ResolvableType; import org.springframework.stereotype.Component; @Component @@ -35,9 +38,16 @@ public class ApiTask implements Task { @Nonnull public TaskResult execute(@Nonnull Stage stage) { + ObjectMapper objectMapper = OrcaObjectMapper.newInstance(); + TaskResult result; - StageInput stageInput = new StageInput(); - stageInput.setInput(stage.getContext()); + ResolvableType resolvedType = ResolvableType.forClass(apiStage.getClass()); + resolvedType.resolve(); + + ResolvableType inputType = resolvedType.getGeneric(0); + + StageInput stageInput = + new StageInput(objectMapper.convertValue(stage.getContext(), inputType.getRawClass())); StageOutput outputs = apiStage.execute(stageInput); switch (outputs.getStatus()) { case TERMINAL: From bc56a28224cbe541ea548c6153b13118dcb68b55 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Fri, 9 Aug 2019 13:19:04 -0700 Subject: [PATCH 08/18] fix(plugins): should properly get the generic from StageInput --- .../spinnaker/orca/pipeline/ApiTask.java | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index e60ff747e9..fef6edf0f0 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -24,6 +24,7 @@ import com.netflix.spinnaker.orca.api.StageOutput; import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper; import com.netflix.spinnaker.orca.pipeline.model.Stage; +import java.lang.reflect.Method; import javax.annotation.Nonnull; import org.springframework.core.ResolvableType; import org.springframework.stereotype.Component; @@ -41,32 +42,39 @@ public TaskResult execute(@Nonnull Stage stage) { ObjectMapper objectMapper = OrcaObjectMapper.newInstance(); TaskResult result; - ResolvableType resolvedType = ResolvableType.forClass(apiStage.getClass()); - resolvedType.resolve(); + try { + Method method = apiStage.getClass().getMethod("execute"); + ResolvableType resolvedType = ResolvableType.forMethodParameter(method, 1); + resolvedType.resolve(); - ResolvableType inputType = resolvedType.getGeneric(0); + ResolvableType inputType = resolvedType.getGeneric(0); - StageInput stageInput = - new StageInput(objectMapper.convertValue(stage.getContext(), inputType.getRawClass())); - StageOutput outputs = apiStage.execute(stageInput); - switch (outputs.getStatus()) { - case TERMINAL: - result = TaskResult.ofStatus(ExecutionStatus.TERMINAL); - break; - case RUNNING: - result = TaskResult.ofStatus(ExecutionStatus.RUNNING); - break; - case COMPLETED: - result = TaskResult.ofStatus(ExecutionStatus.SUCCEEDED); - break; - case NOT_STARTED: - result = TaskResult.ofStatus(ExecutionStatus.NOT_STARTED); - break; - default: - result = TaskResult.ofStatus(ExecutionStatus.FAILED_CONTINUE); - break; + StageInput stageInput = + new StageInput(objectMapper.convertValue(stage.getContext(), inputType.getRawClass())); + StageOutput outputs = apiStage.execute(stageInput); + switch (outputs.getStatus()) { + case TERMINAL: + result = TaskResult.ofStatus(ExecutionStatus.TERMINAL); + break; + case RUNNING: + result = TaskResult.ofStatus(ExecutionStatus.RUNNING); + break; + case COMPLETED: + result = TaskResult.ofStatus(ExecutionStatus.SUCCEEDED); + break; + case NOT_STARTED: + result = TaskResult.ofStatus(ExecutionStatus.NOT_STARTED); + break; + default: + result = TaskResult.ofStatus(ExecutionStatus.FAILED_CONTINUE); + break; + } + + return result; + } catch (Exception e) { + // TODO properly handle exeception } - return result; + return null; } } From fde6cb68ec81f13c419d90b55949f3917b211a28 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Mon, 12 Aug 2019 14:25:27 -0700 Subject: [PATCH 09/18] fix(plugins): properly gets generic class for StageInput --- .../spinnaker/orca/pipeline/ApiTask.java | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index fef6edf0f0..135807be97 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -25,10 +25,16 @@ import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper; import com.netflix.spinnaker.orca.pipeline.model.Stage; import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Map; import javax.annotation.Nonnull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.GenericTypeResolver; import org.springframework.core.ResolvableType; import org.springframework.stereotype.Component; +@Slf4j @Component public class ApiTask implements Task { private com.netflix.spinnaker.orca.api.Stage apiStage; @@ -41,40 +47,43 @@ public class ApiTask implements Task { public TaskResult execute(@Nonnull Stage stage) { ObjectMapper objectMapper = OrcaObjectMapper.newInstance(); - TaskResult result; + ExecutionStatus status; try { - Method method = apiStage.getClass().getMethod("execute"); - ResolvableType resolvedType = ResolvableType.forMethodParameter(method, 1); - resolvedType.resolve(); - - ResolvableType inputType = resolvedType.getGeneric(0); + Class[] cArg = new Class[1]; + cArg[0] = StageInput.class; + Method method = apiStage.getClass().getMethod("execute", cArg); + Type type = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); + Map typeVariableMap = + GenericTypeResolver.getTypeVariableMap(apiStage.getClass()); StageInput stageInput = - new StageInput(objectMapper.convertValue(stage.getContext(), inputType.getRawClass())); + new StageInput( + objectMapper.convertValue( + stage.getContext(), GenericTypeResolver.resolveType(type, typeVariableMap))); StageOutput outputs = apiStage.execute(stageInput); switch (outputs.getStatus()) { case TERMINAL: - result = TaskResult.ofStatus(ExecutionStatus.TERMINAL); + status = ExecutionStatus.TERMINAL; break; case RUNNING: - result = TaskResult.ofStatus(ExecutionStatus.RUNNING); + status = ExecutionStatus.RUNNING; break; case COMPLETED: - result = TaskResult.ofStatus(ExecutionStatus.SUCCEEDED); + status = ExecutionStatus.SUCCEEDED; break; case NOT_STARTED: - result = TaskResult.ofStatus(ExecutionStatus.NOT_STARTED); + status = ExecutionStatus.NOT_STARTED; break; default: - result = TaskResult.ofStatus(ExecutionStatus.FAILED_CONTINUE); + status = ExecutionStatus.FAILED_CONTINUE; break; } - - return result; } catch (Exception e) { - // TODO properly handle exeception + log.error("Cannot execute stage " + apiStage.getName()); + log.error(e.getMessage()); + status = ExecutionStatus.TERMINAL; } - return null; + return TaskResult.ofStatus(status); } } From c858bd4554704c09ab98c76fc1dd2d2c34854614 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Mon, 12 Aug 2019 14:26:50 -0700 Subject: [PATCH 10/18] fix(plugins): made Stage take in generic for StageInput --- .../src/main/java/com/netflix/spinnaker/orca/api/Stage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java index 83d8f50df1..2c6433cc4b 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java @@ -19,6 +19,8 @@ import com.google.common.annotations.Beta; @Beta -public interface Stage { - StageOutput execute(StageInput stageInput); +public interface Stage { + StageOutput execute(StageInput stageInput); + + String getName(); } From 9c3c8f096a58fac2498364d9a930723e03826d84 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Tue, 13 Aug 2019 09:27:32 -0700 Subject: [PATCH 11/18] fix(plugins): using Arrays.asList instead of constructing by hand --- .../java/com/netflix/spinnaker/orca/pipeline/ApiTask.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index 135807be97..01cf957e15 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -27,6 +27,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import lombok.extern.slf4j.Slf4j; @@ -49,9 +51,8 @@ public TaskResult execute(@Nonnull Stage stage) { ExecutionStatus status; try { - Class[] cArg = new Class[1]; - cArg[0] = StageInput.class; - Method method = apiStage.getClass().getMethod("execute", cArg); + List> cArg = Arrays.asList(StageInput.class); + Method method = apiStage.getClass().getMethod("execute", cArg.toArray(new Class[0])); Type type = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); Map typeVariableMap = GenericTypeResolver.getTypeVariableMap(apiStage.getClass()); From 2aa39537ee95c9624b9e8dc63b2064058677b634 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Tue, 13 Aug 2019 09:28:40 -0700 Subject: [PATCH 12/18] fix(plugins): refactored variable name --- .../java/com/netflix/spinnaker/orca/pipeline/ApiTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index 01cf957e15..0a70466db5 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -53,14 +53,14 @@ public TaskResult execute(@Nonnull Stage stage) { try { List> cArg = Arrays.asList(StageInput.class); Method method = apiStage.getClass().getMethod("execute", cArg.toArray(new Class[0])); - Type type = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); + Type inputType = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); Map typeVariableMap = GenericTypeResolver.getTypeVariableMap(apiStage.getClass()); StageInput stageInput = new StageInput( objectMapper.convertValue( - stage.getContext(), GenericTypeResolver.resolveType(type, typeVariableMap))); + stage.getContext(), GenericTypeResolver.resolveType(inputType, typeVariableMap))); StageOutput outputs = apiStage.execute(stageInput); switch (outputs.getStatus()) { case TERMINAL: From 7fc46c260ada369c7e52c01fa0fbb51b624c0af8 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Tue, 13 Aug 2019 09:35:02 -0700 Subject: [PATCH 13/18] feat(plugins): actually able to use stage outputs --- .../com/netflix/spinnaker/orca/pipeline/ApiTask.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index 0a70466db5..16a35a5d28 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -50,6 +50,8 @@ public TaskResult execute(@Nonnull Stage stage) { ObjectMapper objectMapper = OrcaObjectMapper.newInstance(); ExecutionStatus status; + StageOutput outputs = new StageOutput(); + try { List> cArg = Arrays.asList(StageInput.class); Method method = apiStage.getClass().getMethod("execute", cArg.toArray(new Class[0])); @@ -61,7 +63,7 @@ public TaskResult execute(@Nonnull Stage stage) { new StageInput( objectMapper.convertValue( stage.getContext(), GenericTypeResolver.resolveType(inputType, typeVariableMap))); - StageOutput outputs = apiStage.execute(stageInput); + outputs = apiStage.execute(stageInput); switch (outputs.getStatus()) { case TERMINAL: status = ExecutionStatus.TERMINAL; @@ -85,6 +87,9 @@ public TaskResult execute(@Nonnull Stage stage) { status = ExecutionStatus.TERMINAL; } - return TaskResult.ofStatus(status); + return TaskResult.builder(status) + .context(outputs.getOutputs()) + .outputs(outputs.getOutputs()) + .build(); } } From 00f5f8898651f3c7fc13b7814bc4f22357ae36ef Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Wed, 14 Aug 2019 10:29:12 -0700 Subject: [PATCH 14/18] chore(plugins): updated tests for Api Stages --- .../spinnaker/orca/StageResolverSpec.groovy | 36 +++++++++++----- orca-queue/orca-queue.gradle | 1 + .../orca/q/handler/CancelStageHandlerTest.kt | 3 +- .../q/handler/CompleteStageHandlerTest.kt | 43 +++++++++++++++++++ .../orca/q/handler/RestartStageHandlerTest.kt | 13 ++++++ .../orca/q/handler/StartStageHandlerTest.kt | 37 ++++++++++++++++ 6 files changed, 122 insertions(+), 11 deletions(-) diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy index 47e61e8d8a..7fa7a17ce9 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy @@ -16,22 +16,23 @@ package com.netflix.spinnaker.orca +import com.netflix.spinnaker.orca.api.StageInput +import com.netflix.spinnaker.orca.api.StageOutput import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder import com.netflix.spinnaker.orca.pipeline.WaitStage -import com.netflix.spinnaker.orca.pipeline.model.Stage -import com.netflix.spinnaker.orca.pipeline.tasks.WaitTask import spock.lang.Specification import spock.lang.Subject import spock.lang.Unroll -import javax.annotation.Nonnull; - class StageResolverSpec extends Specification { @Subject def stageResolver = new StageResolver([ - new WaitStage(), - new AliasedStageDefinitionBuilder() - ]) + new WaitStage(), + new AliasedStageDefinitionBuilder() + ], + [ + new SimpleStage() + ]) @Unroll def "should lookup stage by name or alias"() { @@ -48,9 +49,12 @@ class StageResolverSpec extends Specification { def "should raise exception on duplicate alias"() { when: new StageResolver([ - new AliasedStageDefinitionBuilder(), - new AliasedStageDefinitionBuilder() - ]) + new AliasedStageDefinitionBuilder(), + new AliasedStageDefinitionBuilder() + ], + [ + new SimpleStage() + ]) then: thrown(StageResolver.DuplicateStageAliasException) @@ -67,4 +71,16 @@ class StageResolverSpec extends Specification { @StageDefinitionBuilder.Aliases("notAliased") class AliasedStageDefinitionBuilder implements StageDefinitionBuilder { } + + class SimpleStage implements com.netflix.spinnaker.orca.api.Stage { + @Override + public StageOutput execute(StageInput input) { + return new StageOutput(); + } + + @Override + public String getName() { + return "simpleApiStage"; + } + } } diff --git a/orca-queue/orca-queue.gradle b/orca-queue/orca-queue.gradle index d98b55a924..66fb09679e 100644 --- a/orca-queue/orca-queue.gradle +++ b/orca-queue/orca-queue.gradle @@ -19,6 +19,7 @@ apply from: "$rootDir/gradle/spek.gradle" dependencies { api(project(":orca-core")) + api(project(":orca-api")) implementation(project(":orca-kotlin")) implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("com.netflix.spinnaker.keiko:keiko-spring:$keikoVersion") diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt index bf1cc89e5f..e117f1721d 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt @@ -24,6 +24,7 @@ import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver import com.netflix.spinnaker.orca.TaskResolver +import com.netflix.spinnaker.orca.api.Stage import com.netflix.spinnaker.orca.fixture.pipeline import com.netflix.spinnaker.orca.fixture.stage import com.netflix.spinnaker.orca.pipeline.DefaultStageDefinitionBuilderFactory @@ -56,7 +57,7 @@ object CancelStageHandlerTest : SubjectSpek({ val stageNavigator: StageNavigator = mock() val cancellableStage: CancelableStageDefinitionBuilder = mock() - val stageResolver = StageResolver(listOf(singleTaskStage, cancellableStage)) + val stageResolver = StageResolver(listOf(singleTaskStage, cancellableStage), emptyList>()) subject(GROUP) { CancelStageHandler( diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt index cbef96b1dd..845e9e7445 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt @@ -26,6 +26,9 @@ import com.netflix.spinnaker.orca.ExecutionStatus.STOPPED import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver +import com.netflix.spinnaker.orca.api.StageInput +import com.netflix.spinnaker.orca.api.StageOutput +import com.netflix.spinnaker.orca.api.StageStatus import com.netflix.spinnaker.orca.events.StageComplete import com.netflix.spinnaker.orca.exceptions.DefaultExceptionHandler import com.netflix.spinnaker.orca.exceptions.ExceptionHandler @@ -143,6 +146,24 @@ object CompleteStageHandlerTest : SubjectSpek({ } } + val emptyApiStage = object : com.netflix.spinnaker.orca.api.Stage { + override fun getName() = "emptyApiStage" + + override fun execute(input: StageInput): StageOutput { + return StageOutput() + } + } + + val successfulApiStage = object : com.netflix.spinnaker.orca.api.Stage { + override fun getName() = "successfulApiStage" + + override fun execute(input: StageInput): StageOutput { + val output = StageOutput() + output.status = StageStatus.COMPLETED + return output + } + } + subject(GROUP) { CompleteStageHandler( queue, @@ -167,6 +188,10 @@ object CompleteStageHandlerTest : SubjectSpek({ stageWithNothingButAfterStages, stageWithSyntheticOnFailure, emptyStage + ), + listOf( + emptyApiStage, + successfulApiStage ) ) ) @@ -1467,4 +1492,22 @@ object CompleteStageHandlerTest : SubjectSpek({ } } } + + given("api stage completed successfully") { + val pipeline = pipeline { + stage { + refId = "1" + type = successfulApiStage.name + } + } + + val message = CompleteStage(pipeline.stageByRef("1")) + pipeline.stageById(message.stageId).apply { + status = SUCCEEDED + } + + it("stage was successfully ran") { + assertThat(pipeline.stageById(message.stageId).status).isEqualTo(SUCCEEDED) + } + } }) diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt index cb4736fe91..77991205fe 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt @@ -22,6 +22,8 @@ import com.netflix.spinnaker.orca.ExecutionStatus.RUNNING import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver +import com.netflix.spinnaker.orca.api.StageInput +import com.netflix.spinnaker.orca.api.StageOutput import com.netflix.spinnaker.orca.fixture.pipeline import com.netflix.spinnaker.orca.fixture.stage import com.netflix.spinnaker.orca.pipeline.DefaultStageDefinitionBuilderFactory @@ -77,6 +79,14 @@ object RestartStageHandlerTest : SubjectSpek({ val pendingExecutionService: PendingExecutionService = mock() val clock = fixedClock() + val emptyApiStage = object : com.netflix.spinnaker.orca.api.Stage { + override fun getName() = "emptyApiStage" + + override fun execute(input: StageInput): StageOutput { + return StageOutput() + } + } + subject(GROUP) { RestartStageHandler( queue, @@ -87,6 +97,9 @@ object RestartStageHandlerTest : SubjectSpek({ singleTaskStage, stageWithSyntheticBefore, stageWithNestedSynthetics + ), + listOf( + emptyApiStage ) ) ), diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt index 6297b06cb9..43830db5a9 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt @@ -24,6 +24,9 @@ import com.netflix.spinnaker.orca.ExecutionStatus.RUNNING import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver +import com.netflix.spinnaker.orca.api.StageInput +import com.netflix.spinnaker.orca.api.StageOutput +import com.netflix.spinnaker.orca.api.StageStatus import com.netflix.spinnaker.orca.events.StageStarted import com.netflix.spinnaker.orca.exceptions.ExceptionHandler import com.netflix.spinnaker.orca.fixture.pipeline @@ -100,6 +103,16 @@ object StartStageHandlerTest : SubjectSpek({ val registry = NoopRegistry() val retryDelay = Duration.ofSeconds(5) + val runningApiStage = object : com.netflix.spinnaker.orca.api.Stage { + override fun getName() = "runningApiStage" + + override fun execute(input: StageInput): StageOutput { + val output = StageOutput() + output.status = StageStatus.RUNNING + return output + } + } + subject(GROUP) { StartStageHandler( queue, @@ -118,6 +131,9 @@ object StartStageHandlerTest : SubjectSpek({ stageWithSyntheticAfterAndNoTasks, webhookStage, failPlanningStage + ), + listOf( + runningApiStage ) ) ), @@ -134,6 +150,7 @@ object StartStageHandlerTest : SubjectSpek({ fun resetMocks() = reset(queue, repository, publisher, exceptionHandler) describe("starting a stage") { + given("there is a single initial task") { val pipeline = pipeline { application = "foo" @@ -1132,5 +1149,25 @@ object StartStageHandlerTest : SubjectSpek({ verify(queue).push(isA()) } } + + given("api stage") { + val pipeline = pipeline { + stage { + refId = "1" + type = runningApiStage.name + } + } + + val message = StartStage(pipeline.stageByRef("1")) + pipeline.stageById(message.stageId).apply { + status = RUNNING + } + + afterGroup(::resetMocks) + + it("stage was successfully started") { + assertThat(pipeline.stageById(message.stageId).status).isEqualTo(RUNNING) + } + } } }) From 8dd69f705e083e52c51a8d8deb822a3a0cbf5fb1 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Wed, 14 Aug 2019 14:00:32 -0700 Subject: [PATCH 15/18] chore(plugins): added test for ApiTask --- .../orca/pipeline/ApiTaskSpec.groovy | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy new file mode 100644 index 0000000000..486c39c3a9 --- /dev/null +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.netflix.spinnaker.orca.pipeline + +import com.netflix.spinnaker.orca.ExecutionStatus +import com.netflix.spinnaker.orca.api.Stage +import com.netflix.spinnaker.orca.api.StageInput +import com.netflix.spinnaker.orca.api.StageOutput +import com.netflix.spinnaker.orca.api.StageStatus +import spock.lang.Specification +import spock.lang.Subject +import spock.lang.Unroll + +class ApiTaskSpec extends Specification { + private static class MyStage implements Stage { + @Override + String getName() { + return "myStage" + } + + @Override + StageOutput execute(StageInput input) { + StageOutput output = new StageOutput() + + Map stageOutput = new HashMap<>() + stageOutput.put("hello", "world") + + output.setStatus(StageStatus.COMPLETED) + output.setOutputs(stageOutput) + return output + } + } + + @Subject + def myStage = new MyStage() + + @Unroll + def "should check dynamic config property"() { + when: + def task = new ApiTask(myStage) + def results = task.execute(new com.netflix.spinnaker.orca.pipeline.model.Stage()) + + then: + results.getStatus() == ExecutionStatus.SUCCEEDED + results.getContext()["hello"] == "world" + } +} From d52530063276ff3f36f9ee564b0e1691e7114768 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 15 Aug 2019 09:39:21 -0700 Subject: [PATCH 16/18] fix(plugins): chnaged header and made code more groovy --- .../com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy index 486c39c3a9..aacbd97ac6 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2019 Netflix, Inc. + * Copyright 2019 Armory, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,6 +56,6 @@ class ApiTaskSpec extends Specification { then: results.getStatus() == ExecutionStatus.SUCCEEDED - results.getContext()["hello"] == "world" + results.context.hello == "world" } } From c752ffae993a0f4daf8605a9529dc3e7b6410b68 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 15 Aug 2019 13:34:44 -0700 Subject: [PATCH 17/18] fix(plugins): made tests work when no plugins are in the codebase --- .../netflix/spinnaker/orca/config/OrcaConfiguration.java | 9 +++++---- .../com/netflix/spinnaker/orca/pipeline/ApiTask.java | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) 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 0ab3bcd828..6c8d997a53 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 @@ -41,8 +41,7 @@ import com.netflix.spinnaker.orca.pipeline.util.ContextParameterProcessor; import java.time.Clock; import java.time.Duration; -import java.util.Collection; -import java.util.List; +import java.util.*; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -189,8 +188,10 @@ public TaskResolver taskResolver(Collection tasks) { @Bean public StageResolver stageResolver( - Collection stageDefinitionBuilders, Collection apiStages) { - return new StageResolver(stageDefinitionBuilders, apiStages); + Collection stageDefinitionBuilders, + Optional> apiStages) { + Collection stages = apiStages.isPresent() ? apiStages.get() : new ArrayList(); + return new StageResolver(stageDefinitionBuilders, stages); } @Bean(name = EVENT_LISTENER_FACTORY_BEAN_NAME) diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java index 16a35a5d28..37b0ec9c98 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import org.springframework.core.GenericTypeResolver; import org.springframework.core.ResolvableType; @@ -41,7 +42,7 @@ public class ApiTask implements Task { private com.netflix.spinnaker.orca.api.Stage apiStage; - ApiTask(com.netflix.spinnaker.orca.api.Stage apiStage) { + ApiTask(@Nullable com.netflix.spinnaker.orca.api.Stage apiStage) { this.apiStage = apiStage; } From 34ead88d609d15da8b192b458bb32c4203c191f3 Mon Sep 17 00:00:00 2001 From: Brandon Powell Date: Thu, 15 Aug 2019 16:37:31 -0700 Subject: [PATCH 18/18] chore(plugins): refacgtored to simple --- .../orca/api/{Stage.java => SimpleStage.java} | 4 +-- ...{StageInput.java => SimpleStageInput.java} | 4 +-- ...tageOutput.java => SimpleStageOutput.java} | 8 ++--- ...tageStatus.java => SimpleStageStatus.java} | 2 +- .../netflix/spinnaker/orca/StageResolver.java | 11 +++---- .../orca/config/OrcaConfiguration.java | 7 +++-- ...java => SimpleStageDefinitionBuilder.java} | 13 +++++---- .../{ApiTask.java => SimpleTask.java} | 29 ++++++++++--------- .../spinnaker/orca/StageResolverSpec.groovy | 11 +++---- ...iTaskSpec.groovy => SimpleTaskSpec.groovy} | 20 ++++++------- .../orca/q/handler/CancelStageHandlerTest.kt | 4 +-- .../q/handler/CompleteStageHandlerTest.kt | 21 +++++++------- .../orca/q/handler/RestartStageHandlerTest.kt | 11 +++---- .../orca/q/handler/StartStageHandlerTest.kt | 15 +++++----- 14 files changed, 84 insertions(+), 76 deletions(-) rename orca-api/src/main/java/com/netflix/spinnaker/orca/api/{Stage.java => SimpleStage.java} (87%) rename orca-api/src/main/java/com/netflix/spinnaker/orca/api/{StageInput.java => SimpleStageInput.java} (92%) rename orca-api/src/main/java/com/netflix/spinnaker/orca/api/{StageOutput.java => SimpleStageOutput.java} (85%) rename orca-api/src/main/java/com/netflix/spinnaker/orca/api/{StageStatus.java => SimpleStageStatus.java} (95%) rename orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/{ApiStageDefinitionBuilder.java => SimpleStageDefinitionBuilder.java} (68%) rename orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/{ApiTask.java => SimpleTask.java} (75%) rename orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/{ApiTaskSpec.groovy => SimpleTaskSpec.groovy} (70%) diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStage.java similarity index 87% rename from orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java rename to orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStage.java index 2c6433cc4b..d59506f0b4 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/Stage.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStage.java @@ -19,8 +19,8 @@ import com.google.common.annotations.Beta; @Beta -public interface Stage { - StageOutput execute(StageInput stageInput); +public interface SimpleStage { + SimpleStageOutput execute(SimpleStageInput simpleStageInput); String getName(); } diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageInput.java similarity index 92% rename from orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java rename to orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageInput.java index b0e64d6120..bb59424855 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageInput.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageInput.java @@ -19,10 +19,10 @@ import com.google.common.annotations.Beta; @Beta -public class StageInput { +public class SimpleStageInput { private T value; - public StageInput(T value) { + public SimpleStageInput(T value) { this.value = value; } diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageOutput.java similarity index 85% rename from orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java rename to orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageOutput.java index 5ad8e4e9a9..138a29faf4 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageOutput.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageOutput.java @@ -20,14 +20,14 @@ import java.util.Map; @Beta -public class StageOutput { - private StageStatus status; +public class SimpleStageOutput { + private SimpleStageStatus status; - public void setStatus(StageStatus status) { + public void setStatus(SimpleStageStatus status) { this.status = status; } - public StageStatus getStatus() { + public SimpleStageStatus getStatus() { return this.status; } diff --git a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageStatus.java similarity index 95% rename from orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java rename to orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageStatus.java index 8bfa7502d0..e4299e9267 100644 --- a/orca-api/src/main/java/com/netflix/spinnaker/orca/api/StageStatus.java +++ b/orca-api/src/main/java/com/netflix/spinnaker/orca/api/SimpleStageStatus.java @@ -19,7 +19,7 @@ import com.google.common.annotations.Beta; @Beta -public enum StageStatus { +public enum SimpleStageStatus { TERMINAL, RUNNING, COMPLETED, diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java index 09e4fa7279..f3061a95c3 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/StageResolver.java @@ -18,8 +18,8 @@ import static java.lang.String.format; -import com.netflix.spinnaker.orca.api.Stage; -import com.netflix.spinnaker.orca.pipeline.ApiStageDefinitionBuilder; +import com.netflix.spinnaker.orca.api.SimpleStage; +import com.netflix.spinnaker.orca.pipeline.SimpleStageDefinitionBuilder; import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder; import java.util.Collection; import java.util.HashMap; @@ -36,7 +36,8 @@ public class StageResolver { private final Map stageDefinitionBuilderByAlias = new HashMap<>(); public StageResolver( - Collection stageDefinitionBuilders, Collection apiStages) { + Collection stageDefinitionBuilders, + Collection apiStages) { for (StageDefinitionBuilder stageDefinitionBuilder : stageDefinitionBuilders) { stageDefinitionBuilderByAlias.put(stageDefinitionBuilder.getType(), stageDefinitionBuilder); for (String alias : stageDefinitionBuilder.aliases()) { @@ -54,8 +55,8 @@ public StageResolver( } if (!Objects.equals(apiStages, null)) { - for (Stage stage : apiStages) { - ApiStageDefinitionBuilder builder = new ApiStageDefinitionBuilder(stage); + for (SimpleStage stage : apiStages) { + SimpleStageDefinitionBuilder builder = new SimpleStageDefinitionBuilder(stage); stageDefinitionBuilderByAlias.put(stage.getName(), builder); } } 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 6c8d997a53..78e2b06c48 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 @@ -25,7 +25,7 @@ import com.netflix.spinnaker.orca.StageResolver; import com.netflix.spinnaker.orca.Task; import com.netflix.spinnaker.orca.TaskResolver; -import com.netflix.spinnaker.orca.api.Stage; +import com.netflix.spinnaker.orca.api.SimpleStage; import com.netflix.spinnaker.orca.commands.ForceExecutionCancellationCommand; import com.netflix.spinnaker.orca.events.ExecutionEvent; import com.netflix.spinnaker.orca.events.ExecutionListenerAdapter; @@ -189,8 +189,9 @@ public TaskResolver taskResolver(Collection tasks) { @Bean public StageResolver stageResolver( Collection stageDefinitionBuilders, - Optional> apiStages) { - Collection stages = apiStages.isPresent() ? apiStages.get() : new ArrayList(); + Optional> simpleStages) { + Collection stages = + simpleStages.isPresent() ? simpleStages.get() : new ArrayList(); return new StageResolver(stageDefinitionBuilders, stages); } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleStageDefinitionBuilder.java similarity index 68% rename from orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java rename to orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleStageDefinitionBuilder.java index 2a589e9f40..53019a6981 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiStageDefinitionBuilder.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleStageDefinitionBuilder.java @@ -16,18 +16,19 @@ package com.netflix.spinnaker.orca.pipeline; +import com.netflix.spinnaker.orca.api.SimpleStage; import com.netflix.spinnaker.orca.pipeline.model.Stage; import javax.annotation.Nonnull; -public class ApiStageDefinitionBuilder implements StageDefinitionBuilder { - private com.netflix.spinnaker.orca.api.Stage apiStage; +public class SimpleStageDefinitionBuilder implements StageDefinitionBuilder { + private SimpleStage simpleStage; - public ApiStageDefinitionBuilder(com.netflix.spinnaker.orca.api.Stage apiStage) { - this.apiStage = apiStage; + public SimpleStageDefinitionBuilder(SimpleStage simpleStage) { + this.simpleStage = simpleStage; } public void taskGraph(@Nonnull Stage stage, @Nonnull TaskNode.Builder builder) { - ApiTask task = new ApiTask(apiStage); - builder.withTask(apiStage.getName(), task.getClass()); + SimpleTask task = new SimpleTask(simpleStage); + builder.withTask(simpleStage.getName(), task.getClass()); } } diff --git a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleTask.java similarity index 75% rename from orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java rename to orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleTask.java index 37b0ec9c98..40f11952cc 100644 --- a/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/ApiTask.java +++ b/orca-core/src/main/java/com/netflix/spinnaker/orca/pipeline/SimpleTask.java @@ -20,8 +20,9 @@ import com.netflix.spinnaker.orca.ExecutionStatus; import com.netflix.spinnaker.orca.Task; import com.netflix.spinnaker.orca.TaskResult; -import com.netflix.spinnaker.orca.api.StageInput; -import com.netflix.spinnaker.orca.api.StageOutput; +import com.netflix.spinnaker.orca.api.SimpleStage; +import com.netflix.spinnaker.orca.api.SimpleStageInput; +import com.netflix.spinnaker.orca.api.SimpleStageOutput; import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper; import com.netflix.spinnaker.orca.pipeline.model.Stage; import java.lang.reflect.Method; @@ -39,11 +40,11 @@ @Slf4j @Component -public class ApiTask implements Task { - private com.netflix.spinnaker.orca.api.Stage apiStage; +public class SimpleTask implements Task { + private SimpleStage simpleStage; - ApiTask(@Nullable com.netflix.spinnaker.orca.api.Stage apiStage) { - this.apiStage = apiStage; + SimpleTask(@Nullable SimpleStage simpleStage) { + this.simpleStage = simpleStage; } @Nonnull @@ -51,20 +52,20 @@ public TaskResult execute(@Nonnull Stage stage) { ObjectMapper objectMapper = OrcaObjectMapper.newInstance(); ExecutionStatus status; - StageOutput outputs = new StageOutput(); + SimpleStageOutput outputs = new SimpleStageOutput(); try { - List> cArg = Arrays.asList(StageInput.class); - Method method = apiStage.getClass().getMethod("execute", cArg.toArray(new Class[0])); + List> cArg = Arrays.asList(SimpleStageInput.class); + Method method = simpleStage.getClass().getMethod("execute", cArg.toArray(new Class[0])); Type inputType = ResolvableType.forMethodParameter(method, 0).getGeneric().getType(); Map typeVariableMap = - GenericTypeResolver.getTypeVariableMap(apiStage.getClass()); + GenericTypeResolver.getTypeVariableMap(simpleStage.getClass()); - StageInput stageInput = - new StageInput( + SimpleStageInput simpleStageInput = + new SimpleStageInput( objectMapper.convertValue( stage.getContext(), GenericTypeResolver.resolveType(inputType, typeVariableMap))); - outputs = apiStage.execute(stageInput); + outputs = simpleStage.execute(simpleStageInput); switch (outputs.getStatus()) { case TERMINAL: status = ExecutionStatus.TERMINAL; @@ -83,7 +84,7 @@ public TaskResult execute(@Nonnull Stage stage) { break; } } catch (Exception e) { - log.error("Cannot execute stage " + apiStage.getName()); + log.error("Cannot execute stage " + simpleStage.getName()); log.error(e.getMessage()); status = ExecutionStatus.TERMINAL; } diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy index 7fa7a17ce9..e86bda3187 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/StageResolverSpec.groovy @@ -16,8 +16,9 @@ package com.netflix.spinnaker.orca -import com.netflix.spinnaker.orca.api.StageInput -import com.netflix.spinnaker.orca.api.StageOutput +import com.netflix.spinnaker.orca.api.SimpleStage +import com.netflix.spinnaker.orca.api.SimpleStageInput +import com.netflix.spinnaker.orca.api.SimpleStageOutput import com.netflix.spinnaker.orca.pipeline.StageDefinitionBuilder import com.netflix.spinnaker.orca.pipeline.WaitStage import spock.lang.Specification @@ -72,10 +73,10 @@ class StageResolverSpec extends Specification { class AliasedStageDefinitionBuilder implements StageDefinitionBuilder { } - class SimpleStage implements com.netflix.spinnaker.orca.api.Stage { + class SimpleStage implements SimpleStage { @Override - public StageOutput execute(StageInput input) { - return new StageOutput(); + public SimpleStageOutput execute(SimpleStageInput input) { + return new SimpleStageOutput(); } @Override diff --git a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/SimpleTaskSpec.groovy similarity index 70% rename from orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy rename to orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/SimpleTaskSpec.groovy index aacbd97ac6..f5ff4d10f0 100644 --- a/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/ApiTaskSpec.groovy +++ b/orca-core/src/test/groovy/com/netflix/spinnaker/orca/pipeline/SimpleTaskSpec.groovy @@ -17,29 +17,29 @@ package com.netflix.spinnaker.orca.pipeline import com.netflix.spinnaker.orca.ExecutionStatus -import com.netflix.spinnaker.orca.api.Stage -import com.netflix.spinnaker.orca.api.StageInput -import com.netflix.spinnaker.orca.api.StageOutput -import com.netflix.spinnaker.orca.api.StageStatus +import com.netflix.spinnaker.orca.api.SimpleStage +import com.netflix.spinnaker.orca.api.SimpleStageInput +import com.netflix.spinnaker.orca.api.SimpleStageOutput +import com.netflix.spinnaker.orca.api.SimpleStageStatus import spock.lang.Specification import spock.lang.Subject import spock.lang.Unroll -class ApiTaskSpec extends Specification { - private static class MyStage implements Stage { +class SimpleTaskSpec extends Specification { + private static class MyStage implements SimpleStage { @Override String getName() { return "myStage" } @Override - StageOutput execute(StageInput input) { - StageOutput output = new StageOutput() + SimpleStageOutput execute(SimpleStageInput input) { + SimpleStageOutput output = new SimpleStageOutput() Map stageOutput = new HashMap<>() stageOutput.put("hello", "world") - output.setStatus(StageStatus.COMPLETED) + output.setStatus(SimpleStageStatus.COMPLETED) output.setOutputs(stageOutput) return output } @@ -51,7 +51,7 @@ class ApiTaskSpec extends Specification { @Unroll def "should check dynamic config property"() { when: - def task = new ApiTask(myStage) + def task = new SimpleTask(myStage) def results = task.execute(new com.netflix.spinnaker.orca.pipeline.model.Stage()) then: diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt index e117f1721d..a6318f4956 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CancelStageHandlerTest.kt @@ -24,7 +24,7 @@ import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver import com.netflix.spinnaker.orca.TaskResolver -import com.netflix.spinnaker.orca.api.Stage +import com.netflix.spinnaker.orca.api.SimpleStage import com.netflix.spinnaker.orca.fixture.pipeline import com.netflix.spinnaker.orca.fixture.stage import com.netflix.spinnaker.orca.pipeline.DefaultStageDefinitionBuilderFactory @@ -57,7 +57,7 @@ object CancelStageHandlerTest : SubjectSpek({ val stageNavigator: StageNavigator = mock() val cancellableStage: CancelableStageDefinitionBuilder = mock() - val stageResolver = StageResolver(listOf(singleTaskStage, cancellableStage), emptyList>()) + val stageResolver = StageResolver(listOf(singleTaskStage, cancellableStage), emptyList>()) subject(GROUP) { CancelStageHandler( diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt index 845e9e7445..8a99d418d4 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/CompleteStageHandlerTest.kt @@ -26,9 +26,10 @@ import com.netflix.spinnaker.orca.ExecutionStatus.STOPPED import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver -import com.netflix.spinnaker.orca.api.StageInput -import com.netflix.spinnaker.orca.api.StageOutput -import com.netflix.spinnaker.orca.api.StageStatus +import com.netflix.spinnaker.orca.api.SimpleStage +import com.netflix.spinnaker.orca.api.SimpleStageInput +import com.netflix.spinnaker.orca.api.SimpleStageOutput +import com.netflix.spinnaker.orca.api.SimpleStageStatus import com.netflix.spinnaker.orca.events.StageComplete import com.netflix.spinnaker.orca.exceptions.DefaultExceptionHandler import com.netflix.spinnaker.orca.exceptions.ExceptionHandler @@ -146,20 +147,20 @@ object CompleteStageHandlerTest : SubjectSpek({ } } - val emptyApiStage = object : com.netflix.spinnaker.orca.api.Stage { + val emptyApiStage = object : SimpleStage { override fun getName() = "emptyApiStage" - override fun execute(input: StageInput): StageOutput { - return StageOutput() + override fun execute(simpleStageInput: SimpleStageInput): SimpleStageOutput { + return SimpleStageOutput() } } - val successfulApiStage = object : com.netflix.spinnaker.orca.api.Stage { + val successfulApiStage = object : SimpleStage { override fun getName() = "successfulApiStage" - override fun execute(input: StageInput): StageOutput { - val output = StageOutput() - output.status = StageStatus.COMPLETED + override fun execute(simpleStageInput: SimpleStageInput): SimpleStageOutput { + val output = SimpleStageOutput() + output.status = SimpleStageStatus.COMPLETED return output } } diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt index 77991205fe..9f90897c3c 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/RestartStageHandlerTest.kt @@ -22,8 +22,9 @@ import com.netflix.spinnaker.orca.ExecutionStatus.RUNNING import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver -import com.netflix.spinnaker.orca.api.StageInput -import com.netflix.spinnaker.orca.api.StageOutput +import com.netflix.spinnaker.orca.api.SimpleStage +import com.netflix.spinnaker.orca.api.SimpleStageInput +import com.netflix.spinnaker.orca.api.SimpleStageOutput import com.netflix.spinnaker.orca.fixture.pipeline import com.netflix.spinnaker.orca.fixture.stage import com.netflix.spinnaker.orca.pipeline.DefaultStageDefinitionBuilderFactory @@ -79,11 +80,11 @@ object RestartStageHandlerTest : SubjectSpek({ val pendingExecutionService: PendingExecutionService = mock() val clock = fixedClock() - val emptyApiStage = object : com.netflix.spinnaker.orca.api.Stage { + val emptyApiStage = object : SimpleStage { override fun getName() = "emptyApiStage" - override fun execute(input: StageInput): StageOutput { - return StageOutput() + override fun execute(simpleStageInput: SimpleStageInput): SimpleStageOutput { + return SimpleStageOutput() } } diff --git a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt index 43830db5a9..bd8439efa0 100644 --- a/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt +++ b/orca-queue/src/test/kotlin/com/netflix/spinnaker/orca/q/handler/StartStageHandlerTest.kt @@ -24,9 +24,10 @@ import com.netflix.spinnaker.orca.ExecutionStatus.RUNNING import com.netflix.spinnaker.orca.ExecutionStatus.SUCCEEDED import com.netflix.spinnaker.orca.ExecutionStatus.TERMINAL import com.netflix.spinnaker.orca.StageResolver -import com.netflix.spinnaker.orca.api.StageInput -import com.netflix.spinnaker.orca.api.StageOutput -import com.netflix.spinnaker.orca.api.StageStatus +import com.netflix.spinnaker.orca.api.SimpleStage +import com.netflix.spinnaker.orca.api.SimpleStageInput +import com.netflix.spinnaker.orca.api.SimpleStageOutput +import com.netflix.spinnaker.orca.api.SimpleStageStatus import com.netflix.spinnaker.orca.events.StageStarted import com.netflix.spinnaker.orca.exceptions.ExceptionHandler import com.netflix.spinnaker.orca.fixture.pipeline @@ -103,12 +104,12 @@ object StartStageHandlerTest : SubjectSpek({ val registry = NoopRegistry() val retryDelay = Duration.ofSeconds(5) - val runningApiStage = object : com.netflix.spinnaker.orca.api.Stage { + val runningApiStage = object : SimpleStage { override fun getName() = "runningApiStage" - override fun execute(input: StageInput): StageOutput { - val output = StageOutput() - output.status = StageStatus.RUNNING + override fun execute(simpleStageInput: SimpleStageInput): SimpleStageOutput { + val output = SimpleStageOutput() + output.status = SimpleStageStatus.RUNNING return output } }