Skip to content

Commit 939a21c

Browse files
still handling getter tosca functions...
1 parent c5cae06 commit 939a21c

10 files changed

Lines changed: 232 additions & 265 deletions

File tree

plugins/iac/nimble/src/main/java/org/apache/cloudstack/tosca/model/ToscaNodeTemplate.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// under the License.
1717
package org.apache.cloudstack.tosca.model;
1818

19+
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
20+
1921
import java.util.HashMap;
2022
import java.util.Map;
2123
import java.util.Set;
@@ -24,8 +26,8 @@ public class ToscaNodeTemplate {
2426
private final String name;
2527
private final ToscaNodeType type;
2628
private final Map<String, ToscaProperty> properties;
27-
private Set<ToscaProperty> unresolvedPropertiesByGetProperty;
28-
private Set<ToscaProperty> unresolvedPropertiesByGetAttribute;
29+
private Set<ToscaGetterFunctionCallContext> getPropertyFunctionCalls;
30+
private Set<ToscaGetterFunctionCallContext> getAttributeFunctionCalls;
2931
private final Map<String, Object> attributes = new HashMap<>();
3032

3133
public ToscaNodeTemplate(String name, ToscaNodeType type, Map<String, ToscaProperty> properties) {
@@ -54,20 +56,20 @@ public Map<String, ToscaProperty> getProperties() {
5456
return properties;
5557
}
5658

57-
public void setUnresolvedPropertiesByGetProperty(Set<ToscaProperty> unresolvedPropertiesByGetProperty) {
58-
this.unresolvedPropertiesByGetProperty = unresolvedPropertiesByGetProperty;
59+
public void setGetPropertyFunctionCalls(Set<ToscaGetterFunctionCallContext> getPropertyFunctionCalls) {
60+
this.getPropertyFunctionCalls = getPropertyFunctionCalls;
5961
}
6062

61-
public Set<ToscaProperty> getUnresolvedPropertiesByGetProperty() {
62-
return unresolvedPropertiesByGetProperty;
63+
public Set<ToscaGetterFunctionCallContext> getGetPropertyFunctionCalls() {
64+
return getPropertyFunctionCalls;
6365
}
6466

65-
public void setUnresolvedPropertiesByGetAttribute(Set<ToscaProperty> unresolvedPropertiesByGetAttribute) {
66-
this.unresolvedPropertiesByGetAttribute = unresolvedPropertiesByGetAttribute;
67+
public void setGetAttributeFunctionCalls(Set<ToscaGetterFunctionCallContext> getAttributeFunctionCalls) {
68+
this.getAttributeFunctionCalls = getAttributeFunctionCalls;
6769
}
6870

69-
public Set<ToscaProperty> getUnresolvedPropertiesByGetAttribute() {
70-
return unresolvedPropertiesByGetAttribute;
71+
public Set<ToscaGetterFunctionCallContext> getGetAttributeFunctionCalls() {
72+
return getAttributeFunctionCalls;
7173
}
7274

7375
public Map<String, String> getApiParams() {

plugins/iac/nimble/src/main/java/org/apache/cloudstack/tosca/model/ToscaServiceTemplate.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// under the License.
1717
package org.apache.cloudstack.tosca.model;
1818

19+
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
20+
1921
import java.util.Collections;
2022
import java.util.Map;
2123
import java.util.Set;
@@ -24,13 +26,13 @@ public class ToscaServiceTemplate {
2426
private final Map<String, ToscaNodeTemplate> nodeTemplates;
2527
private final Map<String, ToscaInputDefinition> inputs;
2628
private final Map<String, Set<ToscaNodeTemplate>> dependencyGraph;
27-
private final Map<String, Set<ToscaProperty>> unresolvedPropertiesByGetInput;
29+
private final Map<String, Set<ToscaGetterFunctionCallContext>> getInputFunctionCalls;
2830

29-
public ToscaServiceTemplate(Map<String, ToscaNodeTemplate> nodeTemplates, Map<String, Set<ToscaNodeTemplate>> dependencyGraph, Map<String, ToscaInputDefinition> inputs, Map<String, Set<ToscaProperty>> unresolvedPropertiesByGetInput) {
31+
public ToscaServiceTemplate(Map<String, ToscaNodeTemplate> nodeTemplates, Map<String, Set<ToscaNodeTemplate>> dependencyGraph, Map<String, ToscaInputDefinition> inputs, Map<String, Set<ToscaGetterFunctionCallContext>> getInputFunctionCalls) {
3032
this.nodeTemplates = nodeTemplates;
3133
this.dependencyGraph = dependencyGraph;
3234
this.inputs = inputs;
33-
this.unresolvedPropertiesByGetInput = unresolvedPropertiesByGetInput;
35+
this.getInputFunctionCalls = getInputFunctionCalls;
3436
}
3537

3638
public Map<String, ToscaNodeTemplate> getNodeTemplates() {
@@ -45,7 +47,7 @@ public Map<String, Set<ToscaNodeTemplate>> getDependencyGraph() {
4547
return Collections.unmodifiableMap(dependencyGraph);
4648
}
4749

48-
public Map<String, Set<ToscaProperty>> getUnresolvedPropertiesByGetInput() {
49-
return Collections.unmodifiableMap(unresolvedPropertiesByGetInput);
50+
public Map<String, Set<ToscaGetterFunctionCallContext>> getGetInputFunctionCalls() {
51+
return Collections.unmodifiableMap(getInputFunctionCalls);
5052
}
5153
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/tosca/orchestrator/ToscaOrchestrator.java

Lines changed: 35 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@
4242
import org.apache.cloudstack.tosca.model.ToscaInputDefinition;
4343
import org.apache.cloudstack.tosca.model.ToscaNodeTemplate;
4444
import org.apache.cloudstack.tosca.model.ToscaNodeType;
45-
import org.apache.cloudstack.tosca.model.ToscaPrimitiveType;
4645
import org.apache.cloudstack.tosca.model.ToscaProperty;
4746
import org.apache.cloudstack.tosca.model.ToscaServiceTemplate;
4847
import org.apache.cloudstack.tosca.model.ToscaTypeDefinition;
4948
import org.apache.cloudstack.tosca.parser.ToscaConstants;
49+
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
5050
import org.apache.cloudstack.tosca.parser.ToscaParser;
5151
import org.apache.cloudstack.tosca.parser.ToscaYamlHelper;
5252
import org.apache.commons.collections4.CollectionUtils;
@@ -57,7 +57,6 @@
5757

5858
import javax.inject.Inject;
5959
import javax.inject.Named;
60-
import java.util.ArrayList;
6160
import java.util.Collections;
6261
import java.util.HashMap;
6362
import java.util.HashSet;
@@ -125,16 +124,18 @@ protected void resolveServiceTemplateInputs(ToscaServiceTemplate serviceTemplate
125124
return;
126125
}
127126

128-
serviceTemplate.getUnresolvedPropertiesByGetInput().forEach((nodeTemplate, unresolvedProperties) -> {
129-
unresolvedProperties.forEach(unresolvedProperty -> {
130-
resolveUnresolvedPropertyByGetInput(nodeTemplate, unresolvedProperty, serviceTemplate, inputs);
127+
serviceTemplate.getGetInputFunctionCalls().forEach((nodeTemplate, getInputFunctionCalls) -> {
128+
getInputFunctionCalls.forEach(getInputFunctionCall -> {
129+
handleGetInputFunctionCall(nodeTemplate, getInputFunctionCall, serviceTemplate, inputs);
131130
});
132131
});
133132
}
134133

135-
private void resolveUnresolvedPropertyByGetInput(String nodeTemplateName, ToscaProperty unresolvedProperty, ToscaServiceTemplate serviceTemplate, Map<String, String> inputs) {
136-
logger.debug("Resolving the unresolved property [{}] of the node template [{}] by the [{}] TOSCA function.", unresolvedProperty.getDefinition().getName(), nodeTemplateName, ToscaConstants.GET_INPUT_FUNCTION);
137-
Map<String, Object> functionCall = ToscaYamlHelper.asMap(unresolvedProperty.getRawValue());
134+
private void handleGetInputFunctionCall(String nodeTemplateName, ToscaGetterFunctionCallContext getInputFunctionCall, ToscaServiceTemplate serviceTemplate, Map<String, String> inputs) {
135+
ToscaProperty callerProperty = getInputFunctionCall.getProperty();
136+
logger.debug("Resolving the [{}] function call triggered by the [{}] property of the [{}] node template.", ToscaConstants.GET_INPUT_FUNCTION, callerProperty.getDefinition().getName(), nodeTemplateName);
137+
138+
Map<String, Object> functionCall = getInputFunctionCall.getFunctionCall();
138139
String targetInput = ToscaYamlHelper.asString(functionCall.get(ToscaConstants.GET_INPUT_FUNCTION));
139140
ToscaInputDefinition inputDefinition = serviceTemplate.getInputs().get(targetInput);
140141
Object inputValue = inputDefinition.getType().convertPrimitiveTypeFromString(inputs.get(targetInput));
@@ -151,13 +152,13 @@ private void resolveUnresolvedPropertyByGetInput(String nodeTemplateName, ToscaP
151152
inputValue = inputDefinition.getDefaultValue();
152153
}
153154

154-
ToscaFunction.ToscaBooleanFunction propertyValidationFunction = unresolvedProperty.getDefinition().getValidation();
155+
ToscaFunction.ToscaBooleanFunction propertyValidationFunction = callerProperty.getDefinition().getValidation();
155156
if (propertyValidationFunction != null && !propertyValidationFunction.evaluate(inputValue)) {
156157
throw new InvalidParameterValueException(String.format("The input [%s] of the node template [%s] is invalid. The value [%s] does not satisfy the validation rules.", targetInput, nodeTemplateName, inputValue));
157158
}
158159

159-
logger.debug("The input [{}] of the property [{}] of the node template [{}] has been resolved successfully.", targetInput, unresolvedProperty.getDefinition().getName(), nodeTemplateName);
160-
unresolvedProperty.setEvaluatedValue(inputValue);
160+
logger.debug("The input [{}] of the property [{}] of the node template [{}] has been successfully retrieved.", targetInput, callerProperty.getDefinition().getName(), nodeTemplateName);
161+
callerProperty.setEvaluatedValue(inputValue);
161162
}
162163

163164
private Map<String, CompletableFuture<String>> createProvisioningTasksFutures(ToscaServiceTemplate serviceTemplate) {
@@ -176,8 +177,7 @@ private Map<String, CompletableFuture<String>> createProvisioningTasksFutures(To
176177
.map((dep) -> futures.get(dep.getName())).toArray(CompletableFuture[]::new);
177178
taskFuture = CompletableFuture.allOf(dependenciesFutures).thenCompose(v -> {
178179
logger.debug("All dependencies of the node [{}] are ready. Building its provisioning task.", node);
179-
resolveUnresolvedPropertiesByGetPropertyAndGetAttribute(nodeTemplate, serviceTemplate, ToscaConstants.GET_PROPERTY_FUNCTION);
180-
resolveUnresolvedPropertiesByGetPropertyAndGetAttribute(nodeTemplate, serviceTemplate, ToscaConstants.GET_ATTRIBUTE_FUNCTION);
180+
executeGetAttributeAndGetPropertyFunctionCalls(nodeTemplate, serviceTemplate);
181181
return buildNodeProvisioningTask(nodeTemplate, callContext);
182182
});
183183
}
@@ -360,55 +360,41 @@ protected void populateNodeTemplateAttributes(ToscaNodeTemplate nodeTemplate, Ma
360360
}
361361

362362
/**
363-
* Resolve the unresolved/pending properties of a node template by the <code>$get_attribute</code> and <code>$get_property</code> TOSCA functions.
364-
* @param nodeTemplate The node template from which the pending dependencies will be resolved.
363+
* Executes the <code>$get_attribute</code> and <code>$get_property</code> TOSCA functions called by a node template.
364+
* @param nodeTemplate The node template from which the functions are called.
365365
* @param serviceTemplate The TOSCA service template the node template belongs to.
366-
* @param toscaFunction The TOSCA function used to resolve the pending dependencies. Current supported functions are: <code>$get_attribute</code> and <code>$get_property</code>.
367366
* @throws InvalidParameterValueException When the return value of the <code>$get_attribute</code> and <code>$get_property</code> function calls is null
368-
* or when the return value does not passes the validation function.
367+
* or when the return value does not pass the validation function.
369368
*/
370-
protected void resolveUnresolvedPropertiesByGetPropertyAndGetAttribute(ToscaNodeTemplate nodeTemplate, ToscaServiceTemplate serviceTemplate, String toscaFunction) {
371-
Set<ToscaProperty> unresolvedProperties = ToscaConstants.GET_PROPERTY_FUNCTION.equals(toscaFunction) ?
372-
nodeTemplate.getUnresolvedPropertiesByGetProperty() : nodeTemplate.getUnresolvedPropertiesByGetAttribute();
373-
if (CollectionUtils.isEmpty(unresolvedProperties)) {
374-
logger.debug("Node template [{}] has no unresolved properties to be resolved by the [{}] TOSCA function.", nodeTemplate.getName(), toscaFunction);
369+
protected void executeGetAttributeAndGetPropertyFunctionCalls(ToscaNodeTemplate nodeTemplate, ToscaServiceTemplate serviceTemplate) {
370+
Set<ToscaGetterFunctionCallContext> functionCalls = new HashSet<>(nodeTemplate.getGetPropertyFunctionCalls());
371+
functionCalls.addAll(nodeTemplate.getGetAttributeFunctionCalls());
372+
if (CollectionUtils.isEmpty(functionCalls)) {
373+
logger.debug("Node template [{}] has no function calls to the [{}] and [{}] TOSCA function.", nodeTemplate.getName(), ToscaConstants.GET_ATTRIBUTE_FUNCTION, ToscaConstants.GET_PROPERTY_FUNCTION);
375374
return;
376375
}
377376

378-
logger.info("Resolving the unresolved properties of the node template [{}] by the [{}] TOSCA function.", nodeTemplate.getName(), toscaFunction);
379-
for (ToscaProperty unresolvedProperty : unresolvedProperties) {
380-
Object valueToBeResolved = resolveValue(unresolvedProperty.getRawValue(), toscaFunction, serviceTemplate, nodeTemplate);
377+
logger.info("Handling the [{}] and [{}] TOSCA function calls performed by the [{}] node template.", ToscaConstants.GET_ATTRIBUTE_FUNCTION, ToscaConstants.GET_PROPERTY_FUNCTION, nodeTemplate.getName());
378+
for (ToscaGetterFunctionCallContext functionCall : functionCalls) {
379+
Object valueToBeResolved = resolveGetAttributeAndGetPropertyFunctionCall(functionCall.getFunctionCall(), serviceTemplate, nodeTemplate);
380+
ToscaProperty callerProperty = functionCall.getProperty();
381381

382-
if (unresolvedProperty.getDefinition().getValidation() != null && unresolvedProperty.getDefinition().getType().getKind() == ToscaTypeDefinition.Kind.PRIMITIVE) {
383-
logger.debug("The unresolved property [{}] has a validation clause. Executing it.", unresolvedProperty.getDefinition().getName());
384-
boolean validationResult = unresolvedProperty.getDefinition().getValidation().evaluate(valueToBeResolved);
382+
if (callerProperty.getDefinition().getValidation() != null && callerProperty.getDefinition().getType().getKind() == ToscaTypeDefinition.Kind.PRIMITIVE) {
383+
logger.debug("The property [{}] has a validation clause. Executing it.", callerProperty.getDefinition().getName());
384+
boolean validationResult = callerProperty.getDefinition().getValidation().evaluate(valueToBeResolved);
385385
if (!validationResult) {
386-
logger.error("The value of the property [{}] of node template [{}] is not valid. Aborting IaC template deployment.", unresolvedProperty.getDefinition().getName(), nodeTemplate.getName());
387-
throw new InvalidParameterValueException(String.format("The value of the property [%s] of node template [%s] is not valid. Please, check the value and try again.", unresolvedProperty.getDefinition().getName(), nodeTemplate.getName()));
386+
logger.error("The value of the property [{}] of node template [{}] is not valid. Aborting IaC template deployment.", callerProperty.getDefinition().getName(), nodeTemplate.getName());
387+
throw new InvalidParameterValueException(String.format("The value of the property [%s] of node template [%s] is not valid. Please, check the value and try again.", callerProperty.getDefinition().getName(), nodeTemplate.getName()));
388388
}
389389
}
390390

391-
logger.debug("The unresolved property [{}] of node template [{}] will be resolved to value [{}].", unresolvedProperty.getDefinition().getName(), nodeTemplate.getName(), valueToBeResolved);
392-
unresolvedProperty.setEvaluatedValue(valueToBeResolved);
391+
logger.debug("The unresolved property [{}] of node template [{}] will be resolved to value [{}].", callerProperty.getDefinition().getName(), nodeTemplate.getName(), valueToBeResolved);
392+
callerProperty.setEvaluatedValue(valueToBeResolved);
393393
}
394394
}
395395

396-
private Object resolveValue(Object rawValue, String toscaFunction, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
397-
if (rawValue instanceof List) {
398-
List<?> rawList = ToscaYamlHelper.asList(rawValue);
399-
return resolveList(rawList, toscaFunction, serviceTemplate, nodeTemplate);
400-
}
401-
if (rawValue instanceof Map) {
402-
Map<String, Object> rawMap = ToscaYamlHelper.asMap(rawValue);
403-
if (isToscaFunctionCall(rawMap, toscaFunction)) {
404-
return resolveGetAttributeAndGetPropertyFunctionCall(rawMap, toscaFunction, serviceTemplate, nodeTemplate);
405-
}
406-
return resolveMap(rawMap, toscaFunction, serviceTemplate, nodeTemplate);
407-
}
408-
return rawValue;
409-
}
410-
411-
private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object> functionCall, String toscaFunction, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
396+
private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object> functionCall, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
397+
String toscaFunction = functionCall.keySet().iterator().next();
412398
List<?> args = ToscaYamlHelper.asList(functionCall.get(toscaFunction));
413399
String targetNodeName = ToscaYamlHelper.asString(args.get(0));
414400
String targetField = ToscaYamlHelper.asString(args.get(1));
@@ -418,33 +404,11 @@ private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object>
418404
targetNode.getProperty(targetField).getEvaluatedValue() : targetNode.getAttribute(targetField);
419405

420406
if (functionCallResult == null) {
421-
throw new InvalidParameterValueException(String.format("The field [%s] of the target node [%s] has not been defined. Unable to deploy [%s].", targetField, targetNode.getName(), nodeTemplate.getName()));
407+
throw new InvalidParameterValueException(String.format("The field [%s] of the target node [%s] referenced by the TOSCA function [%s] has not been defined. Unable to deploy [%s].", targetField, targetNode.getName(), toscaFunction, nodeTemplate.getName()));
422408
}
423409
return functionCallResult;
424410
}
425411

426-
private List<Object> resolveList(List<?> list, String toscaFunction, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
427-
List<Object> resolved = new ArrayList<>();
428-
for (Object element : list) {
429-
Object resolvedElement = resolveValue(element, toscaFunction, serviceTemplate, nodeTemplate);
430-
resolved.add(resolvedElement);
431-
}
432-
return resolved;
433-
}
434-
435-
private Map<String, Object> resolveMap(Map<String, Object> rawMap, String toscaFunction, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
436-
Map<String, Object> resolved = new LinkedHashMap<>();
437-
for (Map.Entry<String, Object> entry : rawMap.entrySet()) {
438-
Object resolvedValue = resolveValue(entry.getValue(), toscaFunction, serviceTemplate, nodeTemplate);
439-
resolved.put(entry.getKey(), resolvedValue);
440-
}
441-
return resolved;
442-
}
443-
444-
private boolean isToscaFunctionCall(Map<String, Object> map, String toscaFunction) {
445-
return map.size() == 1 && map.containsKey(toscaFunction);
446-
}
447-
448412
public void configureExecutorPool(int poolSize) {
449413
logger.info("Configuring TOSCA's fixed executor thread pool with [{}] threads.", poolSize);
450414
executorPool = Executors.newFixedThreadPool(poolSize);

0 commit comments

Comments
 (0)