Skip to content

Commit

Permalink
feat(pipelines): add pipelineNameFilter to /{application}/pipelineCon…
Browse files Browse the repository at this point in the history
…figs endpoint (#1839)

This plumbs through the new pipelineNameFilter query param to the front50 service call in gate.
Refer the front50 change: spinnaker/front50#1504

Co-authored-by: Richard Timpson <richard.timpson@salesforce.com>
  • Loading branch information
kirangodishala and Richard Timpson authored Nov 6, 2024
1 parent e5c4c74 commit c294ae6
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ List<Map> getApplicationHistory(

@GET("/pipelines/{app}")
List<Map> getPipelineConfigsForApplication(
@Path("app") String app, @Query("refresh") boolean refresh);
@Path("app") String app,
@Query("pipelineNameFilter") String pipelineNameFilter,
@Query("refresh") boolean refresh);

@GET("/pipelines/{app}/name/{name}")
Map getPipelineConfigByApplicationAndName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ class ApplicationController {

@ApiOperation(value = "Retrieve a list of an application's pipeline configurations", response = List.class)
@RequestMapping(value = "/{application}/pipelineConfigs", method = RequestMethod.GET)
List getPipelineConfigsForApplication(@PathVariable("application") String application) {
applicationService.getPipelineConfigsForApplication(application)
List getPipelineConfigsForApplication(@PathVariable("application") String application,
@RequestParam(required = false, value="pipelineNameFilter") String pipelineNameFilter) {
applicationService.getPipelineConfigsForApplication(application, pipelineNameFilter)
}

@ApiOperation(value = "Retrieve a pipeline configuration", response = HashMap.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class PipelineController {
@ApiOperation(value = "Delete a pipeline definition")
@DeleteMapping("/{application}/{pipelineName:.+}")
void deletePipeline(@PathVariable String application, @PathVariable String pipelineName) {
List<Map> pipelineConfigs = front50Service.getPipelineConfigsForApplication(application, true)
List<Map> pipelineConfigs = front50Service.getPipelineConfigsForApplication(application, null, true)
if (pipelineConfigs!=null && !pipelineConfigs.isEmpty()){
Optional<Map> filterResult = pipelineConfigs.stream().filter({ pipeline -> ((String) pipeline.get("name")) != null && ((String) pipeline.get("name")).trim().equalsIgnoreCase(pipelineName) }).findFirst()
if (filterResult.isPresent()){
Expand Down Expand Up @@ -220,7 +220,7 @@ class PipelineController {
)
}

return front50Service.getPipelineConfigsForApplication((String) pipeline.get("application"), true)?.find {
return front50Service.getPipelineConfigsForApplication((String) pipeline.get("application"), null, true)?.find {
id == (String) it.get("id")
}
}
Expand Down Expand Up @@ -259,7 +259,7 @@ class PipelineController {
String pipelineName = pipelineMap.get("name");
String application = pipelineMap.get("application");

List<Map> pipelineConfigs = front50Service.getPipelineConfigsForApplication(application, true)
List<Map> pipelineConfigs = front50Service.getPipelineConfigsForApplication(application, null, true)

if (pipelineConfigs!=null && !pipelineConfigs.isEmpty()){
Optional<Map> filterResult = pipelineConfigs.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ class ApplicationService {
}

List<Map> getPipelineConfigsForApplication(String app) {
return front50Service.getPipelineConfigsForApplication(app, true)
return getPipelineConfigsForApplication(app, null);
}

List<Map> getPipelineConfigsForApplication(String app, String pipelineNameFilter) {
return front50Service.getPipelineConfigsForApplication(app, pipelineNameFilter, true)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,24 @@

package com.netflix.spinnaker.gate.controllers

import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.gate.config.ApplicationConfigurationProperties
import com.netflix.spinnaker.gate.config.ServiceConfiguration
import com.netflix.spinnaker.gate.services.ApplicationService
import com.netflix.spinnaker.gate.services.internal.ClouddriverService
import com.netflix.spinnaker.gate.services.internal.ClouddriverServiceSelector
import com.netflix.spinnaker.gate.services.internal.Front50Service
import com.squareup.okhttp.mockwebserver.MockWebServer
import groovy.json.JsonSlurper
import org.springframework.http.MediaType
import org.springframework.mock.web.MockHttpServletResponse
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.util.NestedServletException
import spock.lang.Specification
import spock.lang.Unroll

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

class ApplicationControllerSpec extends Specification {

Expand Down Expand Up @@ -62,9 +63,66 @@ class ApplicationControllerSpec extends Specification {
mockMvc = MockMvcBuilders.standaloneSetup(new ApplicationController(applicationService: applicationService)).build()
}

@Unroll
void 'should return configs for an application' (){
given: "random configs"
def configs = [
[
name: 'pipelineA',
some: 'some-random-x',
],
[
name: 'pipelineB',
some: 'some-random-F',
],
]

when: "all configs are requested"
def response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON))

then: "we only call front50 once, and do not pass through the pipelineNameFilter"
1 * front50Service.getPipelineConfigsForApplication('true-app', null, true) >> configs
0 * front50Service._

and: "we get all configs"
response.andExpect status().isOk()
response.andExpect content().string(new ObjectMapper().writeValueAsString(configs))

where:
endpoint << ["/applications/true-app/pipelineConfigs"]
}

@Unroll
void 'should return configs for an application with pipelineNameFilter' (){
given: "only one config"
def configs = [
[
name: 'pipelineA',
some: 'some-random-x',
],
]

when: "configs are requested with a filter"
def response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON))

then: "we only call front50 once, and we do pass through the pipelineNameFilter"
1 * front50Service.getPipelineConfigsForApplication('true-app', 'pipelineA', true) >> configs
0 * front50Service._

and: "only filtered configs are returned"
response.andExpect status().isOk()
response.andExpect content().string(new ObjectMapper().writeValueAsString(configs))

where:
endpoint << ["/applications/true-app/pipelineConfigs?pipelineNameFilter=pipelineA"]
}


@Unroll
void 'should return 200 with info on pipeline that exists with config' (){
given:
def configs = [
[
name: 'some-true-pipeline',
Expand All @@ -77,35 +135,34 @@ class ApplicationControllerSpec extends Specification {
someY: 'some-random-Z'
],
]
given:
1 * front50Service.getPipelineConfigsForApplication('true-app', true) >> configs
when:
MockHttpServletResponse response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON)).andReturn().response
def response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON))

then:
new JsonSlurper().parseText(response.contentAsString) == configs[0]
response.status == 200
1 * front50Service.getPipelineConfigsForApplication('true-app', null, true) >> configs
response.andExpect status().isOk()
response.andExpect content().string(new ObjectMapper().writeValueAsString(configs[0]))

where:
endpoint << ["/applications/true-app/pipelineConfigs/some-true-pipeline"]
}

@Unroll
void 'should return 404 on pipeline that does not exists' (){
given:
def configs = [
[
name: 'some-true-pipeline',
some: 'some-random-x',
someY: 'some-random-y'
]
]
given:
1 * front50Service.getPipelineConfigsForApplication('true-app', true) >> configs
when:
mockMvc.perform(get(endpoint))

then:
1 * front50Service.getPipelineConfigsForApplication('true-app', null, true) >> configs
NestedServletException ex = thrown()
ex.message.contains('Pipeline config (id: some-fake-pipeline) not found for Application (id: true-app)')

Expand All @@ -115,6 +172,7 @@ class ApplicationControllerSpec extends Specification {

@Unroll
void 'should return 200 with strategy configuration for strategy exists' (){
given:
def configs = [
[
name: 'some-true-strategy',
Expand All @@ -127,35 +185,34 @@ class ApplicationControllerSpec extends Specification {
someY: 'some-random-Z'
],
]
given:
1 * front50Service.getStrategyConfigs('true-app') >> configs
when:
MockHttpServletResponse response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON)).andReturn().response
def response = mockMvc.perform(get(endpoint)
.accept(MediaType.APPLICATION_JSON))

then:
new JsonSlurper().parseText(response.contentAsString) == configs[0]
response.status == 200
1 * front50Service.getStrategyConfigs('true-app') >> configs
response.andExpect status().isOk()
response.andExpect content().string(new ObjectMapper().writeValueAsString(configs[0]))

where:
endpoint << ["/applications/true-app/strategyConfigs/some-true-strategy"]
}

@Unroll
void 'should return 404 with strategy configuration for strategy not exists' (){
given:
def configs = [
[
name: 'some-true-strategy',
some: 'some-random-x',
someY: 'some-random-y'
]
]
given:
1 * front50Service.getStrategyConfigs('true-app') >> configs
when:
mockMvc.perform(get(endpoint))

then:
1 * front50Service.getStrategyConfigs('true-app') >> configs
NestedServletException ex = thrown()
ex.message.contains('Strategy config (id: some-fake-strategy) not found for Application (id: true-app)')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class PipelineControllerSpec extends Specification {
]
]
]) >> { [id: 'task-id', application: 'application', status: 'SUCCEEDED'] }
1 * front50Service.getPipelineConfigsForApplication('application', true) >> []
1 * front50Service.getPipelineConfigsForApplication('application', null, true) >> []
}

def "should propagate pipeline template errors"() {
Expand Down

0 comments on commit c294ae6

Please sign in to comment.