Skip to content

Commit

Permalink
test(sql): Add extra test for pipelineRef feature flag (#4760)
Browse files Browse the repository at this point in the history
* test(sql): add extra tests in ExecutionLauncher for pipelineRef

* style(sql): include comments to explain reason behind custom deserializer

* test(Executionlauncher): rename tests without implementation details.

---------

Co-authored-by: Jason <[email protected]>
  • Loading branch information
edgarulg and jasonmcintosh committed Jul 16, 2024
1 parent ccaeb0a commit f28f295
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
1 change: 1 addition & 0 deletions orca-core/orca-core.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {

testImplementation(project(":orca-test"))
testImplementation(project(":orca-test-groovy"))
testImplementation(project(":orca-sql"))
testImplementation("com.github.tomakehurst:wiremock-jre8-standalone")
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.assertj:assertj-core")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType;
import com.netflix.spinnaker.orca.api.pipeline.models.PipelineExecution;
import com.netflix.spinnaker.orca.config.ExecutionConfigurationProperties;
import com.netflix.spinnaker.orca.jackson.OrcaObjectMapper;
import com.netflix.spinnaker.orca.pipeline.model.PipelineTrigger;
import com.netflix.spinnaker.orca.pipeline.model.support.TriggerDeserializer;
import com.netflix.spinnaker.orca.pipeline.persistence.ExecutionRepository;
import com.netflix.spinnaker.orca.sql.PipelineRefTriggerDeserializerSupplier;
import com.netflix.spinnaker.orca.sql.pipeline.persistence.PipelineRefTrigger;
import com.netflix.spinnaker.orca.test.YamlFileApplicationContextInitializer;
import java.time.Clock;
import java.util.Map;
Expand Down Expand Up @@ -332,6 +337,120 @@ public void testExcludeSpinnakerAccountsFromPipeline() throws Exception {
assertThat(pipelineExecution.getAuthentication().getAllowedAccounts()).isEqualTo(Set.of());
}

@DisplayName(
"ExecutionLauncher can start a new execution when a customerTriggerSupplier is provided")
@Test
public void testPipelineRefCanBeDeserializeWhenEnabled() throws Exception {
// create the orcaObjectMapper to be able to deserialize triggers
ObjectMapper orcaMapper = OrcaObjectMapper.getInstance();
// add the Custom Trigger Deserializer for PipelineRef
TriggerDeserializer.Companion.getCustomTriggerSuppliers().clear();
TriggerDeserializer.Companion.getCustomTriggerSuppliers()
.add(new PipelineRefTriggerDeserializerSupplier(true));
// setup
executionLauncher =
new ExecutionLauncher(
orcaMapper,
executionRepository,
executionRunner,
clock,
applicationEventPublisher,
pipelineValidator,
registry,
executionConfigurationProperties);

// when
// childPipeline pipeline type should be able to run
PipelineExecution pipelineExecution =
executionLauncher.start(
ExecutionType.PIPELINE, getConfigJson("ad-hoc/pipeline-with-pipeline-trigger.json"));

// then
// verify that the execution runner attempted to start the execution as expected
verify(executionRunner).start(pipelineExecution);
// verify that the PipelineTrigger is deserialized as PipelineRef
assertThat(pipelineExecution.getTrigger()).isInstanceOf(PipelineRefTrigger.class);
// verify that no errors were thrown such as the explicitly disabled ones
verify(executionRepository, never()).updateStatus(any(), anyString(), any());
verify(executionRepository, never()).cancel(any(), anyString(), anyString(), anyString());
}

@DisplayName(
"ExecutionLauncher can start a new execution and the state of the trigger does not change when a customerTriggerSupplier is provided")
@Test
public void testPipelineTriggerIsNotDeserializedIntoPipelineRefWhenDisabled() throws Exception {
// create the orcaObjectMapper to be able to deserialize triggers
ObjectMapper orcaMapper = OrcaObjectMapper.getInstance();
// add the Custom Trigger Deserializer for PipelineRef
TriggerDeserializer.Companion.getCustomTriggerSuppliers().clear();
TriggerDeserializer.Companion.getCustomTriggerSuppliers()
.add(new PipelineRefTriggerDeserializerSupplier(false));
// setup
executionLauncher =
new ExecutionLauncher(
orcaMapper,
executionRepository,
executionRunner,
clock,
applicationEventPublisher,
pipelineValidator,
registry,
executionConfigurationProperties);

// when
// childPipeline pipeline type should be able to run
PipelineExecution pipelineExecution =
executionLauncher.start(
ExecutionType.PIPELINE, getConfigJson("ad-hoc/pipeline-with-pipeline-trigger.json"));

// then
// verify that the execution runner attempted to start the execution as expected
verify(executionRunner).start(pipelineExecution);
// verify that the execution has PipelineTrigger
assertThat(pipelineExecution.getTrigger()).isInstanceOf(PipelineTrigger.class);
// verify that no errors were thrown such as the explicitly disabled ones
verify(executionRepository, never()).updateStatus(any(), anyString(), any());
verify(executionRepository, never()).cancel(any(), anyString(), anyString(), anyString());
}

@DisplayName(
"ExecutionLauncher can start a new execution and process special triggers when a customerTriggerSupplier is provided")
@Test
public void testPipelineRefTriggerCanBeDeserializedEvenDisabled() throws Exception {
// create the orcaObjectMapper to be able to deserialize triggers
ObjectMapper orcaMapper = OrcaObjectMapper.getInstance();
// add the Custom Trigger Deserializer for PipelineRef
TriggerDeserializer.Companion.getCustomTriggerSuppliers().clear();
TriggerDeserializer.Companion.getCustomTriggerSuppliers()
.add(new PipelineRefTriggerDeserializerSupplier(false));
// setup
executionLauncher =
new ExecutionLauncher(
orcaMapper,
executionRepository,
executionRunner,
clock,
applicationEventPublisher,
pipelineValidator,
registry,
executionConfigurationProperties);

// when
// childPipeline pipeline type should be able to run
PipelineExecution pipelineExecution =
executionLauncher.start(
ExecutionType.PIPELINE, getConfigJson("ad-hoc/pipeline-with-pipelineRef-trigger.json"));

// then
// verify that the execution runner attempted to start the execution as expected
verify(executionRunner).start(pipelineExecution);
// verify that the PipelineTrigger is deserialized as PipelineRef
assertThat(pipelineExecution.getTrigger()).isInstanceOf(PipelineRefTrigger.class);
// verify that no errors were thrown such as the explicitly disabled ones
verify(executionRepository, never()).updateStatus(any(), anyString(), any());
verify(executionRepository, never()).cancel(any(), anyString(), anyString(), anyString());
}

private Map<String, Object> getConfigJson(String resource) throws Exception {
return objectMapper.readValue(
ExecutionLauncherTest.class.getResourceAsStream(resource), Map.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"application":"edgartest",
"name":"wait stage",
"stages": [
{
"name": "Wait",
"refId": "1",
"requisiteStageRefIds": [],
"type": "wait",
"waitTime": 30
}
],
"trigger": {
"type": "pipeline",
"parentExecution": {
"application": "edgartest",
"id": "parentID",
"stages": [
{
"name": "Wait",
"refId": "1",
"requisiteStageRefIds": [],
"type": "wait",
"waitTime": 30
}
]
}
},
"origin":"api"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"application":"edgartest",
"name":"wait stage",
"stages": [
{
"name": "Wait",
"refId": "1",
"requisiteStageRefIds": [],
"type": "wait",
"waitTime": 30
}
],
"trigger": {
"type": "pipelineRef",
"parentExecutionId": "parentID"
},
"origin":"api"
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ class PipelineRefTriggerDeserializerSupplier(

override val predicate: (node: JsonNode) -> Boolean
get() = { node ->
// We need to deserialize always PipelineRef because
// 1. There is a single object mapper use for serialize/deserialize in
// multiple places (OperationsController, ExecutionLauncher, SqlExecutionRepository)
// 2. Insert executions with trigger works properly but update an existing execution fails because
// SqlExecutionRepository gets execution from database (deserialize) and we convert PipelineRef in its
// In-memory representation. This makes the SqlExecutionRepository to try to store again all execution
// context. We need to deserialize again to transform into PipelineRef properly.
if (pipelineRefEnabled) {
node.looksLikePipeline() || node.isPipelineRefTrigger() //if pipelineRef enabled we deserialize PipelineTrigger as PipelineRefTrigger
} else {
Expand Down

0 comments on commit f28f295

Please sign in to comment.