aba585e29054cf5c64c77592821215648992ddd1
[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.UUID;
32 import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
33 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
34 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
35 import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse;
36 import org.onap.policy.clamp.controlloop.runtime.instantiation.ControlLoopInstantiationProvider;
37 import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
38 import org.onap.policy.models.base.PfModelException;
39 import org.onap.policy.models.base.PfModelRuntimeException;
40 import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
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.PutMapping;
49 import org.springframework.web.bind.annotation.RequestBody;
50 import org.springframework.web.bind.annotation.RequestHeader;
51 import org.springframework.web.bind.annotation.RequestParam;
52 import org.springframework.web.bind.annotation.RestController;
53
54 /**
55  * Class to provide REST end points for creating, deleting, query and commanding a control loop definition.
56  */
57 @RestController
58 public class InstantiationController extends AbstractRestController {
59
60     private static final Logger LOGGER = LoggerFactory.getLogger(InstantiationController.class);
61
62     // The CL provider for instantiation requests
63     private final ControlLoopInstantiationProvider provider;
64
65     /**
66      * Create Instantiation Controller.
67      *
68      * @param provider the ControlLoopInstantiationProvider
69      */
70     public InstantiationController(ControlLoopInstantiationProvider provider) {
71         this.provider = provider;
72     }
73
74     /**
75      * Creates a control loop.
76      *
77      * @param requestId request ID used in ONAP logging
78      * @param controlLoops the control loops
79      * @return a response
80      */
81     // @formatter:off
82     @PostMapping(value = "/instantiation",
83             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
84             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
85     @ApiOperation(
86             value = "Commissions control loop definitions",
87             notes = "Commissions control loop definitions, returning the control loop IDs",
88             response = InstantiationResponse.class,
89             tags = {"Control Loop Instantiation API"},
90             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
91             responseHeaders = {
92                 @ResponseHeader(
93                     name = VERSION_MINOR_NAME,
94                     description = VERSION_MINOR_DESCRIPTION,
95                     response = String.class),
96                 @ResponseHeader(
97                     name = VERSION_PATCH_NAME,
98                     description = VERSION_PATCH_DESCRIPTION,
99                     response = String.class),
100                 @ResponseHeader(
101                     name = VERSION_LATEST_NAME,
102                     description = VERSION_LATEST_DESCRIPTION,
103                     response = String.class),
104                 @ResponseHeader(
105                     name = REQUEST_ID_NAME,
106                     description = REQUEST_ID_HDR_DESCRIPTION,
107                     response = UUID.class)
108                 },
109             extensions = {
110                 @Extension
111                     (
112                         name = EXTENSION_NAME,
113                         properties = {
114                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
115                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
116                         }
117                     )
118             }
119         )
120     @ApiResponses(
121             value = {
122                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
123                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
124                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
125             }
126         )
127     // @formatter:on
128     public ResponseEntity<InstantiationResponse> create(
129             @RequestHeader(name = REQUEST_ID_NAME, required = false)
130             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
131             @ApiParam(value = "Entity Body of Control Loop", required = true)
132             @RequestBody ControlLoops controlLoops) {
133
134         try {
135             return ResponseEntity.ok().body(provider.createControlLoops(controlLoops));
136
137         } catch (PfModelRuntimeException | PfModelException e) {
138             LOGGER.warn("creation of control loop failed", e);
139             return createInstantiationErrorResponse(e);
140         }
141     }
142
143     /**
144      * Queries details of all control loops.
145      *
146      * @param requestId request ID used in ONAP logging
147      * @param name the name of the control loop to get, null for all control loops
148      * @param version the version of the control loop to get, null for all control loops
149      * @return the control loops
150      */
151     // @formatter:off
152     @GetMapping(value = "/instantiation",
153             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
154     @ApiOperation(value = "Query details of the requested control loops",
155             notes = "Queries details of the requested control loops, returning all control loop details",
156             response = ControlLoops.class,
157             tags = {
158                 "Clamp control loop Instantiation API"
159             },
160             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
161             responseHeaders = {
162                 @ResponseHeader(
163                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
164                     response = String.class),
165                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
166                     response = String.class),
167                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
168                     response = String.class),
169                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
170                     response = UUID.class)},
171             extensions = {
172                 @Extension
173                      (
174                          name = EXTENSION_NAME,
175                          properties = {
176                              @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
177                              @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
178                          }
179                     )
180                 }
181         )
182     @ApiResponses(
183             value = {
184                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
185                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
186                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
187             }
188         )
189     // @formatter:on
190     public ResponseEntity<?> query(
191             @RequestHeader(name = REQUEST_ID_NAME, required = false)
192             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
193             @ApiParam(value = "Control Loop definition name", required = false)
194             @RequestParam(value = "name", required = false) String name,
195             @ApiParam(value = "Control Loop definition version", required = false)
196             @RequestParam(value = "version", required = false) String version) {
197
198         try {
199             return ResponseEntity.ok().body(provider.getControlLoops(name, version));
200
201         } catch (PfModelRuntimeException | PfModelException e) {
202             LOGGER.warn("commisssioning of control loop failed", e);
203             return createInstantiationErrorResponse(e);
204         }
205
206     }
207
208     /**
209      * Updates a control loop.
210      *
211      * @param requestId request ID used in ONAP logging
212      * @param controlLoops the control loops
213      * @return a response
214      */
215     // @formatter:off
216     @PutMapping(value = "/instantiation",
217             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
218             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
219     @ApiOperation(
220             value = "Updates control loop definitions",
221             notes = "Updates control loop definitions, returning the updated control loop definition IDs",
222             response = InstantiationResponse.class,
223             tags = {
224                 "Control Loop Instantiation API"
225                 },
226             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
227             responseHeaders = {
228                 @ResponseHeader(
229                     name = VERSION_MINOR_NAME,
230                     description = VERSION_MINOR_DESCRIPTION,
231                     response = String.class),
232                 @ResponseHeader(
233                     name = VERSION_PATCH_NAME,
234                     description = VERSION_PATCH_DESCRIPTION,
235                     response = String.class),
236                 @ResponseHeader(
237                     name = VERSION_LATEST_NAME,
238                     description = VERSION_LATEST_DESCRIPTION,
239                     response = String.class),
240                 @ResponseHeader(
241                     name = REQUEST_ID_NAME,
242                     description = REQUEST_ID_HDR_DESCRIPTION,
243                     response = UUID.class)
244             },
245             extensions = {
246                 @Extension
247                     (
248                         name = EXTENSION_NAME,
249                         properties = {
250                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
251                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
252                         }
253                     )
254             }
255         )
256     @ApiResponses(
257             value = {
258                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
259                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
260                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
261             }
262         )
263     // @formatter:on
264     public ResponseEntity<InstantiationResponse> update(
265             @RequestHeader(name = REQUEST_ID_NAME, required = false)
266             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
267             @ApiParam(value = "Entity Body of Control Loop", required = true)
268             @RequestBody ControlLoops controlLoops) {
269
270         try {
271             return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops));
272
273         } catch (PfModelRuntimeException | PfModelException e) {
274             LOGGER.warn("update of control loops failed", e);
275             return createInstantiationErrorResponse(e);
276         }
277     }
278
279     /**
280      * Deletes a control loop definition.
281      *
282      * @param requestId request ID used in ONAP logging
283      * @param name the name of the control loop to delete
284      * @param version the version of the control loop to delete
285      * @return a response
286      */
287     // @formatter:off
288     @DeleteMapping(value = "/instantiation",
289             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
290     @ApiOperation(value = "Delete a control loop",
291             notes = "Deletes a control loop, returning optional error details",
292             response = InstantiationResponse.class,
293             tags = {
294                 "Clamp Control Loop Instantiation API"
295                 },
296             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
297             responseHeaders = {
298                 @ResponseHeader(
299                     name = VERSION_MINOR_NAME,
300                     description = VERSION_MINOR_DESCRIPTION,
301                     response = String.class),
302                 @ResponseHeader(
303                     name = VERSION_PATCH_NAME,
304                     description = VERSION_PATCH_DESCRIPTION,
305                     response = String.class),
306                 @ResponseHeader(
307                     name = VERSION_LATEST_NAME,
308                     description = VERSION_LATEST_DESCRIPTION,
309                     response = String.class),
310                 @ResponseHeader(
311                     name = REQUEST_ID_NAME,
312                     description = REQUEST_ID_HDR_DESCRIPTION,
313                     response = UUID.class)},
314             extensions = {
315                 @Extension
316                     (
317                         name = EXTENSION_NAME,
318                         properties = {
319                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
320                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
321                         }
322                     )
323                 }
324         )
325     @ApiResponses(
326         value = {
327             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
328             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
329             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
330         }
331     )
332     // @formatter:on
333
334     public ResponseEntity<InstantiationResponse> delete(
335             @RequestHeader(name = REQUEST_ID_NAME, required = false)
336             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
337             @ApiParam(value = "Control Loop definition name", required = true)
338             @RequestParam("name") String name,
339             @ApiParam(value = "Control Loop definition version")
340             @RequestParam(value = "version", required = false) String version) {
341
342         try {
343             return ResponseEntity.ok().body(provider.deleteControlLoop(name, version));
344
345         } catch (PfModelRuntimeException | PfModelException e) {
346             LOGGER.warn("delete of control loop failed", e);
347             return createInstantiationErrorResponse(e);
348         }
349     }
350
351     /**
352      * Issues control loop commands to control loops.
353      *
354      * @param requestId request ID used in ONAP logging
355      * @param command the command to issue to control loops
356      * @return the control loop definitions
357      */
358     // @formatter:off
359     @PutMapping(value = "/instantiation/command",
360             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
361             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
362     @ApiOperation(value = "Issue a command to the requested control loops",
363             notes = "Issues a command to a control loop, ordering a state change on the control loop",
364             response = InstantiationResponse.class,
365             tags = {
366                 "Clamp Control Loop Instantiation API"
367             },
368             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
369             responseHeaders = {
370                 @ResponseHeader(
371                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
372                     response = String.class),
373                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
374                     response = String.class),
375                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
376                     response = String.class),
377                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
378                     response = UUID.class)},
379             extensions = {
380                 @Extension
381                     (
382                         name = EXTENSION_NAME,
383                         properties = {
384                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
385                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
386                         }
387                     )
388                 }
389         )
390     @ApiResponses(
391             value = {
392                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
393                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
394                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
395             }
396         )
397     // @formatter:on
398     public ResponseEntity<InstantiationResponse> issueControlLoopCommand(
399             @RequestHeader(name = REQUEST_ID_NAME, required = false)
400             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
401             @ApiParam(value = "Entity Body of control loop command", required = true)
402             @RequestBody InstantiationCommand command) {
403
404         try {
405             return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command));
406
407         } catch (PfModelRuntimeException | PfModelException | ControlLoopException e) {
408             LOGGER.warn("creation of control loop failed", e);
409             return createInstantiationErrorResponse(e);
410         }
411     }
412
413     /**
414      * create a Instantiation Response from an exception.
415      *
416      * @param e the error
417      * @return the Instantiation Response
418      */
419     private ResponseEntity<InstantiationResponse> createInstantiationErrorResponse(ErrorResponseInfo e) {
420         var resp = new InstantiationResponse();
421         resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
422         return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
423     }
424 }