cd6c08e30ed898f8291704503ab7dc546e6ce487
[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.commissioning.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 javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
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.models.messages.rest.commissioning.CommissioningResponse;
42 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler;
43 import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
44 import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController;
45 import org.onap.policy.models.base.PfModelException;
46 import org.onap.policy.models.base.PfModelRuntimeException;
47 import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * Class to provide REST end points for creating, deleting, querying commissioned control loops.
55  */
56 public class CommissioningController extends RestController {
57
58     private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
59
60     private final CommissioningProvider provider;
61
62     /**
63      * create Commissioning Controller.
64      */
65     public CommissioningController() {
66         this.provider = CommissioningHandler.getInstance().getProvider();
67     }
68
69     /**
70      * Creates a control loop definition.
71      *
72      * @param requestId request ID used in ONAP logging
73      * @param body the body of control loop following TOSCA definition
74      * @return a response
75      */
76     // @formatter:off
77     @POST
78     @Path("/commission")
79     @ApiOperation(
80             value = "Commissions control loop definitions",
81             notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
82             response = CommissioningResponse.class,
83             tags = {
84                     "Control Loop Commissioning API"
85             },
86             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
87             responseHeaders = {
88                     @ResponseHeader(
89                             name = VERSION_MINOR_NAME,
90                             description = VERSION_MINOR_DESCRIPTION,
91                             response = String.class),
92                     @ResponseHeader(
93                             name = VERSION_PATCH_NAME,
94                             description = VERSION_PATCH_DESCRIPTION,
95                             response = String.class),
96                     @ResponseHeader(
97                             name = VERSION_LATEST_NAME,
98                             description = VERSION_LATEST_DESCRIPTION,
99                             response = String.class),
100                     @ResponseHeader(
101                             name = REQUEST_ID_NAME,
102                             description = REQUEST_ID_HDR_DESCRIPTION,
103                             response = UUID.class)
104             },
105             extensions = {
106                     @Extension(
107                             name = EXTENSION_NAME,
108                             properties = {
109                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
110                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
111                             }
112                     )
113             }
114     )
115     @ApiResponses(
116             value = {
117                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
118                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
119                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
120             }
121     )
122     // @formatter:on
123     public Response create(
124             @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
125             @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) {
126
127         try {
128             CommissioningResponse response = provider.createControlLoopDefinitions(body);
129             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
130                     .entity(response).build();
131
132         } catch (PfModelRuntimeException | PfModelException e) {
133             LOGGER.warn("Commissioning of the control loops failed", e);
134             return createCommissioningErrorResponse(e, requestId);
135         }
136
137     }
138
139     /**
140      * Deletes a control loop definition.
141      *
142      * @param requestId request ID used in ONAP logging
143      * @param name the name of the control loop definition to delete
144      * @param version the version of the control loop definition to delete
145      * @return a response
146      */
147     // @formatter:off
148     @DELETE
149     @Path("/commission")
150     @ApiOperation(value = "Delete a commissioned control loop",
151             notes = "Deletes a Commissioned Control Loop, returning optional error details",
152             response = CommissioningResponse.class,
153             tags = {
154                     "Clamp Control Loop Commissioning API"
155             },
156             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
157             responseHeaders = {
158                     @ResponseHeader(
159                             name = VERSION_MINOR_NAME,
160                             description = VERSION_MINOR_DESCRIPTION,
161                             response = String.class),
162                     @ResponseHeader(
163                             name = VERSION_PATCH_NAME,
164                             description = VERSION_PATCH_DESCRIPTION,
165                             response = String.class),
166                     @ResponseHeader(
167                             name = VERSION_LATEST_NAME,
168                             description = VERSION_LATEST_DESCRIPTION,
169                             response = String.class),
170                     @ResponseHeader(
171                             name = REQUEST_ID_NAME,
172                             description = REQUEST_ID_HDR_DESCRIPTION,
173                             response = UUID.class)},
174             extensions = {
175                     @Extension(
176                             name = EXTENSION_NAME,
177                             properties = {
178                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
179                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
180                             }
181                     )
182             }
183     )
184     @ApiResponses(value = {
185             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
186             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
187             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
188         }
189     )
190     // @formatter:on
191     public Response delete(
192             @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
193             @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
194             @ApiParam(value = "Control Loop definition version", required = true)
195             @QueryParam("version") String version) {
196
197         try {
198             CommissioningResponse response = provider.deleteControlLoopDefinition(name, version);
199             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
200                     .entity(response).build();
201
202         } catch (PfModelRuntimeException | PfModelException e) {
203             LOGGER.warn("Decommisssioning of control loop failed", e);
204             return createCommissioningErrorResponse(e, requestId);
205         }
206
207     }
208
209     /**
210      * Queries details of all or specific control loop definitions.
211      *
212      * @param requestId request ID used in ONAP logging
213      * @param name the name of the control loop definition to get, null for all definitions
214      * @param version the version of the control loop definition to get, null for all definitions
215      * @return the control loop definitions
216      */
217     // @formatter:off
218     @GET
219     @Path("/commission")
220     @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
221             notes = "Queries details of the requested commissioned control loop definitions, "
222                     + "returning all control loop details",
223             response = ToscaNodeTemplate.class,
224             tags = {
225                     "Clamp Control Loop Commissioning API"
226             },
227             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
228             responseHeaders = {
229                     @ResponseHeader(
230                             name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
231                             response = String.class),
232                     @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
233                             response = String.class),
234                     @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
235                             response = String.class),
236                     @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
237                             response = UUID.class)},
238             extensions = {
239                     @Extension(
240                             name = EXTENSION_NAME,
241                             properties = {
242                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
243                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
244                             }
245                     )
246             }
247     )
248     @ApiResponses(
249             value = {
250                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
251                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
252                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
253             }
254     )
255     // @formatter:on
256     public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
257                           @ApiParam(value = "Control Loop definition name", required = true)
258                               @QueryParam("name") String name,
259                           @ApiParam(value = "Control Loop definition version", required = true)
260                               @QueryParam("version") String version) {
261
262         try {
263             List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version);
264             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
265                     .build();
266
267         } catch (PfModelRuntimeException | PfModelException e) {
268             LOGGER.warn("Get of control loop definitions failed", e);
269             return createCommissioningErrorResponse(e, requestId);
270         }
271
272     }
273
274     /**
275      * Queries the elements of a specific control loop.
276      *
277      * @param requestId request ID used in ONAP logging
278      * @param name the name of the control loop definition to get
279      * @param version the version of the control loop definition to get
280      * @return the control loop element definitions
281      */
282     // @formatter:off
283     @GET
284     @Path("/commission/elements")
285     @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
286             notes = "Queries details of the requested commissioned control loop element definitions, "
287                     + "returning all control loop elements' details",
288             response = ToscaNodeTemplate.class,
289             tags = {
290                     "Clamp Control Loop Commissioning API"
291             },
292             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
293             responseHeaders = {
294                     @ResponseHeader(
295                             name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
296                             response = String.class),
297                     @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
298                             response = String.class),
299                     @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
300                             response = String.class),
301                     @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
302                             response = UUID.class)},
303             extensions = {
304                     @Extension(
305                             name = EXTENSION_NAME,
306                             properties = {
307                                     @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
308                                     @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
309                             }
310                     )
311             }
312     )
313     @ApiResponses(
314             value = {
315                     @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
316                     @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
317                     @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
318             }
319     )
320     // @formatter:on
321     public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
322                           @ApiParam(value = "Control Loop definition name", required = true)
323                           @QueryParam("name") String name,
324                           @ApiParam(value = "Control Loop definition version", required = true)
325                           @QueryParam("version") String version) throws Exception {
326
327         try {
328             List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
329             //Prevent ambiguous queries with multiple returns
330             if (nodeTemplate.size() > 1) {
331                 throw new Exception();
332             }
333             List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
334             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
335                     .build();
336
337         } catch (PfModelRuntimeException | PfModelException e) {
338             LOGGER.warn("Get of control loop element definitions failed", e);
339             return createCommissioningErrorResponse(e, requestId);
340         }
341
342     }
343
344     private Response createCommissioningErrorResponse(ErrorResponseInfo e, UUID requestId) {
345         CommissioningResponse resp = new CommissioningResponse();
346         resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
347         return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
348                 requestId).entity(resp).build();
349     }
350
351 }