73bd8d72b0d410039d496bee792da2bad3aa7afc
[cps.git] / cps-ncmp-rest / src / main / java / org / onap / cps / ncmp / rest / controller / NetworkCmProxyController.java
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Pantheon.tech
4  *  Modifications Copyright (C) 2021-2024 Nordix Foundation
5  *  Modifications Copyright (C) 2021 highstreet technologies GmbH
6  *  Modifications Copyright (C) 2021-2022 Bell Canada
7  *  ================================================================================
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  *
20  *  SPDX-License-Identifier: Apache-2.0
21  *  ============LICENSE_END=========================================================
22  */
23
24 package org.onap.cps.ncmp.rest.controller;
25
26 import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
27 import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
28 import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE;
29 import static org.onap.cps.ncmp.api.impl.operations.OperationType.DELETE;
30 import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH;
31 import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE;
32
33 import io.micrometer.core.annotation.Timed;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.stream.Collectors;
39 import lombok.RequiredArgsConstructor;
40 import lombok.extern.slf4j.Slf4j;
41 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
42 import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
43 import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException;
44 import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
45 import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
46 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
47 import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
48 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
49 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
50 import org.onap.cps.ncmp.rest.controller.handlers.NcmpCachedResourceRequestHandler;
51 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreRequestHandler;
52 import org.onap.cps.ncmp.rest.controller.handlers.NcmpPassthroughResourceRequestHandler;
53 import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper;
54 import org.onap.cps.ncmp.rest.mapper.DataOperationRequestMapper;
55 import org.onap.cps.ncmp.rest.model.CmHandlePublicProperties;
56 import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
57 import org.onap.cps.ncmp.rest.model.DataOperationRequest;
58 import org.onap.cps.ncmp.rest.model.RestModuleDefinition;
59 import org.onap.cps.ncmp.rest.model.RestModuleReference;
60 import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
61 import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState;
62 import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties;
63 import org.onap.cps.ncmp.rest.util.DeprecationHelper;
64 import org.onap.cps.spi.model.ModuleDefinition;
65 import org.onap.cps.utils.JsonObjectMapper;
66 import org.springframework.beans.factory.annotation.Qualifier;
67 import org.springframework.http.HttpStatus;
68 import org.springframework.http.ResponseEntity;
69 import org.springframework.util.StringUtils;
70 import org.springframework.web.bind.annotation.RequestMapping;
71 import org.springframework.web.bind.annotation.RestController;
72
73 @Slf4j
74 @RestController
75 @RequestMapping("${rest.api.ncmp-base-path}")
76 @RequiredArgsConstructor
77 public class NetworkCmProxyController implements NetworkCmProxyApi {
78
79     private static final String NO_BODY = null;
80     private final NetworkCmProxyDataService networkCmProxyDataService;
81     private final JsonObjectMapper jsonObjectMapper;
82     private final DeprecationHelper deprecationHelper;
83     private final NcmpRestInputMapper ncmpRestInputMapper;
84     private final CmHandleStateMapper cmHandleStateMapper;
85     private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
86     private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
87     private final DataOperationRequestMapper dataOperationRequestMapper;
88     @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME)
89     private final Map<String, TrustLevel> trustLevelPerCmHandle;
90
91     /**
92      * Get resource data from datastore.
93      *
94      * @param datastoreName        name of the datastore
95      * @param cmHandle             cm handle identifier
96      * @param resourceIdentifier   resource identifier
97      * @param optionsParamInQuery  options query parameter
98      * @param topicParamInQuery    topic query parameter
99      * @param includeDescendants   whether to include descendants or not
100      * @return {@code ResponseEntity} response from dmi plugin
101      */
102     @Override
103     @Timed(value = "cps.ncmp.controller.get", description = "Time taken to get resource data from datastore")
104     public ResponseEntity<Object> getResourceDataForCmHandle(final String datastoreName,
105                                                              final String cmHandle,
106                                                              final String resourceIdentifier,
107                                                              final String optionsParamInQuery,
108                                                              final String topicParamInQuery,
109                                                              final Boolean includeDescendants) {
110         final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = getNcmpDatastoreRequestHandler(datastoreName);
111         return ncmpDatastoreRequestHandler.executeRequest(datastoreName, cmHandle, resourceIdentifier,
112                 optionsParamInQuery, topicParamInQuery, includeDescendants);
113     }
114
115     @Override
116     public ResponseEntity<Object> executeDataOperationForCmHandles(final String topicParamInQuery,
117                                                                   final DataOperationRequest
118                                                                           dataOperationRequest) {
119         return ncmpPassthroughResourceRequestHandler.executeRequest(topicParamInQuery,
120                 dataOperationRequestMapper.toDataOperationRequest(dataOperationRequest));
121     }
122
123     /**
124      * Query resource data from datastore.
125      *
126      * @param datastoreName        name of the datastore
127      * @param cmHandle             cm handle identifier
128      * @param cpsPath              CPS Path
129      * @param optionsParamInQuery  options query parameter
130      * @param topicParamInQuery    topic query parameter
131      * @param includeDescendants   whether to include descendants or not
132      * @return {@code ResponseEntity} response from dmi plugin
133      */
134
135     @Override
136     public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName,
137                                                                final String cmHandle,
138                                                                final String cpsPath,
139                                                                final String optionsParamInQuery,
140                                                                final String topicParamInQuery,
141                                                                final Boolean includeDescendants) {
142         validateDataStore(OPERATIONAL, datastoreName);
143         return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants);
144     }
145
146     /**
147      * Patch resource data from passthrough-running.
148      *
149      * @param datastoreName      name of the datastore
150      * @param cmHandle           cm handle identifier
151      * @param resourceIdentifier resource identifier
152      * @param requestBody        the request body
153      * @param contentType        content type of body
154      * @return {@code ResponseEntity} response from dmi plugin
155      */
156
157     @Override
158     public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName,
159                                                                       final String cmHandle,
160                                                                       final String resourceIdentifier,
161                                                                       final Object requestBody,
162                                                                       final String contentType) {
163
164         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
165
166         final Object responseObject = networkCmProxyDataService
167                 .writeResourceDataPassThroughRunningForCmHandle(
168                         cmHandle, resourceIdentifier, PATCH,
169                         jsonObjectMapper.asJsonString(requestBody), contentType);
170         return ResponseEntity.ok(responseObject);
171     }
172
173     /**
174      * Create resource data in datastore pass-through running for given cm-handle.
175      *
176      * @param datastoreName      name of the datastore
177      * @param cmHandle           cm handle identifier
178      * @param resourceIdentifier resource identifier
179      * @param requestBody        the request body
180      * @param contentType        content type of body
181      * @return {@code ResponseEntity} response from dmi plugin
182      */
183     @Override
184     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName,
185                                                                      final String cmHandle,
186                                                                      final String resourceIdentifier,
187                                                                      final Object requestBody,
188                                                                      final String contentType) {
189
190         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
191
192         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
193                 resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
194         return new ResponseEntity<>(HttpStatus.CREATED);
195     }
196
197     /**
198      * Update resource data in datastore pass-through running for given cm-handle.
199      *
200      * @param datastoreName      name of the datastore
201      * @param cmHandle           cm handle identifier
202      * @param resourceIdentifier resource identifier
203      * @param requestBody        the request body
204      * @param contentType        content type of the body
205      * @return response entity
206      */
207
208     @Override
209     public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
210                                                                        final String cmHandle,
211                                                                        final String resourceIdentifier,
212                                                                        final Object requestBody,
213                                                                        final String contentType) {
214         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
215
216         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
217                 resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType);
218         return new ResponseEntity<>(HttpStatus.OK);
219     }
220
221     /**
222      * Delete resource data in datastore pass-through running for a given cm-handle.
223      *
224      * @param datastoreName      name of the datastore
225      * @param cmHandle           cm handle identifier
226      * @param resourceIdentifier resource identifier
227      * @param contentType        content type of the body
228      * @return response entity no content if request is successful
229      */
230     @Override
231     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
232                                                                      final String cmHandle,
233                                                                      final String resourceIdentifier,
234                                                                      final String contentType) {
235
236         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
237
238         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
239                 resourceIdentifier, DELETE, NO_BODY, contentType);
240         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
241     }
242
243     /**
244      * Query and return cm handles that match the given query parameters.
245      *
246      * @param cmHandleQueryParameters the cm handle query parameters
247      * @return collection of cm handles
248      */
249     @Override
250     @SuppressWarnings("deprecation") // mapOldConditionProperties method will be removed in Release 12
251     public ResponseEntity<List<RestOutputCmHandle>> searchCmHandles(
252             final CmHandleQueryParameters cmHandleQueryParameters) {
253         final CmHandleQueryApiParameters cmHandleQueryApiParameters =
254                 deprecationHelper.mapOldConditionProperties(cmHandleQueryParameters);
255         final Collection<NcmpServiceCmHandle> cmHandles = networkCmProxyDataService
256                 .executeCmHandleSearch(cmHandleQueryApiParameters);
257         final List<RestOutputCmHandle> outputCmHandles =
258                 cmHandles.stream().map(this::toRestOutputCmHandle).collect(Collectors.toList());
259         return ResponseEntity.ok(outputCmHandles);
260     }
261
262     /**
263      * Query and return cm handle ids that match the given query parameters.
264      *
265      * @param cmHandleQueryParameters the cm handle query parameters
266      * @return collection of cm handle ids
267      */
268     @Override
269     public ResponseEntity<List<String>> searchCmHandleIds(
270             final CmHandleQueryParameters cmHandleQueryParameters) {
271         final CmHandleQueryApiParameters cmHandleQueryApiParameters =
272                 jsonObjectMapper.convertToValueType(cmHandleQueryParameters, CmHandleQueryApiParameters.class);
273         final Collection<String> cmHandleIds
274             = networkCmProxyDataService.executeCmHandleIdSearch(cmHandleQueryApiParameters);
275         return ResponseEntity.ok(List.copyOf(cmHandleIds));
276     }
277
278     /**
279      * Search for Cm Handle and Properties by Name.
280      *
281      * @param cmHandleId cm-handle identifier
282      * @return cm handle and its properties
283      */
284     @Override
285     public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) {
286         final NcmpServiceCmHandle ncmpServiceCmHandle = networkCmProxyDataService.getNcmpServiceCmHandle(cmHandleId);
287         final RestOutputCmHandle restOutputCmHandle = toRestOutputCmHandle(ncmpServiceCmHandle);
288         return ResponseEntity.ok(restOutputCmHandle);
289     }
290
291     /**
292      * Get Cm Handle Properties by Cm Handle Id.
293      *
294      * @param cmHandleId cm-handle identifier
295      * @return cm handle properties
296      */
297     @Override
298     public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
299             final String cmHandleId) {
300         final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
301         cmHandlePublicProperties.add(networkCmProxyDataService.getCmHandlePublicProperties(cmHandleId));
302         final RestOutputCmHandlePublicProperties restOutputCmHandlePublicProperties =
303                 new RestOutputCmHandlePublicProperties();
304         restOutputCmHandlePublicProperties.setPublicCmHandleProperties(cmHandlePublicProperties);
305         return ResponseEntity.ok(restOutputCmHandlePublicProperties);
306     }
307
308     /**
309      * Get Cm Handle State by Cm Handle Id.
310      *
311      * @param cmHandleId cm-handle identifier
312      * @return cm handle state
313      */
314     @Override
315     public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
316             final String cmHandleId) {
317         final CompositeState cmHandleState = networkCmProxyDataService.getCmHandleCompositeState(cmHandleId);
318         final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState =
319                 new RestOutputCmHandleCompositeState();
320         restOutputCmHandleCompositeState.setState(
321                 cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
322         return ResponseEntity.ok(restOutputCmHandleCompositeState);
323     }
324
325     /**
326      * Return module definitions.
327      *
328      * @param cmHandleId    cm-handle identifier
329      * @param moduleName    module name
330      * @param revision      the revision of the module
331      * @return list of module definitions (module name, revision, yang resource content)
332      */
333     @Override
334     public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleId,
335                                                                            final String moduleName,
336                                                                            final String revision) {
337         final Collection<ModuleDefinition> moduleDefinitions;
338         if (StringUtils.hasText(moduleName)) {
339             moduleDefinitions =
340                 networkCmProxyDataService.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, revision);
341         } else {
342             moduleDefinitions = networkCmProxyDataService.getModuleDefinitionsByCmHandleId(cmHandleId);
343             if (StringUtils.hasText(revision)) {
344                 log.warn("Ignoring revision filter as no module name is provided");
345             }
346         }
347         final List<RestModuleDefinition> response = new ArrayList<>();
348         for (final ModuleDefinition moduleDefinition: moduleDefinitions) {
349             response.add(ncmpRestInputMapper.toRestModuleDefinition(moduleDefinition));
350         }
351         return new ResponseEntity<>(response, HttpStatus.OK);
352     }
353
354     /**
355      * Return module references for a cm handle.
356      *
357      * @param cmHandle the cm handle
358      * @return module references for cm handle. Namespace will be always blank because restConf does not include this.
359      */
360     public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
361         final List<RestModuleReference> restModuleReferences =
362                 networkCmProxyDataService.getYangResourcesModuleReferences(cmHandle).stream()
363                         .map(ncmpRestInputMapper::toRestModuleReference)
364                         .collect(Collectors.toList());
365         return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
366     }
367
368     /**
369      * Set the data sync enabled flag, along with the data sync state for the specified cm handle.
370      *
371      * @param cmHandleId          cm handle id
372      * @param dataSyncEnabledFlag data sync enabled flag
373      * @return response entity ok if request is successful
374      */
375     @Override
376     public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
377                                                                     final Boolean dataSyncEnabledFlag) {
378         networkCmProxyDataService.setDataSyncEnabled(cmHandleId, dataSyncEnabledFlag);
379         return new ResponseEntity<>(HttpStatus.OK);
380     }
381
382
383     private RestOutputCmHandle toRestOutputCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) {
384         final RestOutputCmHandle restOutputCmHandle = new RestOutputCmHandle();
385         final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
386         final TrustLevel cmHandleCurrentTrustLevel = trustLevelPerCmHandle.get(ncmpServiceCmHandle.getCmHandleId());
387         restOutputCmHandle.setCmHandle(ncmpServiceCmHandle.getCmHandleId());
388         cmHandlePublicProperties.add(ncmpServiceCmHandle.getPublicProperties());
389         restOutputCmHandle.setPublicCmHandleProperties(cmHandlePublicProperties);
390         restOutputCmHandle.setState(cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(
391                 ncmpServiceCmHandle.getCompositeState()));
392         if (cmHandleCurrentTrustLevel != null) {
393             restOutputCmHandle.setTrustLevel(cmHandleCurrentTrustLevel.toString());
394         }
395         return restOutputCmHandle;
396     }
397
398     private void validateDataStore(final DatastoreType acceptableDataStoreType, final String requestedDatastoreName) {
399         final DatastoreType datastoreType = DatastoreType.fromDatastoreName(requestedDatastoreName);
400
401         if (acceptableDataStoreType != datastoreType) {
402             throw new InvalidDatastoreException(requestedDatastoreName + " is not supported");
403         }
404     }
405
406     private NcmpDatastoreRequestHandler getNcmpDatastoreRequestHandler(final String datastoreName) {
407         if (OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) {
408             return ncmpCachedResourceRequestHandler;
409         }
410         return ncmpPassthroughResourceRequestHandler;
411     }
412
413
414 }
415