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

This plumbs through the new pipelineNameFilter query param to the front50 service call in gate.
Refer the front50 change: spinnaker/front50#1504
  • Loading branch information
Richard Timpson authored and kirangodishala committed Nov 6, 2024
1 parent e5c4c74 commit 80610dd
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 80610dd

Please sign in to comment.