a03254272b55963e878f44b5ed9ff6565503e154
[policy/clamp.git] /
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.runtime.main.rest;
22
23 import io.swagger.annotations.ApiOperation;
24 import io.swagger.annotations.ApiParam;
25 import io.swagger.annotations.ApiResponse;
26 import io.swagger.annotations.ApiResponses;
27 import io.swagger.annotations.Authorization;
28 import io.swagger.annotations.Extension;
29 import io.swagger.annotations.ExtensionProperty;
30 import io.swagger.annotations.ResponseHeader;
31 import java.util.List;
32 import java.util.UUID;
33 import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
34 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
35 import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
36 import org.onap.policy.models.base.PfModelException;
37 import org.onap.policy.models.base.PfModelRuntimeException;
38 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.springframework.http.HttpStatus;
43 import org.springframework.http.MediaType;
44 import org.springframework.http.ResponseEntity;
45 import org.springframework.web.bind.annotation.DeleteMapping;
46 import org.springframework.web.bind.annotation.GetMapping;
47 import org.springframework.web.bind.annotation.PostMapping;
48 import org.springframework.web.bind.annotation.RequestBody;
49 import org.springframework.web.bind.annotation.RequestHeader;
50 import org.springframework.web.bind.annotation.RequestParam;
51 import org.springframework.web.bind.annotation.RestController;
52
53 /**
54  * Class to provide REST end points for creating, deleting, querying commissioned control loops.
55  */
56 @RestController
57 public class CommissioningController extends AbstractRestController {
58
59     private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
60
61     private final CommissioningProvider provider;
62
63     /**
64      * Create Commissioning Controller.
65      *
66      * @param provider the CommissioningProvider
67      */
68     public CommissioningController(CommissioningProvider provider) {
69         this.provider = provider;
70     }
71
72     /**
73      * Creates a control loop definition.
74      *
75      * @param requestId request ID used in ONAP logging
76      * @param body the body of control loop following TOSCA definition
77      * @return a response
78      */
79     // @formatter:off
80     @PostMapping(value = "/commission",
81             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
82             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
83     @ApiOperation(
84             value = "Commissions control loop definitions",
85             notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
86             response = CommissioningResponse.class,
87             tags = {"Control Loop Commissioning API"},
88             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
89             responseHeaders = {
90                 @ResponseHeader(
91                     name = VERSION_MINOR_NAME,
92                     description = VERSION_MINOR_DESCRIPTION,
93                     response = String.class),
94                 @ResponseHeader(
95                     name = VERSION_PATCH_NAME,
96                     description = VERSION_PATCH_DESCRIPTION,
97                     response = String.class),
98                 @ResponseHeader(
99                     name = VERSION_LATEST_NAME,
100                     description = VERSION_LATEST_DESCRIPTION,
101                     response = String.class),
102                 @ResponseHeader(
103                     name = REQUEST_ID_NAME,
104                     description = REQUEST_ID_HDR_DESCRIPTION,
105                     response = UUID.class)
106             },
107             extensions = {
108                 @Extension
109                     (
110                         name = EXTENSION_NAME,
111                         properties = {
112                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
113                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
114                         }
115                     )
116             }
117     )
118     @ApiResponses(
119             value = {
120                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
121                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
122                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
123             }
124     )
125     // @formatter:on
126     public ResponseEntity<CommissioningResponse> create(
127             @RequestHeader(
128                     name = REQUEST_ID_NAME,
129                     required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
130             @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) {
131         try {
132             return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body));
133
134         } catch (PfModelRuntimeException | PfModelException e) {
135             LOGGER.warn("Commissioning of the control loops failed", e);
136             var resp = new CommissioningResponse();
137             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
138             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
139         }
140
141     }
142
143     /**
144      * Deletes a control loop definition.
145      *
146      * @param requestId request ID used in ONAP logging
147      * @param name the name of the control loop definition to delete
148      * @param version the version of the control loop definition to delete
149      * @return a response
150      */
151     // @formatter:off
152     @DeleteMapping(value = "/commission",
153             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
154     @ApiOperation(value = "Delete a commissioned control loop",
155             notes = "Deletes a Commissioned Control Loop, returning optional error details",
156             response = CommissioningResponse.class,
157             tags = {"Clamp Control Loop Commissioning API"},
158             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
159             responseHeaders = {
160                 @ResponseHeader(
161                     name = VERSION_MINOR_NAME,
162                     description = VERSION_MINOR_DESCRIPTION,
163                     response = String.class),
164                 @ResponseHeader(
165                     name = VERSION_PATCH_NAME,
166                     description = VERSION_PATCH_DESCRIPTION,
167                     response = String.class),
168                 @ResponseHeader(
169                     name = VERSION_LATEST_NAME,
170                     description = VERSION_LATEST_DESCRIPTION,
171                     response = String.class),
172                 @ResponseHeader(
173                             name = REQUEST_ID_NAME,
174                             description = REQUEST_ID_HDR_DESCRIPTION,
175                             response = UUID.class)},
176             extensions = {
177                 @Extension
178                     (
179                         name = EXTENSION_NAME,
180                         properties = {
181                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
182                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
183                         }
184                     )
185             }
186     )
187     @ApiResponses(
188         value = {
189             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
190             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
191             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
192         }
193     )
194     // @formatter:on
195     public ResponseEntity<CommissioningResponse> delete(
196             @RequestHeader(
197                     name = REQUEST_ID_NAME,
198                     required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
199             @ApiParam(value = "Control Loop definition name", required = true) @RequestParam(
200                     value = "name") String name,
201             @ApiParam(
202                     value = "Control Loop definition version",
203                     required = true) @RequestParam("version") String version) {
204
205         try {
206             return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version));
207
208         } catch (PfModelRuntimeException | PfModelException e) {
209             LOGGER.warn("Decommisssioning of control loop failed", e);
210             var resp = new CommissioningResponse();
211             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
212             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
213         }
214
215     }
216
217     /**
218      * Queries details of all or specific control loop definitions.
219      *
220      * @param requestId request ID used in ONAP logging
221      * @param name the name of the control loop definition to get, null for all definitions
222      * @param version the version of the control loop definition to get, null for all definitions
223      * @return the control loop definitions
224      */
225     // @formatter:off
226     @GetMapping(value = "/commission",
227             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
228     @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
229             notes = "Queries details of the requested commissioned control loop definitions, "
230                     + "returning all control loop details",
231             response = ToscaNodeTemplate.class,
232             tags = {"Clamp Control Loop Commissioning API"},
233             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
234             responseHeaders = {
235                 @ResponseHeader(
236                         name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
237                         response = String.class),
238                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
239                         response = String.class),
240                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
241                         response = String.class),
242                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
243                         response = UUID.class)},
244         extensions = {
245             @Extension
246                 (
247                     name = EXTENSION_NAME,
248                     properties = {
249                         @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
250                         @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
251                     }
252                 )
253             }
254     )
255     @ApiResponses(
256         value = {
257             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
258             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
259             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
260         }
261     )
262     // @formatter:on
263     public ResponseEntity<?> query(
264             @RequestHeader(
265                     name = REQUEST_ID_NAME,
266                     required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
267             @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
268                     value = "name",
269                     required = false) String name,
270             @ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
271                     value = "version",
272                     required = false) String version) {
273
274         try {
275             return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version));
276
277         } catch (PfModelRuntimeException | PfModelException e) {
278             LOGGER.warn("Get of control loop definitions failed", e);
279             var resp = new CommissioningResponse();
280             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
281             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
282         }
283
284     }
285
286     /**
287      * Retrieves the Tosca Service Template.
288      *
289      * @param requestId request ID used in ONAP logging
290      * @param name the name of the tosca service template to retrieve
291      * @param version the version of the tosca service template to get
292      * @return the specified tosca service template
293      */
294     // @formatter:off
295     @GetMapping(value = "/commission/toscaservicetemplate",
296             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
297     @ApiOperation(value = "Query details of the requested tosca service templates",
298             notes = "Queries details of the requested commissioned tosca service template, "
299                     + "returning all tosca service template details",
300             response = ToscaServiceTemplate.class,
301             tags = {"Clamp Control Loop Commissioning API"},
302             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
303             responseHeaders = {
304                 @ResponseHeader(
305                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
306                     response = String.class),
307                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
308                     response = String.class),
309                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
310                     response = String.class),
311                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
312                     response = UUID.class)},
313             extensions = {
314                 @Extension
315                     (
316                         name = EXTENSION_NAME,
317                         properties = {
318                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
319                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
320                         }
321                     )
322             }
323     )
324     @ApiResponses(
325         value = {
326             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
327             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
328             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
329         }
330     )
331     // @formatter:on
332     public ResponseEntity<?> queryToscaServiceTemplate(
333             @RequestHeader(
334                     name = REQUEST_ID_NAME,
335                     required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
336             @ApiParam(value = "Tosca service template name", required = false) @RequestParam(
337                     value = "name",
338                     required = false) String name,
339             @ApiParam(value = "Tosca service template version", required = true) @RequestParam(
340                     value = "version",
341                     required = false) String version) {
342
343         try {
344             return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version));
345
346         } catch (PfModelRuntimeException | PfModelException e) {
347             LOGGER.warn("Get of tosca service template failed", e);
348             var resp = new CommissioningResponse();
349             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
350             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
351         }
352
353     }
354
355     /**
356      * Queries the elements of a specific control loop.
357      *
358      * @param requestId request ID used in ONAP logging
359      * @param name the name of the control loop definition to get
360      * @param version the version of the control loop definition to get
361      * @return the control loop element definitions
362      */
363     // @formatter:off
364     @GetMapping(value = "/commission/elements",
365             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
366     @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
367             notes = "Queries details of the requested commissioned control loop element definitions, "
368                     + "returning all control loop elements' details",
369             response = ToscaNodeTemplate.class,
370             tags = {"Clamp Control Loop Commissioning API"},
371             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
372             responseHeaders = {
373                 @ResponseHeader(
374                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
375                     response = String.class),
376                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
377                     response = String.class),
378                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
379                     response = String.class),
380                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
381                     response = UUID.class)},
382             extensions = {
383                 @Extension
384                     (
385                         name = EXTENSION_NAME,
386                         properties = {
387                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
388                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
389                         }
390                     )
391             }
392     )
393     @ApiResponses(
394         value = {
395             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
396             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
397             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
398         }
399     )
400     // @formatter:on
401     public ResponseEntity<?> queryElements(
402             @RequestHeader(
403                     name = REQUEST_ID_NAME,
404                     required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
405             @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
406                     value = "name",
407                     required = false) String name,
408             @ApiParam(value = "Control Loop definition version", required = true) @RequestParam(
409                     value = "version",
410                     required = false) String version) {
411
412         try {
413             List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
414             // Prevent ambiguous queries with multiple returns
415             if (nodeTemplate.size() > 1) {
416                 var resp = new CommissioningResponse();
417                 resp.setErrorDetails("Multiple ControlLoops are not supported");
418                 return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp);
419             }
420
421             List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
422             return ResponseEntity.ok().body(response);
423
424         } catch (PfModelRuntimeException | PfModelException e) {
425             LOGGER.warn("Get of control loop element definitions failed", e);
426             var resp = new CommissioningResponse();
427             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
428             return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
429         }
430
431     }
432 }