summaryrefslogtreecommitdiffstats
path: root/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/controller/CompositionController.java
blob: 3261ddce9a2646d5ab91e83b6b897002c72c7dd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
package org.onap.sdc.dcae.composition.controller;

import org.json.JSONArray;
import org.json.JSONException;
import org.onap.sdc.common.onaplog.Enums.LogLevel;
import org.onap.sdc.dcae.composition.impl.CompositionBusinessLogic;
import org.onap.sdc.dcae.composition.restmodels.MessageResponse;
import org.onap.sdc.dcae.composition.restmodels.ReferenceUUID;
import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact;
import org.onap.sdc.dcae.composition.restmodels.sdc.Asset;
import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
import org.onap.sdc.dcae.catalog.Catalog;
import org.onap.sdc.dcae.catalog.Catalog.*;
import org.onap.sdc.dcae.catalog.engine.*;
import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
import org.onap.sdc.dcae.enums.LifecycleOperationType;
import org.onap.sdc.dcae.errormng.ActionStatus;
import org.onap.sdc.dcae.errormng.ErrConfMgr;
import org.onap.sdc.dcae.errormng.ErrConfMgr.ApiType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;

import javax.annotation.PostConstruct;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@EnableAutoConfiguration
@CrossOrigin
public class CompositionController extends BaseController {

	@Autowired private CatalogController catalogController;

	@Autowired private CompositionBusinessLogic compositionBusinessLogic;

	@PostConstruct public void init() {
		catalogController.setDefaultCatalog(URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.ASDC_CATALOG_URL)));
	}

	@RequestMapping(value = { "/utils/clone/{assetType}/{sourceId}/{targetId}" }, method = { RequestMethod.GET }, produces = { "application/json" }) public ResponseEntity clone(@RequestHeader("USER_ID") String userId,
			@PathVariable("assetType") String theAssetType, @PathVariable("sourceId") String theSourceId, @PathVariable("targetId") String theTargetId, @ModelAttribute("requestId") String requestId) {
		MessageResponse response = new MessageResponse();

		try {
			// fetch the source and assert it is a vfcmt containing clone worthy artifacts (composition + rules)
			ResourceDetailed sourceVfcmt = baseBusinessLogic.getSdcRestClient().getResource(theSourceId, requestId);
			checkVfcmtType(sourceVfcmt);
			List<Artifact> artifactsToClone = CollectionUtils.isEmpty(sourceVfcmt.getArtifacts()) ?
					null :
					sourceVfcmt.getArtifacts().stream().filter(p -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(p.getArtifactName()) || p.getArtifactName().endsWith(DcaeBeConstants.Composition.fileNames.MAPPING_RULE_POSTFIX))
							.collect(Collectors.toList());
			if (CollectionUtils.isEmpty(artifactsToClone)) {
				response.setSuccessResponse("Nothing to clone");
				return new ResponseEntity<>(response, HttpStatus.NO_CONTENT);
			}

			// fetch the target
			ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(theTargetId, requestId);
			debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
			checkVfcmtType(vfcmt);
			checkUserIfResourceCheckedOut(userId, vfcmt);
			boolean isTargetNeed2Checkout = isNeedToCheckOut(vfcmt.getLifecycleState());
			if (isTargetNeed2Checkout) {
				ResourceDetailed targetVfcmt = baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKOUT.name(), "checking out VFCMT before clone", requestId);
				if (null == targetVfcmt) {
					return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERAL_ERROR);
				}
				theTargetId = targetVfcmt.getUuid();
				debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New targetVfcmt (for artifact clone) after checkoutVfcmt is: {}", theTargetId);
			}

			Map<String, Artifact> currentArtifacts = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? new HashMap<>() : vfcmt.getArtifacts().stream().collect(Collectors.toMap(Artifact::getArtifactName, Function.identity()));

			//TODO target VFCMT rule artifacts should be removed
			for (Artifact artifactToClone : artifactsToClone) {
				String payload = baseBusinessLogic.getSdcRestClient().getResourceArtifact(theSourceId, artifactToClone.getArtifactUUID(), requestId);
				baseBusinessLogic.cloneArtifactToTarget(userId, theTargetId, payload, artifactToClone, currentArtifacts.get(artifactToClone.getArtifactName()), requestId);
			}

			baseBusinessLogic.getSdcRestClient().changeResourceLifecycleState(userId, theTargetId, LifecycleOperationType.CHECKIN.name(), "check in VFCMT after clone", requestId);
			debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Cloning {} from {} has finished successfully", theSourceId, theTargetId);
			response.setSuccessResponse("Clone VFCMT complete");
			return new ResponseEntity<>(response, HttpStatus.OK);
		} catch (Exception e) {
			return handleException(e, ApiType.CLONE_VFCMT);
		}
	}

	@RequestMapping(value = "/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest) {

		final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest;

		Catalog catalog = catalogController.getCatalog(request.getCatalog());
		DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());

		catalog.rootsByLabel(request.getStartingLabel()).setHandler(catalogController.new CatalogHandler<Folders>(request, result) {
			public CatalogResponse handleData(Folders theFolders) {
				JSONArray ja = new JSONArray();
				if (theFolders != null) {
					for (Folder folder : theFolders) {
						ja.put(catalogController.patchData(catalog, folder.data()));
					}
				}
				CatalogResponse response = new CatalogResponse(this.request);
				try {
					response.data().put("elements", ja);
				} catch (JSONException e) {
					errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting json elements to response {}", e);
				}
				return response;
			}
		});
		return result;
	}

	@RequestMapping(value = "/{theItemId}/elements", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") public DeferredResult<CatalogResponse> items(@RequestBody(required = false) ItemsRequest theRequest,
			@PathVariable String theItemId) {

		final ItemsRequest request = (theRequest == null) ? ItemsRequest.EMPTY_REQUEST : theRequest;

		Catalog catalog = catalogController.getCatalog(request.getCatalog());
		DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());

		catalog
				// .fetchFolderByItemId(theItemId)
				.folder(theItemId).withParts().withPartAnnotations().withItems().withItemAnnotations().withItemModels().execute().setHandler(catalogController.new CatalogHandler<Folder>(request, result) {
			public CatalogResponse handleData(Folder theFolder) {
				CatalogResponse response = new CatalogResponse(this.request);
				if (theFolder == null) {
					return response;
				}

				try {
					Elements folders = theFolder.elements("parts", Folders.class);
					if (folders != null) {
						for (Object folder : folders) {
							catalogController.patchData(catalog, ((Element) folder).data());
							// lots of ephemere proxies created here ..
							Elements annotations = ((Element) folder).elements("annotations", Annotations.class);
							if (annotations != null) {
								for (Object a : annotations) {
									catalogController.patchData(catalog, ((Annotation) a).data());
								}
							}
						}
					}
					Elements items = theFolder.elements("items", Items.class);
					if (items != null) {
						for (Object i : items) {
							catalogController.patchData(catalog, ((Element) i).data());
							// lots of ephemere proxies created here ..
							Elements annotations = ((Element) i).elements("annotations", Annotations.class);
							if (annotations != null) {
								for (Object a : annotations) {
									catalogController.patchData(catalog, ((Annotation) a).data());
								}
							}
						}
					}
				} catch (Exception x) {
					errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", x);
					return new CatalogError(this.request, "", x);
				}

				try {
					response.data().put("element", theFolder.data());
				} catch (JSONException e) {
					errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting element to response {}", e);
				}
				return response;
			}
		});

		return result;
	}

	@RequestMapping(value = "/{theItemId}/model", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") public DeferredResult model(@RequestBody(required = false) ElementRequest theRequest,
			@PathVariable String theItemId) {
		final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest;

		Catalog catalog = catalogController.getCatalog(request.getCatalog());
		DeferredResult<CatalogResponse> result = new DeferredResult<>(request.getTimeout());

		catalog.item(theItemId).withModels().execute().setHandler(catalogController.new CatalogHandler<Item>(request, result) {
			public CatalogResponse handleData(Item theItem) {
				if (theItem == null) {
					return new CatalogError(this.request, "No such item");
				}
				Templates models = null;
				try {
					models = (Templates) theItem.elements("models", Templates.class);
					if (models == null || models.isEmpty()) {
						return new CatalogError(this.request, "Item has no models");
					}
					if (models.size() > 1) {
						return new CatalogError(this.request, "Item has more than one model !?");
					}
					catalog.template(models.get(0).id()).withInputs().withOutputs().withNodes().withNodeProperties().withNodePropertiesAssignments().withNodeRequirements().withNodeCapabilities().withNodeCapabilityProperties()
							.withNodeCapabilityPropertyAssignments().withPolicies().withPolicyProperties().withPolicyPropertiesAssignments().execute().setHandler(catalogController.new CatalogHandler<Template>(this.request, this.result) {
						public CatalogResponse handleData(Template theTemplate) {
							CatalogResponse response = new CatalogResponse(this.request);
							if (theTemplate != null) {
								try {
									response.data().put("model", catalogController.patchData(catalog, theTemplate.data()));
								} catch (JSONException e) {
									errLogger.log(LogLevel.ERROR, this.getClass().getName(), "JSONException putting model to response {}", e);
								}
							}
							return response;
						}
					});
				} catch (Exception e) {
					handleException(e, ApiType.GET_MODEL, models.get(0).name());
				}
				return null;
			}
		});

		return result;
	}

	@RequestMapping(value = "/{theItemId}/type/{theTypeName}", method = { RequestMethod.POST, RequestMethod.GET }, produces = "application/json") public DeferredResult<CatalogResponse> model(@RequestBody(required = false) ElementRequest theRequest,
			@PathVariable String theItemId, @PathVariable String theTypeName) {
		final ElementRequest request = (theRequest == null) ? ElementRequest.EMPTY_REQUEST : theRequest;

		Catalog catalog = catalogController.getCatalog(request.getCatalog());
		DeferredResult<CatalogResponse> result = new DeferredResult<CatalogResponse>(request.getTimeout());

		catalog.type(theItemId, theTypeName).withHierarchy().withCapabilities().withRequirements().execute().setHandler(catalogController.new CatalogHandler<Type>(request, result) {
			public CatalogResponse handleData(Type theType) {
				CatalogResponse response = new CatalogResponse(this.request);
				if (theType != null) {
					try {
						response.data().put("type", catalogController.patchData(catalog, theType.data()));
					} catch (JSONException e) {
						errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Exception processing catalog {}", e);
					}
				}
				return response;
			}
		});

		return result;
	}

	@RequestMapping(value = { "/getComposition/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = { "application/json" }) public ResponseEntity getComposition(@PathVariable("vfcmtUuid") String vfcmtUuid,
			@ModelAttribute("requestId") String requestId) {
		MessageResponse response = new MessageResponse();
		try {
			ResourceDetailed vfcmt = baseBusinessLogic.getSdcRestClient().getResource(vfcmtUuid, requestId);
			debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), vfcmt.toString());
			checkVfcmtType(vfcmt);

			Artifact compositionArtifact = CollectionUtils.isEmpty(vfcmt.getArtifacts()) ? null : vfcmt.getArtifacts().stream().filter(a -> DcaeBeConstants.Composition.fileNames.COMPOSITION_YML.equals(a.getArtifactName())).findAny().orElse(null);

			if (null == compositionArtifact) {
				debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Couldn't find {} in VFCMT artifacts", DcaeBeConstants.Composition.fileNames.COMPOSITION_YML);
				response.setErrorResponse("No Artifacts");
				return new ResponseEntity<>(response, HttpStatus.NO_CONTENT);
			}

			String artifact = baseBusinessLogic.getSdcRestClient().getResourceArtifact(vfcmtUuid, compositionArtifact.getArtifactUUID(), requestId);

			debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "ARTIFACT: {}", artifact);
			response.setSuccessResponse(artifact);
			return new ResponseEntity<>(response, HttpStatus.OK);
		} catch (Exception e) {
			return handleException(e, ApiType.GET_CDUMP);
		}
	}


	@RequestMapping(value = { "/getMC/{vfcmtUuid}" }, method = { RequestMethod.GET }, produces = {"application/json" })
	public ResponseEntity getMC(@PathVariable String vfcmtUuid, @ModelAttribute String requestId) {
		try {
			return new ResponseEntity<>(compositionBusinessLogic.getDataAndComposition(vfcmtUuid, requestId), HttpStatus.OK);
		} catch (Exception e) {
			return handleException(e, ApiType.GET_VFCMT);
		}
	}

	@RequestMapping(value = "/saveComposition/{vfcmtUuid}", method = RequestMethod.POST)
	public ResponseEntity saveComposition(@RequestHeader("USER_ID") String userId, @RequestBody String theCdump, @PathVariable("vfcmtUuid") String vfcmtUuid, @ModelAttribute("requestId") String requestId) {

		debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "ARTIFACT CDUMP: {}", theCdump);
		return compositionBusinessLogic.saveComposition(userId, vfcmtUuid, theCdump, requestId, true);
	}

	@RequestMapping(value = "/{contextType}/{serviceUuid}/{vfiName}/saveComposition/{vfcmtUuid}", method = RequestMethod.POST)
	public ResponseEntity updateComposition(@RequestHeader("USER_ID") String userId, @RequestBody String theCdump,
			@PathVariable String contextType, @PathVariable String serviceUuid, @PathVariable String vfiName, @PathVariable String vfcmtUuid, @ModelAttribute String requestId) {

		ResponseEntity res = compositionBusinessLogic.saveComposition(userId, vfcmtUuid, theCdump, requestId, false);
		if (HttpStatus.OK == res.getStatusCode()) {
			ResourceDetailed vfcmt = (ResourceDetailed) res.getBody();
			if (!vfcmtUuid.equals(vfcmt.getUuid())) {
				try {
					debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "New vfcmt major version created with id {} , adding new reference.", vfcmt.getUuid());
					baseBusinessLogic.getSdcRestClient().addExternalMonitoringReference(userId, contextType, serviceUuid, vfiName, new ReferenceUUID(vfcmt.getUuid()), requestId);
				} catch (Exception e) {
					return handleException(e, ApiType.SAVE_CDUMP);
				}
			}
		}
		return res;
	}
}