3455204b69d5580b5c29084f82e2b6a585ddfd4c
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.translator.services.heattotosca.impl.resourcetranslation;
22
23 import org.apache.commons.collections4.MapUtils;
24 import org.openecomp.sdc.common.errors.CoreException;
25 import org.openecomp.sdc.common.errors.ErrorCategory;
26 import org.openecomp.sdc.common.errors.ErrorCode;
27 import org.openecomp.sdc.datatypes.error.ErrorLevel;
28 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
29 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
30 import org.openecomp.sdc.heat.datatypes.model.Resource;
31 import org.openecomp.sdc.logging.api.Logger;
32 import org.openecomp.sdc.logging.api.LoggerFactory;
33 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
34 import org.openecomp.sdc.logging.types.LoggerConstants;
35 import org.openecomp.sdc.logging.types.LoggerErrorCode;
36 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
37 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
38 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
39 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
40 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
41 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
42 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
43 import org.openecomp.sdc.tosca.services.DataModelUtil;
44 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
45 import org.openecomp.sdc.tosca.services.YamlUtil;
46 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
47 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
48 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
49 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource;
50 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
51 import org.openecomp.sdc.translator.services.heattotosca.errors.TranslatorErrorCodes;
52
53 import java.util.ArrayList;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Objects;
57 import java.util.Optional;
58 import java.util.function.Predicate;
59
60 abstract class BaseResourceConnection<T> {
61   protected static Logger logger = (Logger) LoggerFactory.getLogger(BaseResourceConnection.class);
62   protected TranslateTo translateTo;
63   FileData nestedFileData;
64   NodeTemplate substitutionNodeTemplate;
65   NodeType nodeType;
66   ResourceTranslationBase resourceTranslationBase;
67
68   BaseResourceConnection(ResourceTranslationBase resourceTranslationBase, TranslateTo translateTo,
69                          FileData nestedFileData, NodeTemplate substitutionNodeTemplate,
70                          NodeType nodeType) {
71     this.translateTo = translateTo;
72     this.nestedFileData = nestedFileData;
73     this.substitutionNodeTemplate = substitutionNodeTemplate;
74     this.nodeType = nodeType;
75     this.resourceTranslationBase = resourceTranslationBase;
76   }
77
78   abstract boolean isDesiredNodeTemplateType(NodeTemplate nodeTemplate);
79
80   abstract List<Predicate<T>> getPredicatesListForConnectionPoints();
81
82   abstract Optional<List<String>> getConnectorPropertyParamName(String heatResourceId,
83                                                                 Resource heatResource,
84                                                                 HeatOrchestrationTemplate
85                                                                     nestedHeatOrchestrationTemplate,
86                                                                 String nestedHeatFileName);
87
88   abstract String getDesiredResourceType();
89
90   abstract String getMappedNodeTranslatedResourceId(ServiceTemplate nestedServiceTemplate,
91                                                     Map.Entry<String, T> connectionPointEntry);
92
93   abstract Map.Entry<String, T> getMappedConnectionPointEntry(ServiceTemplate nestedServiceTemplate,
94                                                               Map.Entry<String, T>
95                                                                   connectionPointEntry);
96
97   abstract void addRequirementToConnectResources(Map.Entry<String, T> connectionPointEntry,
98                                                  List<String> paramNames);
99
100   abstract List<Map<String, T>> getAllConnectionPoints();
101
102   abstract boolean validateResourceTypeSupportedForReqCreation(String nestedResourceId,
103                                                                final String nestedPropertyName,
104                                                                String connectionPointId,
105                                                                Resource connectedResource,
106                                                                List<String> supportedTypes);
107
108   void connect() {
109     ServiceTemplate nestedServiceTemplate = translateTo.getContext().getTranslatedServiceTemplates()
110         .get(translateTo.getResource().getType());
111     List<String> paramNames;
112     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate = new YamlUtil()
113         .yamlToObject(translateTo.getContext().getFileContent(nestedFileData.getFile()),
114             HeatOrchestrationTemplate.class);
115     List<Map<String, T>> exposedConnectionPoints = getAllConnectionPoints();
116     for (Map<String, T> connectionPointsMap : exposedConnectionPoints) {
117       for (Map.Entry<String, T> connectionPointEntry : connectionPointsMap.entrySet()) {
118         paramNames =
119             getConnectionParameterName(nestedServiceTemplate, nestedHeatOrchestrationTemplate,
120                 nestedFileData.getFile(), connectionPointEntry);
121         if (paramNames != null && !paramNames.isEmpty()) {
122           addRequirementToConnectResources(connectionPointEntry, paramNames);
123         }
124       }
125     }
126   }
127
128   private List<String> getConnectionParameterName(ServiceTemplate nestedServiceTemplate,
129                                                   HeatOrchestrationTemplate
130                                                       nestedHeatOrchestrationTemplate,
131                                                   String nestedHeatFileName,
132                                                   Map.Entry<String, T> connectionPointEntry) {
133     List<String> connectionParameterNameList = new ArrayList<>();
134     String mappedTranslatedResourceId =
135         getMappedNodeTranslatedResourceId(nestedServiceTemplate, connectionPointEntry);
136     NodeTemplate mappedNodeTemplate =
137         nestedServiceTemplate.getTopology_template().getNode_templates()
138             .get(mappedTranslatedResourceId);
139     if (isDesiredNodeTemplateType(mappedNodeTemplate)) {
140       return getResourcesConnectionParameterName(mappedTranslatedResourceId,
141           nestedHeatOrchestrationTemplate, nestedHeatFileName);
142     }
143
144     ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
145     if (toscaAnalyzerService.isSubstitutableNodeTemplate(mappedNodeTemplate)) {
146       Optional<String> mappedSubstituteServiceTemplateName = toscaAnalyzerService
147           .getSubstituteServiceTemplateName(mappedTranslatedResourceId, mappedNodeTemplate);
148       if (mappedSubstituteServiceTemplateName.isPresent()) {
149         String mappedNestedHeatFileName = translateTo.getContext().getNestedHeatFileName()
150             .get(mappedSubstituteServiceTemplateName.get());
151         if (Objects.isNull(mappedNestedHeatFileName)) {
152           return null;
153         }
154         HeatOrchestrationTemplate mappedNestedHeatOrchestrationTemplate = new YamlUtil()
155             .yamlToObject(translateTo.getContext().getFileContent(mappedNestedHeatFileName),
156                 HeatOrchestrationTemplate.class);
157         ServiceTemplate mappedNestedServiceTemplate =
158             translateTo.getContext().getTranslatedServiceTemplates().get(mappedNestedHeatFileName);
159         List<String> nestedPropertyNames = getConnectionParameterName(mappedNestedServiceTemplate,
160             mappedNestedHeatOrchestrationTemplate, mappedNestedHeatFileName,
161             getMappedConnectionPointEntry(nestedServiceTemplate, connectionPointEntry));
162
163         if (nestedPropertyNames != null && !nestedPropertyNames.isEmpty()) {
164           for (String propertyName : nestedPropertyNames) {
165             Object propertyValue = mappedNodeTemplate.getProperties().get(propertyName);
166             if (propertyValue instanceof Map && ((Map) propertyValue).containsKey("get_input")) {
167               Object paramName = ((Map) propertyValue).get("get_input");
168               if (paramName instanceof String) {
169                 connectionParameterNameList.add((String) paramName);
170               }
171             }
172           }
173         }
174         return connectionParameterNameList;
175       }
176     }
177     return null;
178   }
179
180   private List<String> getResourcesConnectionParameterName(String translatedResourceId,
181                                                            HeatOrchestrationTemplate
182                                                                nestedHeatOrchestrationTemplate,
183                                                            String nestedHeatFileName) {
184     List<String> params = new ArrayList<>();
185     Optional<List<Map.Entry<String, Resource>>> heatResources =
186         getResourceByTranslatedResourceId(translatedResourceId, nestedHeatOrchestrationTemplate);
187     if (heatResources.isPresent()) {
188       for (Map.Entry<String, Resource> resourceEntry : heatResources.get()) {
189         Resource heatResource = resourceEntry.getValue();
190         if (!MapUtils.isEmpty(heatResource.getProperties())) {
191           Optional<List<String>> connectorParamName =
192               getConnectorPropertyParamName(resourceEntry.getKey(), heatResource,
193                   nestedHeatOrchestrationTemplate, nestedHeatFileName);
194           connectorParamName.ifPresent(params::addAll);
195         }
196       }
197     }
198     return params;
199   }
200
201   protected Optional<List<Map.Entry<String, Resource>>> getResourceByTranslatedResourceId(
202       String translatedResourceId, HeatOrchestrationTemplate nestedHeatOrchestrationTemplate) {
203     Optional<List<Map.Entry<String, Resource>>> resourceByTranslatedResourceId =
204         resourceTranslationBase.getResourceByTranslatedResourceId(nestedFileData.getFile(),
205             nestedHeatOrchestrationTemplate, translatedResourceId, translateTo,
206             getDesiredResourceType());
207     if (!resourceByTranslatedResourceId.isPresent()) {
208       MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
209           LoggerTragetServiceName.GET_RESOURCE, ErrorLevel.ERROR.name(),
210           LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.TRANSLATE_HEAT);
211       throw new CoreException((new ErrorCode.ErrorCodeBuilder()).withMessage(
212           "Failed to get original resource from heat for translate resource id '"
213               + translatedResourceId + "'")
214           .withId(TranslatorErrorCodes.HEAT_TO_TOSCA_MAPPING_COLLISION)
215           .withCategory(ErrorCategory.APPLICATION).build());
216     }
217     return resourceByTranslatedResourceId;
218   }
219
220   RequirementAssignment createRequirementAssignment(Map.Entry<String, RequirementDefinition>
221                                                         requirementEntry, String node,
222                                                     NodeTemplate nodeTemplate) {
223     RequirementAssignment requirementAssignment = null;
224     if (Objects.nonNull(node)) {
225       requirementAssignment = new RequirementAssignment();
226       requirementAssignment.setRelationship(requirementEntry.getValue().getRelationship());
227       requirementAssignment.setCapability(requirementEntry.getValue().getCapability());
228       requirementAssignment.setNode(node);
229       DataModelUtil
230           .addRequirementAssignment(nodeTemplate, requirementEntry.getKey(), requirementAssignment);
231     }
232     return requirementAssignment;
233   }
234
235
236   Optional<String> getConnectionTranslatedNodeUsingGetParamFunc(
237       Map.Entry<String, T> connectionPointEntry, String paramName,
238       List<String> supportedNodeTypes) {
239
240     Optional<AttachedResourceId> attachedResourceId =
241         HeatToToscaUtil.extractAttachedResourceId(translateTo, paramName);
242     if (!attachedResourceId.isPresent()) {
243       return Optional.empty();
244     }
245     AttachedResourceId resourceId = attachedResourceId.get();
246     if (resourceId.isGetParam() && resourceId.getEntityId() instanceof String) {
247       TranslatedHeatResource shareResource =
248           translateTo.getContext().getHeatSharedResourcesByParam().get(resourceId.getEntityId());
249       if (Objects.nonNull(shareResource)
250           && !HeatToToscaUtil.isHeatFileNested(translateTo, translateTo.getHeatFileName())) {
251         if (validateResourceTypeSupportedForReqCreation(translateTo.getResourceId(), paramName,
252             connectionPointEntry.getKey(), shareResource.getHeatResource(), supportedNodeTypes)) {
253           return Optional.of(shareResource.getTranslatedId());
254         }
255       }
256     }
257     return Optional.empty();
258   }
259
260   Optional<TranslatedHeatResource> getConnectionTranslatedHeatResourceUsingGetParamFunc(
261       Map.Entry<String, T> connectionPointEntry, String paramName,
262       List<String> supportedNodeTypes) {
263
264     Optional<AttachedResourceId> attachedResourceId =
265         HeatToToscaUtil.extractAttachedResourceId(translateTo, paramName);
266     if (!attachedResourceId.isPresent()) {
267       return Optional.empty();
268     }
269     AttachedResourceId resourceId = attachedResourceId.get();
270     if (resourceId.isGetParam() && resourceId.getEntityId() instanceof String) {
271       TranslatedHeatResource shareResource =
272           translateTo.getContext().getHeatSharedResourcesByParam().get(resourceId.getEntityId());
273       if (Objects.nonNull(shareResource)
274           && !HeatToToscaUtil.isHeatFileNested(translateTo, translateTo.getHeatFileName())) {
275         if (validateResourceTypeSupportedForReqCreation(translateTo.getResourceId(), paramName,
276             connectionPointEntry.getKey(), shareResource.getHeatResource(), supportedNodeTypes)) {
277           return Optional.of(shareResource);
278         }
279       }
280     }
281     return Optional.empty();
282   }
283
284
285   Optional<String> getConnectionTranslatedNodeUsingGetResourceFunc(
286       Map.Entry<String, T> connectionPointEntry, String paramName, Object paramValue,
287       List<String> supportedNodeTypes) {
288     Optional<String> getResourceAttachedResourceId =
289         HeatToToscaUtil.extractContrailGetResourceAttachedHeatResourceId(paramValue);
290     if (getResourceAttachedResourceId.isPresent()) { // get resource
291       Resource resource = translateTo.getHeatOrchestrationTemplate().getResources()
292           .get(getResourceAttachedResourceId.get());
293       if (validateResourceTypeSupportedForReqCreation(translateTo.getResourceId(), paramName,
294           connectionPointEntry.getKey(), resource, supportedNodeTypes)) {
295         return ResourceTranslationBase.getResourceTranslatedId(translateTo.getHeatFileName(),
296             translateTo.getHeatOrchestrationTemplate(), getResourceAttachedResourceId.get(),
297             translateTo.getContext());
298       }
299     }
300
301     return Optional.empty();
302   }
303
304   Optional<String> getConnectionResourceUsingGetResourceFunc(
305       Map.Entry<String, T> connectionPointEntry, String paramName, Object paramValue,
306       List<String> supportedNodeTypes) {
307     Optional<String> getResourceAttachedResourceId =
308         HeatToToscaUtil.extractContrailGetResourceAttachedHeatResourceId(paramValue);
309     if (getResourceAttachedResourceId.isPresent()) { // get resource
310       Resource resource = translateTo.getHeatOrchestrationTemplate().getResources()
311           .get(getResourceAttachedResourceId.get());
312       if (validateResourceTypeSupportedForReqCreation(translateTo.getResourceId(), paramName,
313           connectionPointEntry.getKey(), resource, supportedNodeTypes)) {
314         return getResourceAttachedResourceId;
315       }
316     }
317     return Optional.empty();
318   }
319 }