Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(web): Retrieve dependent pipelines correctly #1459

Merged
merged 3 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import com.netflix.spinnaker.front50.model.pipeline.PipelineDAO;
import com.netflix.spinnaker.front50.model.pipeline.PipelineTemplate;
import com.netflix.spinnaker.front50.model.pipeline.PipelineTemplateDAO;
import com.netflix.spinnaker.front50.model.pipeline.TemplateConfiguration;
import com.netflix.spinnaker.front50.model.pipeline.V2TemplateConfiguration;
import com.netflix.spinnaker.kork.web.exceptions.NotFoundException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
Expand Down Expand Up @@ -186,22 +186,22 @@ List<String> getDependentConfigs(String templateId) {
List<String> dependentConfigIds = new ArrayList<>();

String prefixedId = SPINNAKER_PREFIX + templateId;

pipelineDAO.all().stream()
.filter(pipeline -> pipeline.getType() != null && pipeline.getType().equals(TYPE_TEMPLATED))
.forEach(
templatedPipeline -> {
String source;
try {
TemplateConfiguration config =
objectMapper.convertValue(
templatedPipeline.getConfig(), TemplateConfiguration.class);

source = config.getPipeline().getTemplate().getSource();
V2TemplateConfiguration config =
objectMapper.convertValue(templatedPipeline, V2TemplateConfiguration.class);
source = config.getTemplate().getReference();
} catch (Exception e) {
return;
}

if (source != null && source.equalsIgnoreCase(prefixedId)) {
if (source != null && source.startsWith(prefixedId)) {
dependentConfigIds.add(templatedPipeline.getId());
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@

package com.netflix.spinnaker.front50.controllers

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.front50.exceptions.InvalidEntityException
import static com.netflix.spinnaker.front50.api.model.pipeline.Pipeline.TYPE_TEMPLATED;
import static com.netflix.spinnaker.front50.model.pipeline.TemplateConfiguration.TemplateSource.SPINNAKER_PREFIX;
import com.netflix.spinnaker.front50.api.model.pipeline.Pipeline;
import com.netflix.spinnaker.front50.model.pipeline.V2TemplateConfiguration;
import com.netflix.spinnaker.front50.model.pipeline.PipelineDAO
import com.netflix.spinnaker.front50.model.pipeline.PipelineTemplate
import com.netflix.spinnaker.front50.model.pipeline.PipelineTemplateDAO
import com.netflix.spinnaker.front50.model.pipeline.TemplateConfiguration
import spock.lang.Specification
import spock.lang.Subject
import spock.lang.Unroll
Expand All @@ -34,7 +40,9 @@ class V2PipelineTemplateControllerSpec extends Specification {
def controller = new V2PipelineTemplateController(
pipelineDAO: pipelineDAO,
pipelineTemplateDAO: pipelineTemplateDAO,
objectMapper: new ObjectMapper(),
// V2TemplateConfiguration doesn't expect `id` attribute as part of pipeline config.
// Hence has to ignore unknown properties when converting the value.
objectMapper: new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
)

def template1 = [
Expand Down Expand Up @@ -156,6 +164,102 @@ class V2PipelineTemplateControllerSpec extends Specification {
hash1 == hash2
}

def "verify retrieval of templated pipeline config using v1 approach results in null"() {
given:

def templatedPipeline = new Pipeline(
id: "id-of-my-templated-pipeline",
name: "name-of-my-templated-pipeline",
application: "application",
type: TYPE_TEMPLATED,
schema: "v2",
template: [
reference: SPINNAKER_PREFIX + "myPipelineTemplateId"
]
)
def oneOtherTemplatedPipeline = new Pipeline(
id: "id-of-one-other-templated-pipeline",
name: "name-of-one-other-templated-pipeline",
application: "application",
type: TYPE_TEMPLATED,
schema: "v2",
template: [
reference: SPINNAKER_PREFIX + "oneOtherPipelineTemplateId"
]
)

pipelineDAO.all() >> [templatedPipeline, oneOtherTemplatedPipeline]

when:
TemplateConfiguration config = controller.objectMapper.convertValue(
templatedPipeline.getConfig(), TemplateConfiguration.class);

then:
config == null
}

def "getDependentConfigs returns empty list when there are no templated pipelines"() {
given:
pipelineDAO.all() >> []

when:
List<String> dependentConfigIds = controller.getDependentConfigs("myPipelineTemplateId")

then:
dependentConfigIds.isEmpty()
}

def "getDependentConfigs returns empty list when templated pipelines have no dependencies"() {
given:
Pipeline normalPipeline = new Pipeline()
Pipeline templatedPipeline = new Pipeline(id: "id-of-my-templated-pipeline", type: TYPE_TEMPLATED)
pipelineDAO.all() >> [normalPipeline, templatedPipeline]

when:
List<String> dependentConfigIds = controller.getDependentConfigs("a-different-pipeline-template-id")

then:
dependentConfigIds.isEmpty()
}

def "getDependentConfigs returns list of dependent pipeline IDs"() {
given:

def normalPipeline = new Pipeline(
id: "normalPipeline",
name: "normalPipeline",
application: "application",
)
def templatedPipeline = new Pipeline(
id: "id-of-my-templated-pipeline",
name: "name-of-my-templated-pipeline",
application: "application",
type: TYPE_TEMPLATED,
schema: "v2",
template: [
reference: SPINNAKER_PREFIX + "myPipelineTemplateId"
]
)
def oneOtherTemplatedPipeline = new Pipeline(
id: "id-of-one-other-templated-pipeline",
name: "name-of-one-other-templated-pipeline",
application: "application",
type: TYPE_TEMPLATED,
schema: "v2",
template: [
reference: SPINNAKER_PREFIX + "oneOtherPipelineTemplateId"
]
)

pipelineDAO.all() >> [normalPipeline, templatedPipeline, oneOtherTemplatedPipeline]

when:
List<String> dependentConfigIds = controller.getDependentConfigs("myPipelineTemplateId")

then:
dependentConfigIds == ["id-of-my-templated-pipeline"]
}

@Unroll
def 'should fail with InvalidEntityException if Id(#id) is not provided or empty'() {
when:
Expand All @@ -168,4 +272,3 @@ class V2PipelineTemplateControllerSpec extends Specification {
id << [null, "", " "]
}
}