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 com.fasterxml.jackson.module.jsonSchema.JsonSchema;
27 import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;
28 import io.swagger.annotations.ApiOperation;
29 import io.swagger.annotations.ApiParam;
30 import io.swagger.annotations.ApiResponse;
31 import io.swagger.annotations.ApiResponses;
32 import io.swagger.annotations.Authorization;
33 import io.swagger.annotations.Extension;
34 import io.swagger.annotations.ExtensionProperty;
35 import io.swagger.annotations.ResponseHeader;
36 import java.util.List;
37 import java.util.UUID;
38 import javax.ws.rs.core.Response.Status;
39 import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
40 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
41 import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
42 import org.onap.policy.models.base.PfModelException;
43 import org.onap.policy.models.base.PfModelRuntimeException;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.http.HttpStatus;
49 import org.springframework.http.MediaType;
50 import org.springframework.http.ResponseEntity;
51 import org.springframework.web.bind.annotation.DeleteMapping;
52 import org.springframework.web.bind.annotation.GetMapping;
53 import org.springframework.web.bind.annotation.PostMapping;
54 import org.springframework.web.bind.annotation.RequestBody;
55 import org.springframework.web.bind.annotation.RequestHeader;
56 import org.springframework.web.bind.annotation.RequestParam;
57 import org.springframework.web.bind.annotation.RestController;
60 * Class to provide REST end points for creating, deleting, querying commissioned control loops.
63 public class CommissioningController extends AbstractRestController {
65 private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
67 private final CommissioningProvider provider;
70 * Create Commissioning Controller.
72 * @param provider the CommissioningProvider
74 public CommissioningController(CommissioningProvider provider) {
75 this.provider = provider;
79 * Creates a control loop definition.
81 * @param requestId request ID used in ONAP logging
82 * @param body the body of control loop following TOSCA definition
86 @PostMapping(value = "/commission",
87 consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
88 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
90 value = "Commissions control loop definitions",
91 notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
92 response = CommissioningResponse.class,
93 tags = {"Control Loop Commissioning API"},
94 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
97 name = VERSION_MINOR_NAME,
98 description = VERSION_MINOR_DESCRIPTION,
99 response = String.class),
101 name = VERSION_PATCH_NAME,
102 description = VERSION_PATCH_DESCRIPTION,
103 response = String.class),
105 name = VERSION_LATEST_NAME,
106 description = VERSION_LATEST_DESCRIPTION,
107 response = String.class),
109 name = REQUEST_ID_NAME,
110 description = REQUEST_ID_HDR_DESCRIPTION,
111 response = UUID.class)
116 name = EXTENSION_NAME,
118 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
119 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
126 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
127 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
128 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
132 public ResponseEntity<CommissioningResponse> create(
134 name = REQUEST_ID_NAME,
135 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
136 @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) {
138 return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body));
140 } catch (PfModelRuntimeException | PfModelException e) {
141 LOGGER.warn("Commissioning of the control loops failed", e);
142 var resp = new CommissioningResponse();
143 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
144 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
150 * Deletes a control loop definition.
152 * @param requestId request ID used in ONAP logging
153 * @param name the name of the control loop definition to delete
154 * @param version the version of the control loop definition to delete
158 @DeleteMapping(value = "/commission",
159 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
160 @ApiOperation(value = "Delete a commissioned control loop",
161 notes = "Deletes a Commissioned Control Loop, returning optional error details",
162 response = CommissioningResponse.class,
163 tags = {"Clamp Control Loop Commissioning API"},
164 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
167 name = VERSION_MINOR_NAME,
168 description = VERSION_MINOR_DESCRIPTION,
169 response = String.class),
171 name = VERSION_PATCH_NAME,
172 description = VERSION_PATCH_DESCRIPTION,
173 response = String.class),
175 name = VERSION_LATEST_NAME,
176 description = VERSION_LATEST_DESCRIPTION,
177 response = String.class),
179 name = REQUEST_ID_NAME,
180 description = REQUEST_ID_HDR_DESCRIPTION,
181 response = UUID.class)},
185 name = EXTENSION_NAME,
187 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
188 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
195 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
196 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
197 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
201 public ResponseEntity<CommissioningResponse> delete(
203 name = REQUEST_ID_NAME,
204 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
205 @ApiParam(value = "Control Loop definition name", required = true) @RequestParam(
206 value = "name") String name,
208 value = "Control Loop definition version",
209 required = true) @RequestParam("version") String version) {
212 return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version));
214 } catch (PfModelRuntimeException | PfModelException e) {
215 LOGGER.warn("Decommisssioning of control loop failed", e);
216 var resp = new CommissioningResponse();
217 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
218 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
224 * Queries details of all or specific control loop definitions.
226 * @param requestId request ID used in ONAP logging
227 * @param name the name of the control loop definition to get, null for all definitions
228 * @param version the version of the control loop definition to get, null for all definitions
229 * @return the control loop definitions
232 @GetMapping(value = "/commission",
233 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
234 @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
235 notes = "Queries details of the requested commissioned control loop definitions, "
236 + "returning all control loop details",
237 response = ToscaNodeTemplate.class,
238 tags = {"Clamp Control Loop Commissioning API"},
239 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
242 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
243 response = String.class),
244 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
245 response = String.class),
246 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
247 response = String.class),
248 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
249 response = UUID.class)},
253 name = EXTENSION_NAME,
255 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
256 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
263 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
264 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
265 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
269 public ResponseEntity<?> query(
271 name = REQUEST_ID_NAME,
272 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
273 @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
275 required = false) String name,
276 @ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
278 required = false) String version) {
281 return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version));
283 } catch (PfModelRuntimeException | PfModelException e) {
284 LOGGER.warn("Get of control loop definitions failed", e);
285 var resp = new CommissioningResponse();
286 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
287 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
293 * Retrieves the Tosca Service Template.
295 * @param requestId request ID used in ONAP logging
296 * @param name the name of the tosca service template to retrieve
297 * @param version the version of the tosca service template to get
298 * @return the specified tosca service template
301 @GetMapping(value = "/commission/toscaservicetemplate",
302 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
303 @ApiOperation(value = "Query details of the requested tosca service templates",
304 notes = "Queries details of the requested commissioned tosca service template, "
305 + "returning all tosca service template details",
306 response = ToscaServiceTemplate.class,
307 tags = {"Clamp Control Loop Commissioning API"},
308 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
311 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
312 response = String.class),
313 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
314 response = String.class),
315 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
316 response = String.class),
317 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
318 response = UUID.class)},
322 name = EXTENSION_NAME,
324 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
325 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
332 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
333 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
334 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
338 public ResponseEntity<?> queryToscaServiceTemplate(
340 name = REQUEST_ID_NAME,
341 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
342 @ApiParam(value = "Tosca service template name", required = false) @RequestParam(
344 required = false) String name,
345 @ApiParam(value = "Tosca service template version", required = true) @RequestParam(
347 required = false) String version) {
350 return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version));
352 } catch (PfModelRuntimeException | PfModelException e) {
353 LOGGER.warn("Get of tosca service template failed", e);
354 var resp = new CommissioningResponse();
355 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
356 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
362 * Retrieves the Json Schema for the specified Tosca Service Template.
364 * @param requestId request ID used in ONAP logging
365 * @param section section of the tosca service template to get schema for
366 * @return the specified tosca service template or section Json Schema
369 @GetMapping(value = "/commission/toscaServiceTemplateSchema",
370 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
371 @ApiOperation(value = "Query details of the requested tosca service template json schema",
372 notes = "Queries details of the requested commissioned tosca service template json schema, "
373 + "returning all tosca service template json schema details",
374 response = ToscaServiceTemplate.class,
375 tags = {"Clamp Control Loop Commissioning API"},
376 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
379 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
380 response = String.class),
381 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
382 response = String.class),
383 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
384 response = String.class),
385 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
386 response = UUID.class)},
390 name = EXTENSION_NAME,
392 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
393 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
400 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
401 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
402 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
406 public ResponseEntity<?> queryToscaServiceTemplateJsonSchema(
408 name = REQUEST_ID_NAME,
409 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
410 @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam(
412 required = false, defaultValue = "all") String section) {
414 return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section));
416 } catch (PfModelRuntimeException | PfModelException e) {
417 LOGGER.warn("Get of tosca service template json schema failed", e);
418 var resp = new CommissioningResponse();
419 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
420 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
421 } catch (JsonProcessingException e) {
422 LOGGER.warn("Get of tosca service template json schema failed", e);
423 var resp = new CommissioningResponse();
424 resp.setErrorDetails(e.getMessage());
425 return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
430 * Queries the elements of a specific control loop.
432 * @param requestId request ID used in ONAP logging
433 * @param name the name of the control loop definition to get
434 * @param version the version of the control loop definition to get
435 * @return the control loop element definitions
438 @GetMapping(value = "/commission/elements",
439 produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
440 @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
441 notes = "Queries details of the requested commissioned control loop element definitions, "
442 + "returning all control loop elements' details",
443 response = ToscaNodeTemplate.class,
444 tags = {"Clamp Control Loop Commissioning API"},
445 authorizations = @Authorization(value = AUTHORIZATION_TYPE),
448 name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
449 response = String.class),
450 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
451 response = String.class),
452 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
453 response = String.class),
454 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
455 response = UUID.class)},
459 name = EXTENSION_NAME,
461 @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
462 @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
469 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
470 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
471 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
475 public ResponseEntity<?> queryElements(
477 name = REQUEST_ID_NAME,
478 required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
479 @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
481 required = false) String name,
482 @ApiParam(value = "Control Loop definition version", required = true) @RequestParam(
484 required = false) String version) {
487 List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
488 // Prevent ambiguous queries with multiple returns
489 if (nodeTemplate.size() > 1) {
490 var resp = new CommissioningResponse();
491 resp.setErrorDetails("Multiple ControlLoops are not supported");
492 return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp);
495 List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
496 return ResponseEntity.ok().body(response);
498 } catch (PfModelRuntimeException | PfModelException e) {
499 LOGGER.warn("Get of control loop element definitions failed", e);
500 var resp = new CommissioningResponse();
501 resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
502 return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);