2 * Copyright © 2019 Bell Canada Intellectual Property.
3 * Modifications Copyright © 2019 IBM.
4 * Modifications Copyright © 2019 Orange.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
21 import io.swagger.annotations.ApiOperation
22 import io.swagger.annotations.Api
23 import io.swagger.annotations.ApiParam
24 import io.swagger.annotations.ApiResponse
25 import io.swagger.annotations.ApiResponses
26 import org.jetbrains.annotations.NotNull
27 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSearch
28 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintModelHandler
29 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BlueprintSortByOption
30 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.mdcWebCoroutineScope
31 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
32 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString
33 import org.springframework.core.io.Resource
34 import org.springframework.data.domain.Page
35 import org.springframework.data.domain.PageRequest
36 import org.springframework.data.domain.Sort
37 import org.springframework.http.HttpStatus
38 import org.springframework.http.MediaType
39 import org.springframework.http.ResponseEntity
40 import org.springframework.http.codec.multipart.FilePart
41 import org.springframework.security.access.prepost.PreAuthorize
42 import org.springframework.web.bind.annotation.DeleteMapping
43 import org.springframework.web.bind.annotation.GetMapping
44 import org.springframework.web.bind.annotation.PathVariable
45 import org.springframework.web.bind.annotation.PostMapping
46 import org.springframework.web.bind.annotation.RequestBody
47 import org.springframework.web.bind.annotation.RequestMapping
48 import org.springframework.web.bind.annotation.RequestParam
49 import org.springframework.web.bind.annotation.RequestPart
50 import org.springframework.web.bind.annotation.ResponseBody
51 import org.springframework.web.bind.annotation.RestController
54 * BlueprintModelController Purpose: Handle controllerBlueprint API request
60 @RequestMapping("/api/v1/blueprint-model")
62 value = "Blueprint Model Catalog API",
63 description = "Manages all blueprint models which are available in CDS"
65 open class BlueprintModelController(private val bluePrintModelHandler: BluePrintModelHandler) {
68 path = arrayOf("/bootstrap"), produces = arrayOf(MediaType.APPLICATION_JSON_VALUE),
69 consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE)
72 value = "Bootstrap CDS",
73 notes = "Loads all Model Types, Resource Dictionaries and Blueprint Models which are included in CDS by default. " +
74 "Before starting to work with CDS, bootstrap should be called to load all the basic models that each orginization might support. " +
75 "Parameter values can be set as `false` to skip loading e.g. the Resource Dictionaries but this is not recommended."
78 ApiResponse(code = 200, message = "OK"),
79 ApiResponse(code = 500, message = "Internal Server Error")
82 @Throws(BluePrintException::class)
83 @PreAuthorize("hasRole('USER')")
84 suspend fun bootstrap(
85 @ApiParam(required = true, value = "Specifies which elements to load")
86 @RequestBody bootstrapRequest: BootstrapRequest
87 ): Unit = mdcWebCoroutineScope {
88 bluePrintModelHandler.bootstrapBlueprint(bootstrapRequest)
91 @PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
93 value = "Save a Blueprint Model",
94 notes = "Saves a blueprint model by the given CBA zip file input. " +
95 "There is no validation of the attached CBA happening when this API is called.",
96 response = BlueprintModelSearch::class
99 ApiResponse(code = 200, message = "OK"),
100 ApiResponse(code = 500, message = "Internal Server Error")
103 @Throws(BluePrintException::class)
104 @PreAuthorize("hasRole('USER')")
105 suspend fun saveBlueprint(
106 @ApiParam(name = "file", value = "CBA file to be uploaded (example: cba.zip)", required = true)
107 @RequestPart("file") filePart: FilePart
108 ): BlueprintModelSearch = mdcWebCoroutineScope {
109 bluePrintModelHandler.saveBlueprintModel(filePart)
112 @GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
114 value = "List all Blueprint Models",
115 notes = "Lists all meta-data of blueprint models which are saved in CDS."
118 ApiResponse(code = 200, message = "OK"),
119 ApiResponse(code = 500, message = "Internal Server Error")
122 @PreAuthorize("hasRole('USER')")
123 fun allBlueprintModel(): List<BlueprintModelSearch> {
124 return this.bluePrintModelHandler.allBlueprintModel()
127 @GetMapping("/paged", produces = [MediaType.APPLICATION_JSON_VALUE])
129 value = "Get Blueprints ordered",
130 notes = "Lists all blueprint models which are saved in CDS in an ordered mode.",
131 nickname = "BlueprintModelController_allBlueprintModelPaged_GET.org.onap.ccsdk.cds.blueprintsprocessor.designer.api"
134 @PreAuthorize("hasRole('USER')")
135 fun allBlueprintModel(
136 @ApiParam(value = "Maximum number of returned blueprint models") @RequestParam(defaultValue = "20") limit: Int,
137 @ApiParam(value = "Offset") @RequestParam(defaultValue = "0") offset: Int,
138 @ApiParam(value = "Order of returned blueprint models") @RequestParam(defaultValue = "DATE") sort: BlueprintSortByOption,
139 @ApiParam(value = "Ascend or descend ordering") @RequestParam(defaultValue = "ASC") sortType: String
140 ): Page<BlueprintModelSearch> {
141 val pageRequest = PageRequest.of(
143 Sort.Direction.fromString(sortType), sort.columnName
145 return this.bluePrintModelHandler.allBlueprintModel(pageRequest)
148 @GetMapping("meta-data/{keyword}", produces = [MediaType.APPLICATION_JSON_VALUE])
150 value = "Search for Blueprints by a Keyword",
151 notes = "Lists all blueprint models by a matching keyword in any of the meta-data of the blueprint models. " +
152 "Blueprint models are just returned if a whole keyword is matching, not just parts of it. Not case-sensitive. " +
154 responseContainer = "List",
155 response = BlueprintModelSearch::class
158 @PreAuthorize("hasRole('USER')")
159 suspend fun allBlueprintModelMetaData(
161 @ApiParam(value = "Keyword to search for in blueprint model meta-data", required = true, example = "pnf_netconf")
162 @PathVariable(value = "keyword") keyWord: String
163 ): List<BlueprintModelSearch> =
164 mdcWebCoroutineScope {
165 bluePrintModelHandler.searchBluePrintModelsByKeyWord(keyWord)
168 @GetMapping("/paged/meta-data/{keyword}", produces = [MediaType.APPLICATION_JSON_VALUE])
170 value = "Search for Blueprints by a Keyword in an ordered mode",
171 notes = "Lists all blueprint models by a matching keyword in any of the meta-data of the blueprint models in an ordered mode. " +
172 "Blueprint models are just returned if a whole keyword is matching, not just parts of it. Not case-sensitive. " +
176 @PreAuthorize("hasRole('USER')")
177 fun allBlueprintModelMetaDataPaged(
178 @ApiParam(value = "Keyword to search for in blueprint model meta-data", required = true, example = "pnf_netconf")
179 @NotNull @PathVariable(value = "keyword") keyWord: String,
180 @ApiParam(value = "Maximum number of returned blueprint models") @RequestParam(defaultValue = "20") limit: Int,
181 @ApiParam(value = "Offset") @RequestParam(defaultValue = "0") offset: Int,
182 @ApiParam(value = "Order of returned blueprint models") @RequestParam(defaultValue = "DATE") sort: BlueprintSortByOption,
183 @ApiParam(value = "Ascend or descend ordering") @RequestParam(defaultValue = "ASC") sortType: String
184 ): Page<BlueprintModelSearch> {
185 val pageRequest = PageRequest.of(
187 Sort.Direction.fromString(sortType), sort.columnName
189 return this.bluePrintModelHandler.searchBluePrintModelsByKeyWordPaged(keyWord, pageRequest)
192 @DeleteMapping("/{id}")
194 value = "Delete a Blueprint Model by ID",
195 notes = "Delete a blueprint model by its ID. ID is the internally created ID of blueprint, not the name of blueprint."
198 ApiResponse(code = 200, message = "OK"),
199 ApiResponse(code = 404, message = "RESOURCE_NOT_FOUND")
201 @Throws(BluePrintException::class)
202 @PreAuthorize("hasRole('USER')")
203 suspend fun deleteBlueprint(
204 @ApiParam(value = "ID of the blueprint model to delete", required = true, example = "67ec1f96-ab55-4b81-aff9-23ee0ed1d7a4")
205 @PathVariable(value = "id") id: String
206 ) = mdcWebCoroutineScope {
207 bluePrintModelHandler.deleteBlueprintModel(id)
210 @GetMapping("/by-name/{name}/version/{version}", produces = [MediaType.APPLICATION_JSON_VALUE])
212 value = "Get a Blueprint Model by Name and Version",
213 notes = "Get Meta-Data of a Blueprint Model by its name and version.",
214 response = BlueprintModelSearch::class
217 ApiResponse(code = 200, message = "OK"),
218 ApiResponse(code = 404, message = "Not Found")
221 @Throws(BluePrintException::class)
222 @PreAuthorize("hasRole('USER')")
223 suspend fun getBlueprintByNameAndVersion(
224 @ApiParam(value = "Name of the blueprint model", required = true, example = "pnf_netconf") @PathVariable(value = "name") name: String,
225 @ApiParam(value = "Version of the blueprint model", required = true, example = "1.0.0") @PathVariable(value = "version") version: String
226 ): ResponseEntity<BlueprintModelSearch> = mdcWebCoroutineScope {
227 val bluePrintModel: BlueprintModelSearch? =
228 bluePrintModelHandler.getBlueprintModelSearchByNameAndVersion(name, version)
229 if (bluePrintModel != null)
230 ResponseEntity(bluePrintModel, HttpStatus.OK)
232 ResponseEntity(HttpStatus.NO_CONTENT)
235 @GetMapping("/download/by-name/{name}/version/{version}", produces = [MediaType.APPLICATION_JSON_VALUE])
237 value = "Download a Blueprint Model",
238 notes = "Gets the CBA of a blueprint model by its name and version. Response can be saved to a file to download the CBA."
241 ApiResponse(code = 200, message = "OK"),
242 ApiResponse(code = 404, message = "Not Found")
245 @Throws(BluePrintException::class)
246 @PreAuthorize("hasRole('USER')")
247 suspend fun downloadBlueprintByNameAndVersion(
248 @ApiParam(value = "Name of the blueprint model", required = true, example = "pnf_netconf") @PathVariable(value = "name") name: String,
249 @ApiParam(value = "Version of the blueprint model", required = true, example = "1.0.0") @PathVariable(value = "version") version: String
250 ): ResponseEntity<Resource> = mdcWebCoroutineScope {
251 bluePrintModelHandler.downloadBlueprintModelFileByNameAndVersion(name, version)
254 @GetMapping("/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
256 value = "Get a Blueprint Model by ID",
257 notes = "Get meta-data of a blueprint model by its internally created ID.",
258 response = BlueprintModelSearch::class
261 ApiResponse(code = 200, message = "OK"),
262 ApiResponse(code = 404, message = "Not Found")
265 @Throws(BluePrintException::class)
266 @PreAuthorize("hasRole('USER')")
267 suspend fun getBlueprintModel(
268 @ApiParam(value = "ID of the blueprint model to search for", required = true, example = "67ec1f96-ab55-4b81-aff9-23ee0ed1d7a4")
269 @PathVariable(value = "id") id: String
270 ): BlueprintModelSearch = mdcWebCoroutineScope {
271 bluePrintModelHandler.getBlueprintModelSearch(id)
274 @GetMapping("/download/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
276 value = "Download a Blueprint Model by ID",
277 notes = "Gets the CBA of a blueprint model by its ID. Response can be saved to a file to download the CBA."
280 ApiResponse(code = 200, message = "OK"),
281 ApiResponse(code = 404, message = "Not Found")
284 @Throws(BluePrintException::class)
285 @PreAuthorize("hasRole('USER')")
286 suspend fun downloadBluePrint(
287 @ApiParam(value = "ID of the blueprint model to download", required = true, example = "67ec1f96-ab55-4b81-aff9-23ee0ed1d7a4")
288 @PathVariable(value = "id") id: String
289 ): ResponseEntity<Resource> =
290 mdcWebCoroutineScope {
291 bluePrintModelHandler.downloadBlueprintModelFile(id)
295 "/enrich", produces = [MediaType.APPLICATION_JSON_VALUE],
298 .MULTIPART_FORM_DATA_VALUE
302 value = "Enrich a Blueprint Model",
303 notes = "Enriches the attached CBA and returns the enriched CBA zip file in the response. " +
304 "The enrichment process will complete the package by providing all the definition of types used."
307 @Throws(BluePrintException::class)
308 @PreAuthorize("hasRole('USER')")
309 suspend fun enrichBlueprint(
310 @ApiParam(name = "file", value = "CBA zip file to be uploaded (example: cba_unenriched.zip)", required = true)
311 @RequestPart("file") file: FilePart
312 ): ResponseEntity<Resource> = mdcWebCoroutineScope {
313 bluePrintModelHandler.enrichBlueprint(file)
317 "/enrichandpublish", produces = [MediaType.APPLICATION_JSON_VALUE],
320 .MULTIPART_FORM_DATA_VALUE
324 value = "Enrich and publish a Blueprint Model",
325 notes = "Enriches the attached CBA, validates it and saves it in CDS if validation was successful.",
326 response = BlueprintModelSearch::class
329 ApiResponse(code = 200, message = "OK"),
330 ApiResponse(code = 503, message = "Service Unavailable")
333 @Throws(BluePrintException::class)
334 @PreAuthorize("hasRole('USER')")
335 suspend fun enrichAndPubishlueprint(
336 @ApiParam(name = "file", value = "Unenriched CBA zip file to be uploaded (example: cba_unenriched.zip)", required = true)
337 @RequestPart("file") file: FilePart
338 ): BlueprintModelSearch = mdcWebCoroutineScope {
339 bluePrintModelHandler.enrichAndPublishBlueprint(file)
342 @PostMapping("/publish", produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
344 value = "Publish a Blueprint Model",
345 notes = "Validates the attached CBA file and saves it in CDS if validation was successful. CBA needs to be already enriched.",
346 response = BlueprintModelSearch::class
349 @Throws(BluePrintException::class)
350 @PreAuthorize("hasRole('USER')")
351 suspend fun publishBlueprint(
352 @ApiParam(name = "file", value = "Enriched CBA zip file to be uploaded (example: cba_enriched.zip)", required = true)
353 @RequestPart("file") file: FilePart
354 ): BlueprintModelSearch = mdcWebCoroutineScope {
355 bluePrintModelHandler.publishBlueprint(file)
358 @GetMapping("/search/{tags}", produces = [MediaType.APPLICATION_JSON_VALUE])
360 value = "Search for a Blueprint by Tag",
361 notes = "Searches for all blueprint models which contain the specified input parameter in their tags. " +
362 "Blueprint models which contain just parts of the searched word in their tags are also returned.",
363 responseContainer = "List",
364 response = BlueprintModelSearch::class
367 @PreAuthorize("hasRole('USER')")
368 suspend fun searchBlueprintModels(
369 @ApiParam(value = "Tag to search for", example = "test", required = true)
370 @PathVariable(value = "tags") tags: String
371 ): List<BlueprintModelSearch> =
372 mdcWebCoroutineScope {
373 bluePrintModelHandler.searchBlueprintModels(tags)
376 @DeleteMapping("/name/{name}/version/{version}")
378 value = "Delete a Blueprint Model by Name",
379 notes = "Deletes a blueprint model identified by its name and version from CDS.",
380 // to avoid duplicate operation IDs
381 nickname = "BlueprintModelController_deleteBlueprintByName_DELETE.org.onap.ccsdk.cds.blueprintsprocessor.designer.api",
382 produces = MediaType.APPLICATION_JSON_VALUE
384 @PreAuthorize("hasRole('USER')")
385 suspend fun deleteBlueprint(
386 @ApiParam(value = "Name of the blueprint model", required = true, example = "pnf_netconf")
387 @PathVariable(value = "name") name: String,
388 @ApiParam(value = "Version of the blueprint model", required = true, example = "1.0.0")
389 @PathVariable(value = "version") version: String
390 ) = mdcWebCoroutineScope {
391 bluePrintModelHandler.deleteBlueprintModel(name, version)
395 path = arrayOf("/workflow-spec"),
398 .APPLICATION_JSON_VALUE
400 consumes = arrayOf(MediaType.APPLICATION_JSON_VALUE)
403 value = "Get Workflow Specification",
404 notes = "Get the workflow of a blueprint identified by Blueprint and workflow name. " +
405 "Inputs, outputs and data types of workflow is returned."
408 @Throws(BluePrintException::class)
409 @PreAuthorize("hasRole('USER')")
410 suspend fun workflowSpec(
411 @ApiParam(required = true, value = "Blueprint and workflow identification")
412 @RequestBody workFlowSpecReq: WorkFlowSpecRequest
414 ResponseEntity<String> = mdcWebCoroutineScope {
415 var json = bluePrintModelHandler.prepareWorkFlowSpec(workFlowSpecReq)
417 ResponseEntity(json, HttpStatus.OK)
422 "/workflows/blueprint-name/{name}/version/{version}"
424 produces = arrayOf(MediaType.APPLICATION_JSON_VALUE)
427 value = "Get Workflows of a Blueprint",
428 notes = "Get all available workflows of a Blueprint identified by its name and version."
431 @Throws(BluePrintException::class)
432 @PreAuthorize("hasRole('USER')")
433 suspend fun getWorkflowList(
434 @ApiParam(value = "Name of the blueprint model", example = "pnf_netconf", required = true)
435 @PathVariable(value = "name") name: String,
436 @ApiParam(value = "Version of the blueprint model", example = "1.0.0", required = true)
437 @PathVariable(value = "version") version: String
438 ): ResponseEntity<String> = mdcWebCoroutineScope {
439 var json = bluePrintModelHandler.getWorkflowNames(name, version)
441 ResponseEntity(json, HttpStatus.OK)