5a320e8dcddb8b30d84802150ca6523d82badf62
[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     private static final String TAGS = "Clamp Control Loop Instantiation API";
63
64     // The CL provider for instantiation requests
65     private final ControlLoopInstantiationProvider provider;
66
67     /**
68      * Create Instantiation Controller.
69      *
70      * @param provider the ControlLoopInstantiationProvider
71      */
72     public InstantiationController(ControlLoopInstantiationProvider provider) {
73         this.provider = provider;
74     }
75
76     /**
77      * Creates a control loop.
78      *
79      * @param requestId request ID used in ONAP logging
80      * @param controlLoops the control loops
81      * @return a response
82      */
83     // @formatter:off
84     @PostMapping(value = "/instantiation",
85             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
86             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
87     @ApiOperation(
88             value = "Commissions control loop definitions",
89             notes = "Commissions control loop definitions, returning the control loop IDs",
90             response = InstantiationResponse.class,
91             tags = {TAGS},
92             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
93             responseHeaders = {
94                 @ResponseHeader(
95                     name = VERSION_MINOR_NAME,
96                     description = VERSION_MINOR_DESCRIPTION,
97                     response = String.class),
98                 @ResponseHeader(
99                     name = VERSION_PATCH_NAME,
100                     description = VERSION_PATCH_DESCRIPTION,
101                     response = String.class),
102                 @ResponseHeader(
103                     name = VERSION_LATEST_NAME,
104                     description = VERSION_LATEST_DESCRIPTION,
105                     response = String.class),
106                 @ResponseHeader(
107                     name = REQUEST_ID_NAME,
108                     description = REQUEST_ID_HDR_DESCRIPTION,
109                     response = UUID.class)
110                 },
111             extensions = {
112                 @Extension
113                     (
114                         name = EXTENSION_NAME,
115                         properties = {
116                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
117                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
118                         }
119                     )
120             }
121         )
122     @ApiResponses(
123             value = {
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)
127             }
128         )
129     // @formatter:on
130     public ResponseEntity<InstantiationResponse> create(
131             @RequestHeader(name = REQUEST_ID_NAME, required = false)
132             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
133             @ApiParam(value = "Entity Body of Control Loop", required = true)
134             @RequestBody ControlLoops controlLoops) {
135
136         try {
137             return ResponseEntity.ok().body(provider.createControlLoops(controlLoops));
138
139         } catch (PfModelRuntimeException | PfModelException e) {
140             LOGGER.warn("creation of control loop failed", e);
141             return createInstantiationErrorResponse(e);
142         }
143     }
144
145     /**
146      * Queries details of all control loops.
147      *
148      * @param requestId request ID used in ONAP logging
149      * @param name the name of the control loop to get, null for all control loops
150      * @param version the version of the control loop to get, null for all control loops
151      * @return the control loops
152      */
153     // @formatter:off
154     @GetMapping(value = "/instantiation",
155             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
156     @ApiOperation(value = "Query details of the requested control loops",
157             notes = "Queries details of the requested control loops, returning all control loop details",
158             response = ControlLoops.class,
159             tags = {TAGS},
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 = {TAGS},
224             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
225             responseHeaders = {
226                 @ResponseHeader(
227                     name = VERSION_MINOR_NAME,
228                     description = VERSION_MINOR_DESCRIPTION,
229                     response = String.class),
230                 @ResponseHeader(
231                     name = VERSION_PATCH_NAME,
232                     description = VERSION_PATCH_DESCRIPTION,
233                     response = String.class),
234                 @ResponseHeader(
235                     name = VERSION_LATEST_NAME,
236                     description = VERSION_LATEST_DESCRIPTION,
237                     response = String.class),
238                 @ResponseHeader(
239                     name = REQUEST_ID_NAME,
240                     description = REQUEST_ID_HDR_DESCRIPTION,
241                     response = UUID.class)
242             },
243             extensions = {
244                 @Extension
245                     (
246                         name = EXTENSION_NAME,
247                         properties = {
248                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
249                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
250                         }
251                     )
252             }
253         )
254     @ApiResponses(
255             value = {
256                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
257                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
258                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
259             }
260         )
261     // @formatter:on
262     public ResponseEntity<InstantiationResponse> update(
263             @RequestHeader(name = REQUEST_ID_NAME, required = false)
264             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
265             @ApiParam(value = "Entity Body of Control Loop", required = true)
266             @RequestBody ControlLoops controlLoops) {
267
268         try {
269             return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops));
270
271         } catch (PfModelRuntimeException | PfModelException e) {
272             LOGGER.warn("update of control loops failed", e);
273             return createInstantiationErrorResponse(e);
274         }
275     }
276
277     /**
278      * Deletes a control loop definition.
279      *
280      * @param requestId request ID used in ONAP logging
281      * @param name the name of the control loop to delete
282      * @param version the version of the control loop to delete
283      * @return a response
284      */
285     // @formatter:off
286     @DeleteMapping(value = "/instantiation",
287             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
288     @ApiOperation(value = "Delete a control loop",
289             notes = "Deletes a control loop, returning optional error details",
290             response = InstantiationResponse.class,
291             tags = {TAGS},
292             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
293             responseHeaders = {
294                 @ResponseHeader(
295                     name = VERSION_MINOR_NAME,
296                     description = VERSION_MINOR_DESCRIPTION,
297                     response = String.class),
298                 @ResponseHeader(
299                     name = VERSION_PATCH_NAME,
300                     description = VERSION_PATCH_DESCRIPTION,
301                     response = String.class),
302                 @ResponseHeader(
303                     name = VERSION_LATEST_NAME,
304                     description = VERSION_LATEST_DESCRIPTION,
305                     response = String.class),
306                 @ResponseHeader(
307                     name = REQUEST_ID_NAME,
308                     description = REQUEST_ID_HDR_DESCRIPTION,
309                     response = UUID.class)},
310             extensions = {
311                 @Extension
312                     (
313                         name = EXTENSION_NAME,
314                         properties = {
315                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
316                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
317                         }
318                     )
319                 }
320         )
321     @ApiResponses(
322         value = {
323             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
324             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
325             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
326         }
327     )
328     // @formatter:on
329
330     public ResponseEntity<InstantiationResponse> delete(
331             @RequestHeader(name = REQUEST_ID_NAME, required = false)
332             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
333             @ApiParam(value = "Control Loop definition name", required = true)
334             @RequestParam("name") String name,
335             @ApiParam(value = "Control Loop definition version")
336             @RequestParam(value = "version", required = false) String version) {
337
338         try {
339             return ResponseEntity.ok().body(provider.deleteControlLoop(name, version));
340
341         } catch (PfModelRuntimeException | PfModelException e) {
342             LOGGER.warn("delete of control loop failed", e);
343             return createInstantiationErrorResponse(e);
344         }
345     }
346
347     /**
348      * Issues control loop commands to control loops.
349      *
350      * @param requestId request ID used in ONAP logging
351      * @param command the command to issue to control loops
352      * @return the control loop definitions
353      */
354     // @formatter:off
355     @PutMapping(value = "/instantiation/command",
356             produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML},
357             consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML})
358     @ApiOperation(value = "Issue a command to the requested control loops",
359             notes = "Issues a command to a control loop, ordering a state change on the control loop",
360             response = InstantiationResponse.class,
361             tags = {TAGS},
362             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
363             responseHeaders = {
364                 @ResponseHeader(
365                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
366                     response = String.class),
367                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
368                     response = String.class),
369                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
370                     response = String.class),
371                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
372                     response = UUID.class)},
373             extensions = {
374                 @Extension
375                     (
376                         name = EXTENSION_NAME,
377                         properties = {
378                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
379                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
380                         }
381                     )
382                 }
383         )
384     @ApiResponses(
385             value = {
386                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
387                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
388                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
389             }
390         )
391     // @formatter:on
392     public ResponseEntity<InstantiationResponse> issueControlLoopCommand(
393             @RequestHeader(name = REQUEST_ID_NAME, required = false)
394             @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
395             @ApiParam(value = "Entity Body of control loop command", required = true)
396             @RequestBody InstantiationCommand command) {
397
398         try {
399             return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command));
400
401         } catch (PfModelRuntimeException | PfModelException | ControlLoopException e) {
402             LOGGER.warn("creation of control loop failed", e);
403             return createInstantiationErrorResponse(e);
404         }
405     }
406
407     /**
408      * create a Instantiation Response from an exception.
409      *
410      * @param e the error
411      * @return the Instantiation Response
412      */
413     private ResponseEntity<InstantiationResponse> createInstantiationErrorResponse(ErrorResponseInfo e) {
414         var resp = new InstantiationResponse();
415         resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
416         return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
417     }
418 }