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