ebfbbd5eefc820eef07a5594eebefa965fb8a017
[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.tosca.authorative.concepts.ToscaNodeTemplate;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * Class to provide REST end points for creating, deleting, querying commissioned control loops.
54  */
55 public class CommissioningController extends RestController {
56
57     private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
58
59     private final CommissioningProvider provider;
60
61     /**
62      * create Commissioning Controller.
63      */
64     public CommissioningController() {
65         this.provider = CommissioningHandler.getInstance().getProvider();
66     }
67
68     /**
69      * Creates a control loop definition.
70      *
71      * @param requestId request ID used in ONAP logging
72      * @param body the body of control loop following TOSCA definition
73      * @return a response
74      */
75     // @formatter:off
76     @POST
77     @Path("/commission")
78     @ApiOperation(
79             value = "Commissions control loop definitions",
80             notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
81             response = CommissioningResponse.class,
82             tags = {"Control Loop Commissioning API"},
83             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
84             responseHeaders = {
85                 @ResponseHeader(
86                     name = VERSION_MINOR_NAME,
87                     description = VERSION_MINOR_DESCRIPTION,
88                     response = String.class),
89                 @ResponseHeader(
90                     name = VERSION_PATCH_NAME,
91                     description = VERSION_PATCH_DESCRIPTION,
92                     response = String.class),
93                 @ResponseHeader(
94                     name = VERSION_LATEST_NAME,
95                     description = VERSION_LATEST_DESCRIPTION,
96                     response = String.class),
97                 @ResponseHeader(
98                     name = REQUEST_ID_NAME,
99                     description = REQUEST_ID_HDR_DESCRIPTION,
100                     response = UUID.class)
101             },
102             extensions = {
103                 @Extension
104                     (
105                         name = EXTENSION_NAME,
106                         properties = {
107                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
108                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
109                         }
110                     )
111             }
112     )
113     @ApiResponses(
114             value = {
115                 @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
116                 @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
117                 @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
118             }
119     )
120     // @formatter:on
121     public Response create(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
122         @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) {
123
124         try {
125             CommissioningResponse response = provider.createControlLoopDefinitions(body);
126             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
127                 .build();
128
129         } catch (PfModelRuntimeException | PfModelException e) {
130             LOGGER.warn("Commissioning of the control loops failed", e);
131             var resp = new CommissioningResponse();
132             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
133             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
134         }
135
136     }
137
138     /**
139      * Deletes a control loop definition.
140      *
141      * @param requestId request ID used in ONAP logging
142      * @param name the name of the control loop definition to delete
143      * @param version the version of the control loop definition to delete
144      * @return a response
145      */
146     // @formatter:off
147     @DELETE
148     @Path("/commission")
149     @ApiOperation(value = "Delete a commissioned control loop",
150             notes = "Deletes a Commissioned Control Loop, returning optional error details",
151             response = CommissioningResponse.class,
152             tags = {"Clamp Control Loop Commissioning API"},
153             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
154             responseHeaders = {
155                 @ResponseHeader(
156                     name = VERSION_MINOR_NAME,
157                     description = VERSION_MINOR_DESCRIPTION,
158                     response = String.class),
159                 @ResponseHeader(
160                     name = VERSION_PATCH_NAME,
161                     description = VERSION_PATCH_DESCRIPTION,
162                     response = String.class),
163                 @ResponseHeader(
164                     name = VERSION_LATEST_NAME,
165                     description = VERSION_LATEST_DESCRIPTION,
166                     response = String.class),
167                 @ResponseHeader(
168                             name = REQUEST_ID_NAME,
169                             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 Response delete(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
191         @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
192         @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) {
193
194         try {
195             CommissioningResponse response = provider.deleteControlLoopDefinition(name, version);
196             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
197                 .build();
198
199         } catch (PfModelRuntimeException | PfModelException e) {
200             LOGGER.warn("Decommisssioning of control loop failed", e);
201             var resp = new CommissioningResponse();
202             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
203             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
204         }
205
206     }
207
208     /**
209      * Queries details of all or specific control loop definitions.
210      *
211      * @param requestId request ID used in ONAP logging
212      * @param name the name of the control loop definition to get, null for all definitions
213      * @param version the version of the control loop definition to get, null for all definitions
214      * @return the control loop definitions
215      */
216     // @formatter:off
217     @GET
218     @Path("/commission")
219     @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
220             notes = "Queries details of the requested commissioned control loop definitions, "
221                     + "returning all control loop details",
222             response = ToscaNodeTemplate.class,
223             tags = {"Clamp Control Loop Commissioning API"},
224             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
225             responseHeaders = {
226                 @ResponseHeader(
227                         name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
228                         response = String.class),
229                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
230                         response = String.class),
231                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
232                         response = String.class),
233                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
234                         response = UUID.class)},
235         extensions = {
236             @Extension
237                 (
238                     name = EXTENSION_NAME,
239                     properties = {
240                         @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
241                         @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
242                     }
243                 )
244             }
245     )
246     @ApiResponses(
247         value = {
248             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
249             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
250             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
251         }
252     )
253     // @formatter:on
254     public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
255         @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
256         @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) {
257
258         try {
259             List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version);
260             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
261                 .build();
262
263         } catch (PfModelRuntimeException | PfModelException e) {
264             LOGGER.warn("Get of control loop definitions failed", e);
265             var resp = new CommissioningResponse();
266             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
267             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
268         }
269
270     }
271
272     /**
273      * Retrieves the Tosca Service Template.
274      *
275      * @param requestId request ID used in ONAP logging
276      * @param name the name of the tosca service template to retrieve
277      * @param version the version of the tosca service template to get
278      * @return the specified tosca service template
279      */
280     // @formatter:off
281     @GET
282     @Path("/commission/toscaservicetemplate")
283     @ApiOperation(value = "Query details of the requested tosca service templates",
284             notes = "Queries details of the requested commissioned tosca service template, "
285                     + "returning all tosca service template details",
286             response = ToscaServiceTemplate.class,
287             tags = {"Clamp Control Loop Commissioning API"},
288             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
289             responseHeaders = {
290                 @ResponseHeader(
291                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
292                     response = String.class),
293                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
294                     response = String.class),
295                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
296                     response = String.class),
297                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
298                     response = UUID.class)},
299             extensions = {
300                 @Extension
301                     (
302                         name = EXTENSION_NAME,
303                         properties = {
304                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
305                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
306                         }
307                     )
308             }
309     )
310     @ApiResponses(
311         value = {
312             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
313             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
314             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
315         }
316     )
317     // @formatter:on
318     public Response queryToscaServiceTemplate(
319         @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
320         @ApiParam(value = "Tosca service template name", required = true) @QueryParam("name") String name,
321         @ApiParam(value = "Tosca service template version", required = true) @QueryParam("version") String version) {
322
323         try {
324             var response = provider.getToscaServiceTemplate(name, version);
325             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
326                 .build();
327
328         } catch (PfModelRuntimeException | PfModelException e) {
329             LOGGER.warn("Get of tosca service template failed", e);
330             var resp = new CommissioningResponse();
331             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
332             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
333         }
334
335     }
336
337     /**
338      * Queries the elements of a specific control loop.
339      *
340      * @param requestId request ID used in ONAP logging
341      * @param name the name of the control loop definition to get
342      * @param version the version of the control loop definition to get
343      * @return the control loop element definitions
344      */
345     // @formatter:off
346     @GET
347     @Path("/commission/elements")
348     @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
349             notes = "Queries details of the requested commissioned control loop element definitions, "
350                     + "returning all control loop elements' details",
351             response = ToscaNodeTemplate.class,
352             tags = {"Clamp Control Loop Commissioning API"},
353             authorizations = @Authorization(value = AUTHORIZATION_TYPE),
354             responseHeaders = {
355                 @ResponseHeader(
356                     name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
357                     response = String.class),
358                 @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
359                     response = String.class),
360                 @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
361                     response = String.class),
362                 @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
363                     response = UUID.class)},
364             extensions = {
365                 @Extension
366                     (
367                         name = EXTENSION_NAME,
368                         properties = {
369                             @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
370                             @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
371                         }
372                     )
373             }
374     )
375     @ApiResponses(
376         value = {
377             @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
378             @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
379             @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
380         }
381     )
382     // @formatter:on
383     public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
384         @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
385         @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) {
386
387         try {
388             List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
389             // Prevent ambiguous queries with multiple returns
390             if (nodeTemplate.size() > 1) {
391                 var resp = new CommissioningResponse();
392                 resp.setErrorDetails("Multiple ControlLoops are not supported");
393                 return returnResponse(Response.Status.NOT_ACCEPTABLE, requestId, resp);
394             }
395
396             List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
397             return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
398                 .build();
399
400         } catch (PfModelRuntimeException | PfModelException e) {
401             LOGGER.warn("Get of control loop element definitions failed", e);
402             var resp = new CommissioningResponse();
403             resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
404             return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp);
405         }
406
407     }
408
409     private Response returnResponse(Response.Status status, UUID requestId, CommissioningResponse resp) {
410         return addLoggingHeaders(addVersionControlHeaders(Response.status(status)), requestId).entity(resp).build();
411     }
412 }