Merge "Refactor WriteSubJobSpec to make use of test REST endpoint of write job"
[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-2025 OpenInfra Foundation Europe
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.data.models.DatastoreType.OPERATIONAL;
27 import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_RUNNING;
28 import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE;
29 import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE;
30 import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH;
31 import static org.onap.cps.ncmp.api.data.models.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.api.model.DataNode;
42 import org.onap.cps.api.model.ModuleDefinition;
43 import org.onap.cps.ncmp.api.data.exceptions.InvalidDatastoreException;
44 import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
45 import org.onap.cps.ncmp.api.data.models.DatastoreType;
46 import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade;
47 import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryApiParameters;
48 import org.onap.cps.ncmp.api.inventory.models.CompositeState;
49 import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
50 import org.onap.cps.ncmp.impl.data.NetworkCmProxyFacade;
51 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
52 import org.onap.cps.ncmp.rest.model.CmHandleQueryParameters;
53 import org.onap.cps.ncmp.rest.model.DataOperationRequest;
54 import org.onap.cps.ncmp.rest.model.RestModuleDefinition;
55 import org.onap.cps.ncmp.rest.model.RestModuleReference;
56 import org.onap.cps.ncmp.rest.model.RestOutputCmHandle;
57 import org.onap.cps.ncmp.rest.model.RestOutputCmHandleCompositeState;
58 import org.onap.cps.ncmp.rest.model.RestOutputPublicCmHandleProperties;
59 import org.onap.cps.ncmp.rest.util.CmHandleStateMapper;
60 import org.onap.cps.ncmp.rest.util.CountCmHandleSearchExecution;
61 import org.onap.cps.ncmp.rest.util.DataOperationRequestMapper;
62 import org.onap.cps.ncmp.rest.util.DeprecationHelper;
63 import org.onap.cps.ncmp.rest.util.NcmpRestInputMapper;
64 import org.onap.cps.ncmp.rest.util.RestOutputCmHandleMapper;
65 import org.onap.cps.utils.JsonObjectMapper;
66 import org.springframework.http.HttpStatus;
67 import org.springframework.http.ResponseEntity;
68 import org.springframework.util.StringUtils;
69 import org.springframework.web.bind.annotation.RequestMapping;
70 import org.springframework.web.bind.annotation.RestController;
71
72 @Slf4j
73 @RestController
74 @RequestMapping("${rest.api.ncmp-base-path}")
75 @RequiredArgsConstructor
76 public class NetworkCmProxyController implements NetworkCmProxyApi {
77
78     private static final String NO_BODY = null;
79     private final NetworkCmProxyFacade networkCmProxyFacade;
80     private final NetworkCmProxyInventoryFacade networkCmProxyInventoryFacade;
81     private final JsonObjectMapper jsonObjectMapper;
82     private final DeprecationHelper deprecationHelper;
83     private final NcmpRestInputMapper ncmpRestInputMapper;
84     private final CmHandleStateMapper cmHandleStateMapper;
85     private final DataOperationRequestMapper dataOperationRequestMapper;
86     private final RestOutputCmHandleMapper restOutputCmHandleMapper;
87
88     /**
89      * Get resource data from datastore.
90      *
91      * @param datastoreName        name of the datastore
92      * @param cmHandleReference    cm handle or alternate id identifier
93      * @param resourceIdentifier   resource identifier
94      * @param optionsParamInQuery  options query parameter
95      * @param topicParamInQuery    topic query parameter
96      * @param includeDescendants   whether to include descendants or not
97      * @param authorization        contents of Authorization header, or null if not present
98      * @return {@code ResponseEntity} response from dmi plugin
99      */
100     @Override
101     @Timed(value = "cps.ncmp.controller.get", description = "Time taken to get resource data from datastore")
102     public ResponseEntity<Object> getResourceDataForCmHandle(final String datastoreName,
103                                                              final String cmHandleReference,
104                                                              final String resourceIdentifier,
105                                                              final String optionsParamInQuery,
106                                                              final String topicParamInQuery,
107                                                              final Boolean includeDescendants,
108                                                              final String authorization) {
109         final CmResourceAddress cmResourceAddress = new CmResourceAddress(datastoreName, cmHandleReference,
110             resourceIdentifier);
111         final Object result = networkCmProxyFacade.getResourceDataForCmHandle(cmResourceAddress, optionsParamInQuery,
112             topicParamInQuery, includeDescendants, authorization);
113         return ResponseEntity.ok(result);
114     }
115
116     @Override
117     public ResponseEntity<Object> executeDataOperationForCmHandles(final String topicParamInQuery,
118                                                                    final DataOperationRequest dataOperationRequest,
119                                                                    final String authorization) {
120         final Object result = networkCmProxyFacade.executeDataOperationForCmHandles(topicParamInQuery,
121                 dataOperationRequestMapper.toDataOperationRequest(dataOperationRequest), authorization);
122         return ResponseEntity.ok(result);
123     }
124
125     /**
126      * Query resource data from datastore.
127      *
128      * @param datastoreName        name of the datastore (currently only supports "ncmp-datastore:operational")
129      * @param cmHandle             cm handle identifier
130      * @param cpsPath              CPS Path
131      * @param optionsParamInQuery  options query parameter
132      * @param topicParamInQuery    topic query parameter
133      * @param includeDescendants   whether to include descendants or not
134      * @return {@code ResponseEntity} response. Body contains a collection of DataNodes
135      */
136
137     @Override
138     public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName,
139                                                                final String cmHandle,
140                                                                final String cpsPath,
141                                                                final String optionsParamInQuery,
142                                                                final String topicParamInQuery,
143                                                                final Boolean includeDescendants) {
144         validateDataStore(OPERATIONAL, datastoreName);
145         final Collection<DataNode> dataNodes = networkCmProxyFacade.queryResourceDataForCmHandle(cmHandle, cpsPath,
146             includeDescendants);
147         return ResponseEntity.ok(dataNodes);
148     }
149
150     /**
151      * Patch resource data.
152      *
153      * @param datastoreName      name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
154      * @param cmHandleReference  cm handle or alternate identifier
155      * @param resourceIdentifier resource identifier
156      * @param requestBody        the request body
157      * @param contentType        content type of body
158      * @param authorization      contents of Authorization header, or null if not present
159      * @return {@code ResponseEntity} response from dmi plugin
160      */
161
162     @Override
163     public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName,
164                                                                       final String cmHandleReference,
165                                                                       final String resourceIdentifier,
166                                                                       final Object requestBody,
167                                                                       final String contentType,
168                                                                       final String authorization) {
169
170         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
171
172         final Object responseObject = networkCmProxyFacade
173                 .writeResourceDataPassThroughRunningForCmHandle(
174                         cmHandleReference, resourceIdentifier, PATCH,
175                         jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
176         return ResponseEntity.ok(responseObject);
177     }
178
179     /**
180      * Create resource data for given cm-handle.
181      *
182      * @param datastoreName      name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
183      * @param cmHandleReference  cm handle or alternate identifier
184      * @param resourceIdentifier resource identifier
185      * @param requestBody        the request body
186      * @param contentType        content type of body
187      * @param authorization      contents of Authorization header, or null if not present
188      * @return {@code ResponseEntity} response from dmi plugin
189      */
190     @Override
191     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName,
192                                                                      final String cmHandleReference,
193                                                                      final String resourceIdentifier,
194                                                                      final Object requestBody,
195                                                                      final String contentType,
196                                                                      final String authorization) {
197         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
198
199         networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
200                 resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
201         return new ResponseEntity<>(HttpStatus.CREATED);
202     }
203
204     /**
205      * Update resource data for given cm-handle.
206      *
207      * @param datastoreName      name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
208      * @param cmHandleReference  cm handle or alternate identifier
209      * @param resourceIdentifier resource identifier
210      * @param requestBody        the request body
211      * @param contentType        content type of the body
212      * @param authorization      contents of Authorization header, or null if not present
213      * @return response entity
214      */
215
216     @Override
217     public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
218                                                                        final String cmHandleReference,
219                                                                        final String resourceIdentifier,
220                                                                        final Object requestBody,
221                                                                        final String contentType,
222                                                                        final String authorization) {
223         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
224
225         networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
226                 resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
227         return new ResponseEntity<>(HttpStatus.OK);
228     }
229
230     /**
231      * Delete resource data for a given cm-handle.
232      *
233      * @param datastoreName      name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
234      * @param cmHandleReference  cm handle or alternate identifier
235      * @param resourceIdentifier resource identifier
236      * @param contentType        content type of the body
237      * @param authorization      contents of Authorization header, or null if not present
238      * @return response entity no content if request is successful
239      */
240     @Override
241     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
242                                                                      final String cmHandleReference,
243                                                                      final String resourceIdentifier,
244                                                                      final String contentType,
245                                                                      final String authorization) {
246
247         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
248
249         networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
250                 resourceIdentifier, DELETE, NO_BODY, contentType, authorization);
251         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
252     }
253
254     /**
255      * Query and return cm handles that match the given query parameters.
256      *
257      * @param cmHandleQueryParameters the cm handle query parameters
258      * @return collection of cm handles
259      */
260     @Override
261     @SuppressWarnings("deprecation") // mapOldConditionProperties method will be removed in Release 12
262     @CountCmHandleSearchExecution(methodName = "searchCmHandles", interfaceName = "CPS-E-05",
263         description = "Search for cm handles within CPS-E-05 interface")
264     public ResponseEntity<List<RestOutputCmHandle>> searchCmHandles(
265             final CmHandleQueryParameters cmHandleQueryParameters) {
266         final CmHandleQueryApiParameters cmHandleQueryApiParameters =
267                 deprecationHelper.mapOldConditionProperties(cmHandleQueryParameters);
268         final List<RestOutputCmHandle> restOutputCmHandles =
269                 networkCmProxyInventoryFacade.northboundCmHandleSearch(cmHandleQueryApiParameters)
270                         .map(ncmpServiceCmHandle -> restOutputCmHandleMapper
271                                 .toRestOutputCmHandle(ncmpServiceCmHandle, false)).collectList().block();
272         return ResponseEntity.ok(restOutputCmHandles);
273     }
274
275     /**
276      * Query and return cm handle ids or alternate ids that match the given query parameters.
277      *
278      * @param cmHandleQueryParameters   the cm handle query parameters
279      * @param outputAlternateId         Boolean for cm handle reference type either
280      *                                  cm handle id (false or null) or alternate id (true)
281      * @return                          collection of cm handle ids
282      */
283     @Override
284     @CountCmHandleSearchExecution(methodName = "searchCmHandleIds", interfaceName = "CPS-E-05",
285             description = "Search for cm handles within CPS-E-05 interface")
286     public ResponseEntity<List<String>> searchCmHandleIds(final CmHandleQueryParameters cmHandleQueryParameters,
287                                                           final Boolean outputAlternateId) {
288         final CmHandleQueryApiParameters cmHandleQueryApiParameters =
289                 jsonObjectMapper.convertToValueType(cmHandleQueryParameters, CmHandleQueryApiParameters.class);
290         final Collection<String> cmHandleIds
291             = networkCmProxyInventoryFacade.northboundCmHandleIdSearch(cmHandleQueryApiParameters, outputAlternateId);
292         return ResponseEntity.ok(List.copyOf(cmHandleIds));
293     }
294
295     /**
296      * Search for Cm Handle and Properties by Name.
297      *
298      * @param cmHandleReference cm-handle or alternate identifier
299      * @return cm handle and its properties
300      */
301     @Override
302     public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleReference) {
303         final NcmpServiceCmHandle ncmpServiceCmHandle
304             = networkCmProxyInventoryFacade.getNcmpServiceCmHandle(cmHandleReference);
305         final RestOutputCmHandle restOutputCmHandle = restOutputCmHandleMapper
306                 .toRestOutputCmHandle(ncmpServiceCmHandle, false);
307         return ResponseEntity.ok(restOutputCmHandle);
308     }
309
310     /**
311      * Get Cm Handle Properties by Cm Handle or alternate Identifier.
312      *
313      * @param cmHandleReference cm-handle or alternate identifier
314      * @return cm handle properties
315      */
316     @Override
317     public ResponseEntity<RestOutputPublicCmHandleProperties> getPublicCmHandlePropertiesByCmHandleId(
318             final String cmHandleReference) {
319         final List<Map<String, String>> publicCmHandleProperties = new ArrayList<>(1);
320         publicCmHandleProperties.add(networkCmProxyInventoryFacade.getPublicCmHandleProperties(cmHandleReference));
321         final RestOutputPublicCmHandleProperties restOutputPublicCmHandleProperties =
322                 new RestOutputPublicCmHandleProperties();
323         restOutputPublicCmHandleProperties.setPublicCmHandleProperties(publicCmHandleProperties);
324         return ResponseEntity.ok(restOutputPublicCmHandleProperties);
325     }
326
327     /**
328      * Get Cm Handle State by Cm Handle Id.
329      *
330      * @param cmHandleReference cm-handle or alternate identifier
331      * @return cm handle state
332      */
333     @Override
334     public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
335             final String cmHandleReference) {
336         final CompositeState cmHandleState = networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleReference);
337         final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState =
338                 new RestOutputCmHandleCompositeState();
339         restOutputCmHandleCompositeState.setState(
340                 cmHandleStateMapper.toCmHandleCompositeStateExternalLockReason(cmHandleState));
341         return ResponseEntity.ok(restOutputCmHandleCompositeState);
342     }
343
344     /**
345      * Return module definitions.
346      *
347      * @param cmHandleReference   cm handle or alternate id identifier
348      * @param moduleName          module name
349      * @param revision            the revision of the module
350      * @return list of module definitions (module name, revision, yang resource content)
351      */
352     @Override
353     public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleReference,
354                                                                            final String moduleName,
355                                                                            final String revision) {
356         final Collection<ModuleDefinition> moduleDefinitions;
357         if (StringUtils.hasText(moduleName)) {
358             moduleDefinitions =
359                 networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule(cmHandleReference,
360                     moduleName, revision);
361         } else {
362             moduleDefinitions =
363                 networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleReference(cmHandleReference);
364             if (StringUtils.hasText(revision)) {
365                 log.warn("Ignoring revision filter as no module name is provided");
366             }
367         }
368         final List<RestModuleDefinition> response = new ArrayList<>();
369         for (final ModuleDefinition moduleDefinition: moduleDefinitions) {
370             response.add(ncmpRestInputMapper.toRestModuleDefinition(moduleDefinition));
371         }
372         return new ResponseEntity<>(response, HttpStatus.OK);
373     }
374
375     /**
376      * Return module references for a cm handle.
377      *
378      * @param cmHandleReference cm handle or alternate id identifier
379      * @return module references for cm handle. Namespace will be always blank because restConf does not include this.
380      */
381     public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandleReference) {
382         final List<RestModuleReference> restModuleReferences =
383             networkCmProxyInventoryFacade.getYangResourcesModuleReferences(cmHandleReference).stream()
384                         .map(ncmpRestInputMapper::toRestModuleReference)
385                         .collect(Collectors.toList());
386         return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
387     }
388
389     /**
390      * Set the data sync enabled flag, along with the data sync state for the specified cm handle.
391      *
392      * @param cmHandleId          cm handle id
393      * @param dataSyncEnabledFlag data sync enabled flag
394      * @return response entity ok if request is successful
395      */
396     @Override
397     public ResponseEntity<Object> setDataSyncEnabledFlagForCmHandle(final String cmHandleId,
398                                                                     final Boolean dataSyncEnabledFlag) {
399         networkCmProxyInventoryFacade.setDataSyncEnabled(cmHandleId, dataSyncEnabledFlag);
400         return new ResponseEntity<>(HttpStatus.OK);
401     }
402
403     private void validateDataStore(final DatastoreType acceptableDataStoreType, final String requestedDatastoreName) {
404         final DatastoreType datastoreType = DatastoreType.fromDatastoreName(requestedDatastoreName);
405
406         if (acceptableDataStoreType != datastoreType) {
407             throw new InvalidDatastoreException(requestedDatastoreName + " is not supported");
408         }
409     }
410
411 }
412