-
Notifications
You must be signed in to change notification settings - Fork 739
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(web): Adding pipeline template create/read apis (#380)
- Loading branch information
1 parent
b39864b
commit ae721e5
Showing
4 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
126 changes: 126 additions & 0 deletions
126
...b/src/main/groovy/com/netflix/spinnaker/gate/controllers/PipelineTemplatesController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* | ||
* Copyright 2017 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.gate.controllers; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.netflix.spinnaker.gate.services.PipelineTemplateService; | ||
import com.netflix.spinnaker.gate.services.TaskService; | ||
import io.swagger.annotations.ApiOperation; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestMethod; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.ResponseStatus; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@RestController | ||
@RequestMapping(value = "/pipelineTemplates") | ||
public class PipelineTemplatesController { | ||
|
||
// TODO rz - make configurable? | ||
private static final String DEFAULT_APPLICATION = "spinnaker"; | ||
|
||
private PipelineTemplateService pipelineTemplateService; | ||
private TaskService taskService; | ||
private ObjectMapper objectMapper; | ||
|
||
@Autowired | ||
public PipelineTemplatesController(PipelineTemplateService pipelineTemplateService, TaskService taskService, ObjectMapper objectMapper) { | ||
this.pipelineTemplateService = pipelineTemplateService; | ||
this.taskService = taskService; | ||
this.objectMapper = objectMapper; | ||
} | ||
|
||
@ApiOperation(value = "Returns a list of pipeline templates by scope", | ||
notes = "If no scope is provided, 'global' will be defaulted") | ||
@RequestMapping(method = RequestMethod.GET) | ||
public Collection<Map> list(@RequestParam(defaultValue = "global") List<String> scopes) { | ||
return pipelineTemplateService.findByScope(scopes); | ||
} | ||
|
||
@RequestMapping(method = RequestMethod.POST) | ||
@ResponseStatus(value = HttpStatus.ACCEPTED) | ||
public Map create(@RequestBody Map<String, Object> pipelineTemplate) { | ||
List<Map<String, Object>> jobs = new ArrayList<>(); | ||
Map<String, Object> job = new HashMap<>(); | ||
job.put("type", "createPipelineTemplate"); | ||
job.put("pipelineTemplate", pipelineTemplate); | ||
jobs.add(job); | ||
|
||
Map<String, Object> operation = new HashMap<>(); | ||
operation.put("description", "Create pipeline template"); | ||
operation.put("application", getApplicationFromTemplate(pipelineTemplate)); | ||
operation.put("job", jobs); | ||
|
||
return taskService.create(operation); | ||
} | ||
|
||
@RequestMapping(value = "/{id}", method = RequestMethod.GET) | ||
public Map get(@PathVariable String id) { | ||
return pipelineTemplateService.get(id); | ||
} | ||
|
||
@RequestMapping(value = "/{id}", method = RequestMethod.POST) | ||
@ResponseStatus(value = HttpStatus.ACCEPTED) | ||
public Map update(@PathVariable String id, @RequestBody Map<String, Object> pipelineTemplate) { | ||
List<Map<String, Object>> jobs = new ArrayList<>(); | ||
Map<String, Object> job = new HashMap<>(); | ||
job.put("type", "updatePipelineTemplate"); | ||
job.put("id", id); | ||
job.put("pipelineTemplate", pipelineTemplate); | ||
jobs.add(job); | ||
|
||
Map<String, Object> operation = new HashMap<>(); | ||
operation.put("description", "Update pipeline template '" + id + "'"); | ||
operation.put("application", getApplicationFromTemplate(pipelineTemplate)); | ||
operation.put("job", jobs); | ||
|
||
return taskService.create(operation); | ||
} | ||
|
||
private String getApplicationFromTemplate(Map<String, Object> pipelineTemplate) { | ||
PipelineTemplate template; | ||
try { | ||
template = objectMapper.convertValue(pipelineTemplate, PipelineTemplate.class); | ||
} catch (IllegalArgumentException e) { | ||
return DEFAULT_APPLICATION; | ||
} | ||
List<String> scopes = template.metadata.scopes; | ||
return (scopes.isEmpty() || scopes.size() > 1) ? DEFAULT_APPLICATION : scopes.get(0); | ||
} | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
private static class PipelineTemplate { | ||
@JsonProperty | ||
private Metadata metadata = new Metadata(); | ||
|
||
private static class Metadata { | ||
@JsonProperty | ||
private List<String> scopes = new ArrayList<>(); | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
gate-web/src/main/groovy/com/netflix/spinnaker/gate/services/PipelineTemplateService.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright 2017 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.gate.services | ||
|
||
import com.netflix.spinnaker.gate.services.internal.Front50Service | ||
import groovy.transform.CompileStatic | ||
import groovy.util.logging.Slf4j | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.stereotype.Component | ||
|
||
@CompileStatic | ||
@Component | ||
@Slf4j | ||
class PipelineTemplateService { | ||
|
||
private static final String GROUP = "pipelineTemplates"; | ||
|
||
private final Front50Service front50Service; | ||
|
||
@Autowired | ||
public PipelineTemplateService(Front50Service front50Service) { | ||
this.front50Service = front50Service; | ||
} | ||
|
||
Map get(String id) { | ||
front50Service.getPipelineTemplate(id) | ||
} | ||
|
||
List<Map> findByScope(List<String> scopes) { | ||
front50Service.getPipelineTemplates((String[]) scopes.toArray()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
.../test/groovy/com/netflix/spinnaker/gate/controllers/PipelineTemplateControllerSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright 2017 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.gate.controllers | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.netflix.spinnaker.gate.services.PipelineTemplateService | ||
import com.netflix.spinnaker.gate.services.TaskService | ||
import org.springframework.test.web.servlet.MockMvc | ||
import org.springframework.test.web.servlet.setup.MockMvcBuilders | ||
import spock.lang.Specification | ||
import spock.lang.Unroll | ||
|
||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post | ||
|
||
import javax.ws.rs.core.MediaType | ||
|
||
class PipelineTemplateControllerSpec extends Specification { | ||
|
||
@Unroll | ||
def "should inflect job application from pipeline template metadata"() { | ||
given: | ||
def pipelineTemplateService = Mock(PipelineTemplateService) | ||
def taskService = Mock(TaskService) | ||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new PipelineTemplatesController(pipelineTemplateService, taskService, new ObjectMapper())).build() | ||
|
||
and: | ||
def pipelineTemplate = [ | ||
id: 'foo', | ||
metadata: metadata, | ||
configuration: [:] | ||
] | ||
|
||
when: | ||
def response = mockMvc.perform( | ||
post("/pipelineTemplates").contentType(MediaType.APPLICATION_JSON) | ||
.content(new ObjectMapper().writeValueAsString(pipelineTemplate)) | ||
).andReturn().response | ||
|
||
then: | ||
response.status == 202 | ||
1 * taskService.create([ | ||
application: app, | ||
description: "Create pipeline template", | ||
job: [ | ||
[ | ||
type: 'createPipelineTemplate', | ||
pipelineTemplate: [ | ||
id: 'foo', | ||
metadata: metadata, | ||
configuration: [:] | ||
] | ||
] | ||
] | ||
]) >> { [ref: 'taskref'] } | ||
|
||
where: | ||
metadata << [ | ||
[scopes: ['foo']], | ||
[:] | ||
] | ||
app << ['foo', 'spinnaker'] | ||
} | ||
} |