2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.controlloop.runtime.main.rest;
23 import com.fasterxml.jackson.core.JsonProcessingException;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.fasterxml.jackson.databind.PropertyNamingStrategies;
26 import io.swagger.annotations.ApiOperation;
27 import io.swagger.annotations.ApiParam;
28 import io.swagger.annotations.ApiResponse;
29 import io.swagger.annotations.ApiResponses;
30 import io.swagger.annotations.Authorization;
31 import io.swagger.annotations.Extension;
32 import io.swagger.annotations.ExtensionProperty;
33 import io.swagger.annotations.ResponseHeader;
34 import java.util.List;
35 import java.util.UUID;
36 import javax.ws.rs.core.Response.Status;
37 import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
38 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
39 import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
40 import org.onap.policy.models.base.PfModelException;
41 import org.onap.policy.models.base.PfModelRuntimeException;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.springframework.http.HttpStatus;
47 import org.springframework.http.MediaType;
48 import org.springframework.http.ResponseEntity;
49 import org.springframework.web.bind.annotation.DeleteMapping;
50 import org.springframework.web.bind.annotation.GetMapping;
51 import org.springframework.web.bind.annotation.PostMapping;
52 import org.springframework.web.bind.annotation.RequestBody;
53 import org.springframework.web.bind.annotation.RequestHeader;
54 import org.springframework.web.bind.annotation.RequestParam;
55 import org.springframework.web.bind.annotation.RestController;
58 * Class to provide REST end points for creating, deleting, querying commissioned control loops.
61 public class CommissioningController extends AbstractRestController {
63 private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
65 private final CommissioningProvider provider;
68 * Create Commissioning Controller.
70 * @param provider the CommissioningProvider
72 public CommissioningController(CommissioningProvider provider) {
73 this.provider = provider;
77 * Creates a control loop definition.
79 * @param requestId request ID used in ONAP logging
80 * @param body the body of control loop following TOSCA definition
84 @PostMapping(value = "/commission",
85 consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
86 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
88 value = "Commissions control loop definitions",
89 notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
90 response = CommissioningResponse.class,
91 tags = {"Control Loop Commissioning API"},
92 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
95 name = VERSION_MINOR_NAME,
96 description = VERSION_MINOR_DESCRIPTION,
97 response = String.class),
99 name = VERSION_PATCH_NAME,
100 description = VERSION_PATCH_DESCRIPTION,
101 response = String.class),
103 name = VERSION_LATEST_NAME,
104 description = VERSION_LATEST_DESCRIPTION,
105 response = String.class),
107 name = REQUEST_ID_NAME,
108 description = REQUEST_ID_HDR_DESCRIPTION,
109 response = UUID.class)
114 name = EXTENSION_NAME,
116 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
117 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
124 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
125 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
126 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
130 public ResponseEntity<CommissioningResponse> create(
132 name = REQUEST_ID_NAME,
133 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
134 @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) {
136 return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body));
138 } catch (PfModelRuntimeException | PfModelException e) {
139 LOGGER.warn("Commissioning of the control loops failed", e);
140 var resp = new CommissioningResponse();
141 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
142 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
148 * Deletes a control loop definition.
150 * @param requestId request ID used in ONAP logging
151 * @param name the name of the control loop definition to delete
152 * @param version the version of the control loop definition to delete
156 @DeleteMapping(value = "/commission",
157 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
158 @ApiOperation(value = "Delete a commissioned control loop",
159 notes = "Deletes a Commissioned Control Loop, returning optional error details",
160 response = CommissioningResponse.class,
161 tags = {"Clamp Control Loop Commissioning API"},
162 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
165 name = VERSION_MINOR_NAME,
166 description = VERSION_MINOR_DESCRIPTION,
167 response = String.class),
169 name = VERSION_PATCH_NAME,
170 description = VERSION_PATCH_DESCRIPTION,
171 response = String.class),
173 name = VERSION_LATEST_NAME,
174 description = VERSION_LATEST_DESCRIPTION,
175 response = String.class),
177 name = REQUEST_ID_NAME,
178 description = REQUEST_ID_HDR_DESCRIPTION,
179 response = UUID.class)},
183 name = EXTENSION_NAME,
185 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
186 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
193 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
194 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
195 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
199 public ResponseEntity<CommissioningResponse> delete(
201 name = REQUEST_ID_NAME,
202 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
203 @ApiParam(value = "Control Loop definition name", required = true) @RequestParam(
204 value = "name") String name,
206 value = "Control Loop definition version",
207 required = true) @RequestParam("version") String version) {
210 return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version));
212 } catch (PfModelRuntimeException | PfModelException e) {
213 LOGGER.warn("Decommisssioning of control loop failed", e);
214 var resp = new CommissioningResponse();
215 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
216 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
222 * Queries details of all or specific control loop definitions.
224 * @param requestId request ID used in ONAP logging
225 * @param name the name of the control loop definition to get, null for all definitions
226 * @param version the version of the control loop definition to get, null for all definitions
227 * @return the control loop definitions
230 @GetMapping(value = "/commission",
231 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
232 @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
233 notes = "Queries details of the requested commissioned control loop definitions, "
234 + "returning all control loop details",
235 response = ToscaNodeTemplate.class,
236 tags = {"Clamp Control Loop Commissioning API"},
237 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
240 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
241 response = String.class),
242 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
243 response = String.class),
244 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
245 response = String.class),
246 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
247 response = UUID.class)},
251 name = EXTENSION_NAME,
253 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
254 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
261 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
262 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
263 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
267 public ResponseEntity<?> query(
269 name = REQUEST_ID_NAME,
270 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
271 @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
273 required = false) String name,
274 @ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
276 required = false) String version) {
279 return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version));
281 } catch (PfModelRuntimeException | PfModelException e) {
282 LOGGER.warn("Get of control loop definitions failed", e);
283 var resp = new CommissioningResponse();
284 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
285 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
291 * Retrieves the Tosca Service Template.
293 * @param requestId request ID used in ONAP logging
294 * @param name the name of the tosca service template to retrieve
295 * @param version the version of the tosca service template to get
296 * @return the specified tosca service template
299 @GetMapping(value = "/commission/toscaservicetemplate",
300 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
301 @ApiOperation(value = "Query details of the requested tosca service templates",
302 notes = "Queries details of the requested commissioned tosca service template, "
303 + "returning all tosca service template details",
304 response = ToscaServiceTemplate.class,
305 tags = {"Clamp Control Loop Commissioning API"},
306 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
309 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
310 response = String.class),
311 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
312 response = String.class),
313 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
314 response = String.class),
315 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
316 response = UUID.class)},
320 name = EXTENSION_NAME,
322 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
323 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
330 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
331 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
332 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
336 public ResponseEntity<?> queryToscaServiceTemplate(
338 name = REQUEST_ID_NAME,
339 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
340 @ApiParam(value = "Tosca service template name", required = false) @RequestParam(
342 required = false) String name,
343 @ApiParam(value = "Tosca service template version", required = true) @RequestParam(
345 required = false) String version) {
348 ObjectMapper mapper = new ObjectMapper();
349 mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
350 String response = mapper.writerWithDefaultPrettyPrinter()
351 .writeValueAsString(provider.getToscaServiceTemplate(name, version));
353 return ResponseEntity.ok().body(response);
355 } catch (PfModelRuntimeException | PfModelException e) {
356 LOGGER.warn("Get of tosca service template failed", e);
357 var resp = new CommissioningResponse();
358 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
359 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
360 } catch (JsonProcessingException e) {
361 LOGGER.warn("Get of tosca service template failed", e);
362 var resp = new CommissioningResponse();
363 resp.setErrorDetails(e.getMessage());
364 return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
369 * Retrieves the Json Schema for the specified Tosca Service Template.
371 * @param requestId request ID used in ONAP logging
372 * @param section section of the tosca service template to get schema for
373 * @return the specified tosca service template or section Json Schema
376 @GetMapping(value = "/commission/toscaServiceTemplateSchema",
377 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
378 @ApiOperation(value = "Query details of the requested tosca service template json schema",
379 notes = "Queries details of the requested commissioned tosca service template json schema, "
380 + "returning all tosca service template json schema details",
381 response = ToscaServiceTemplate.class,
382 tags = {"Clamp Control Loop Commissioning API"},
383 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
386 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
387 response = String.class),
388 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
389 response = String.class),
390 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
391 response = String.class),
392 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
393 response = UUID.class)},
397 name = EXTENSION_NAME,
399 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
400 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
407 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
408 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
409 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
413 public ResponseEntity<?> queryToscaServiceTemplateJsonSchema(
415 name = REQUEST_ID_NAME,
416 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
417 @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam(
419 required = false, defaultValue = "all") String section) {
421 return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section));
423 } catch (PfModelRuntimeException | PfModelException e) {
424 LOGGER.warn("Get of tosca service template json schema failed", e);
425 var resp = new CommissioningResponse();
426 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
427 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
428 } catch (JsonProcessingException e) {
429 LOGGER.warn("Get of tosca service template json schema failed", e);
430 var resp = new CommissioningResponse();
431 resp.setErrorDetails(e.getMessage());
432 return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
437 * Queries the elements of a specific control loop.
439 * @param requestId request ID used in ONAP logging
440 * @param name the name of the control loop definition to get
441 * @param version the version of the control loop definition to get
442 * @return the control loop element definitions
445 @GetMapping(value = "/commission/elements",
446 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
447 @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
448 notes = "Queries details of the requested commissioned control loop element definitions, "
449 + "returning all control loop elements' details",
450 response = ToscaNodeTemplate.class,
451 tags = {"Clamp Control Loop Commissioning API"},
452 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
455 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
456 response = String.class),
457 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
458 response = String.class),
459 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
460 response = String.class),
461 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
462 response = UUID.class)},
466 name = EXTENSION_NAME,
468 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
469 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
476 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
477 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
478 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
482 public ResponseEntity<?> queryElements(
484 name = REQUEST_ID_NAME,
485 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
486 @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
488 required = false) String name,
489 @ApiParam(value = "Control Loop definition version", required = true) @RequestParam(
491 required = false) String version) {
494 List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
495 // Prevent ambiguous queries with multiple returns
496 if (nodeTemplate.size() > 1) {
497 var resp = new CommissioningResponse();
498 resp.setErrorDetails("Multiple ControlLoops are not supported");
499 return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp);
502 List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
503 return ResponseEntity.ok().body(response);
505 } catch (PfModelRuntimeException | PfModelException e) {
506 LOGGER.warn("Get of control loop element definitions failed", e);
507 var resp = new CommissioningResponse();
508 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
509 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);