Skip to content

Commit 217693c

Browse files
resolving get_inputs -> unit & manual tests remaining
1 parent 41665e5 commit 217693c

7 files changed

Lines changed: 97 additions & 90 deletions

File tree

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

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

19-
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
20-
2119
import java.util.HashMap;
2220
import java.util.HashSet;
2321
import java.util.Map;

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

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

19-
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
20-
2119
import java.util.Collections;
2220
import java.util.Map;
2321
import java.util.Set;
@@ -26,13 +24,13 @@ public class ToscaServiceTemplate {
2624
private final Map<String, ToscaNodeTemplate> nodeTemplates;
2725
private final Map<String, ToscaInputDefinition> inputs;
2826
private final Map<String, Set<ToscaNodeTemplate>> dependencyGraph;
29-
private final Map<String, Set<ToscaGetterFunctionCallContext>> getInputFunctionCalls;
27+
private final Map<String, Set<ToscaProperty>> unresolvedPropertiesByGetInput;
3028

31-
public ToscaServiceTemplate(Map<String, ToscaNodeTemplate> nodeTemplates, Map<String, Set<ToscaNodeTemplate>> dependencyGraph, Map<String, ToscaInputDefinition> inputs, Map<String, Set<ToscaGetterFunctionCallContext>> getInputFunctionCalls) {
29+
public ToscaServiceTemplate(Map<String, ToscaNodeTemplate> nodeTemplates, Map<String, Set<ToscaNodeTemplate>> dependencyGraph, Map<String, ToscaInputDefinition> inputs, Map<String, Set<ToscaProperty>> unresolvedPropertiesByGetInput) {
3230
this.nodeTemplates = nodeTemplates;
3331
this.dependencyGraph = dependencyGraph;
3432
this.inputs = inputs;
35-
this.getInputFunctionCalls = getInputFunctionCalls;
33+
this.unresolvedPropertiesByGetInput = unresolvedPropertiesByGetInput;
3634
}
3735

3836
public Map<String, ToscaNodeTemplate> getNodeTemplates() {
@@ -47,7 +45,7 @@ public Map<String, Set<ToscaNodeTemplate>> getDependencyGraph() {
4745
return Collections.unmodifiableMap(dependencyGraph);
4846
}
4947

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

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

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import org.apache.cloudstack.tosca.model.ToscaServiceTemplate;
4747
import org.apache.cloudstack.tosca.model.ToscaTypeDefinition;
4848
import org.apache.cloudstack.tosca.parser.ToscaConstants;
49-
import org.apache.cloudstack.tosca.parser.ToscaGetterFunctionCallContext;
5049
import org.apache.cloudstack.tosca.parser.ToscaParser;
5150
import org.apache.cloudstack.tosca.parser.ToscaYamlHelper;
5251
import org.apache.commons.collections4.CollectionUtils;
@@ -125,41 +124,25 @@ protected void resolveServiceTemplateInputs(ToscaServiceTemplate serviceTemplate
125124
return;
126125
}
127126

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

135-
private void handleGetInputFunctionCall(String nodeTemplateName, ToscaGetterFunctionCallContext getInputFunctionCall, ToscaServiceTemplate serviceTemplate, Map<String, String> inputs) {
136-
ToscaProperty callerProperty = getInputFunctionCall.getProperty();
137-
logger.debug("Resolving the [{}] function call triggered by the [{}] property of the [{}] node template.", ToscaConstants.GET_INPUT_FUNCTION, callerProperty.getDefinition().getName(), nodeTemplateName);
134+
private void handleGetInputFunctionCall(String nodeTemplateName, ToscaProperty property, ToscaServiceTemplate serviceTemplate, Map<String, String> inputs) {
135+
String propertyName = property.getDefinition().getName();
136+
logger.debug("Resolving the [{}] function call triggered by the [{}] property of the [{}] node template.", ToscaConstants.GET_INPUT_FUNCTION, propertyName, nodeTemplateName);
138137

139-
Map<String, Object> functionCall = getInputFunctionCall.getFunctionCall();
140-
String targetInput = ToscaYamlHelper.asString(functionCall.get(ToscaConstants.GET_INPUT_FUNCTION));
141-
ToscaInputDefinition inputDefinition = serviceTemplate.getInputs().get(targetInput);
142-
Object inputValue = inputDefinition.getType().convertPrimitiveTypeFromString(inputs.get(targetInput));
143-
ToscaFunction.ToscaBooleanFunction inputValidationFunction = inputDefinition.getValidation();
144-
if (inputValue != null && inputValidationFunction != null && !inputValidationFunction.evaluate(inputValue)) {
145-
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));
146-
}
147-
148-
if (inputValue == null) {
149-
logger.debug("The input [{}] was not provided. Checking if it has a default value.", targetInput);
150-
if (inputDefinition.getDefaultValue() == null) {
151-
throw new InvalidParameterValueException(String.format("The input [%s] is required by the node template [%s] but it was not provided and it does not have a default value.", targetInput, nodeTemplateName));
152-
}
153-
inputValue = inputDefinition.getDefaultValue();
154-
}
155-
156-
ToscaFunction.ToscaBooleanFunction propertyValidationFunction = callerProperty.getDefinition().getValidation();
157-
if (propertyValidationFunction != null && !propertyValidationFunction.evaluate(inputValue)) {
158-
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));
138+
Object evaluatedValue = getPropertyEvaluatedValue(property.getRawValue(), serviceTemplate, nodeTemplateName, inputs);
139+
ToscaFunction.ToscaBooleanFunction propertyValidationFunction = property.getDefinition().getValidation();
140+
if (propertyValidationFunction != null && property.getDefinition().getType().getKind() == ToscaTypeDefinition.Kind.PRIMITIVE && !propertyValidationFunction.evaluate(evaluatedValue)) {
141+
throw new InvalidParameterValueException(String.format("The value [%s] does not satisfy the validation rules of the property [%s] of the node template [%s].", evaluatedValue, propertyName, nodeTemplateName));
159142
}
160143

161-
logger.debug("The input [{}] of the property [{}] of the node template [{}] has been successfully retrieved.", targetInput, callerProperty.getDefinition().getName(), nodeTemplateName);
162-
callerProperty.setEvaluatedValue(inputValue);
144+
logger.debug("Resolving the evaluated value of the property [{}] of the node template [{}] to be equal to: [{}].", propertyName, nodeTemplateName, evaluatedValue);
145+
property.setEvaluatedValue(evaluatedValue);
163146
}
164147

165148
private Map<String, CompletableFuture<String>> createProvisioningTasksFutures(ToscaServiceTemplate serviceTemplate) {
@@ -377,7 +360,7 @@ protected void executeGetAttributeAndGetPropertyFunctionCalls(ToscaNodeTemplate
377360

378361
logger.info("Handling the [{}] and [{}] TOSCA function calls performed by the [{}] node template.", ToscaConstants.GET_ATTRIBUTE_FUNCTION, ToscaConstants.GET_PROPERTY_FUNCTION, nodeTemplate.getName());
379362
for (ToscaProperty property : unresolvedProperties) {
380-
Object evaluatedValue = getPropertyEvaluatedValue(property.getRawValue(), serviceTemplate, nodeTemplate);
363+
Object evaluatedValue = getPropertyEvaluatedValue(property.getRawValue(), serviceTemplate, nodeTemplate.getName(), null);
381364

382365
if (property.getDefinition().getValidation() != null && property.getDefinition().getType().getKind() == ToscaTypeDefinition.Kind.PRIMITIVE) {
383366
logger.debug("The property [{}] has a validation clause. Executing it.", property.getDefinition().getName());
@@ -393,32 +376,57 @@ protected void executeGetAttributeAndGetPropertyFunctionCalls(ToscaNodeTemplate
393376
}
394377
}
395378

396-
private Object getPropertyEvaluatedValue(Object rawValue, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
379+
private Object getPropertyEvaluatedValue(Object rawValue, ToscaServiceTemplate serviceTemplate, String nodeTemplateName, Map<String, String> rawInputs) {
397380
if (rawValue instanceof List) {
398381
List<Object> evaluatedValue = new ArrayList<>();
399382
for (Object item : (List<?>) rawValue) {
400-
evaluatedValue.add(getPropertyEvaluatedValue(item, serviceTemplate, nodeTemplate));
383+
evaluatedValue.add(getPropertyEvaluatedValue(item, serviceTemplate, nodeTemplateName, rawInputs));
401384
}
402385
return evaluatedValue;
403386
}
404387

405388
if (rawValue instanceof Map) {
406389
Map<String, Object> rawValueAsMap = ToscaYamlHelper.asMap(rawValue);
407-
boolean isToscaFunction = rawValueAsMap.size() == 1 && ToscaConstants.GETTER_FUNCTION_KEYS.contains(rawValueAsMap.keySet().iterator().next());
390+
String functionName = rawValueAsMap.keySet().iterator().next();
391+
boolean isToscaFunction = rawValueAsMap.size() == 1 && ToscaConstants.GETTER_FUNCTION_KEYS.contains(functionName);
408392
if (isToscaFunction) {
409-
return resolveGetAttributeAndGetPropertyFunctionCall(rawValueAsMap, serviceTemplate, nodeTemplate);
393+
if (ToscaConstants.GET_INPUT_FUNCTION.equals(functionName)) {
394+
return resolveGetInputFunctionCall(rawValueAsMap, nodeTemplateName, serviceTemplate, rawInputs);
395+
}
396+
return resolveGetAttributeAndGetPropertyFunctionCall(rawValueAsMap, nodeTemplateName, serviceTemplate);
410397
}
398+
411399
Map<String, Object> evaluatedValue = new LinkedHashMap<>();
412400
for (Map.Entry<String, Object> entry : rawValueAsMap.entrySet()) {
413-
evaluatedValue.put(entry.getKey(), getPropertyEvaluatedValue(entry.getValue(), serviceTemplate, nodeTemplate));
401+
evaluatedValue.put(entry.getKey(), getPropertyEvaluatedValue(entry.getValue(), serviceTemplate, nodeTemplateName, rawInputs));
414402
}
415403
return evaluatedValue;
416404
}
417405

418406
return rawValue;
419407
}
420408

421-
private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object> functionCall, ToscaServiceTemplate serviceTemplate, ToscaNodeTemplate nodeTemplate) {
409+
private Object resolveGetInputFunctionCall(Map<String, Object> functionCall, String nodeTemplateName, ToscaServiceTemplate serviceTemplate, Map<String, String> inputValues) {
410+
String inputName = ToscaYamlHelper.asString(functionCall.get(ToscaConstants.GET_INPUT_FUNCTION));
411+
ToscaInputDefinition inputDefinition = serviceTemplate.getInputs().get(inputName);
412+
Object inputValue = inputDefinition.getType().convertPrimitiveTypeFromString(inputValues.get(inputName));
413+
414+
ToscaFunction.ToscaBooleanFunction inputValidationFunction = inputDefinition.getValidation();
415+
if (inputValue != null && inputValidationFunction != null && !inputValidationFunction.evaluate(inputValue)) {
416+
throw new InvalidParameterValueException(String.format("The input [%s] declared in the node template [%s] is invalid. The value [%s] does not satisfy the validation rules.", inputName, nodeTemplateName, inputValue));
417+
}
418+
419+
if (inputValue == null) {
420+
logger.debug("The input [{}] was not provided. Checking if it has a default value.", inputName);
421+
if (inputDefinition.getDefaultValue() == null) {
422+
throw new InvalidParameterValueException(String.format("The input [%s] declared in the node template [%s] is required but it was not provided and it does not have a default value.", inputName, nodeTemplateName));
423+
}
424+
inputValue = inputDefinition.getDefaultValue();
425+
}
426+
return inputValue;
427+
}
428+
429+
private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object> functionCall, String nodeTemplateName, ToscaServiceTemplate serviceTemplate) {
422430
String toscaFunction = functionCall.keySet().iterator().next();
423431
List<?> args = ToscaYamlHelper.asList(functionCall.get(toscaFunction));
424432
String targetNodeName = ToscaYamlHelper.asString(args.get(0));
@@ -429,7 +437,7 @@ private Object resolveGetAttributeAndGetPropertyFunctionCall(Map<String, Object>
429437
targetNode.getProperty(targetField).getEvaluatedValue() : targetNode.getAttribute(targetField);
430438

431439
if (functionCallResult == null) {
432-
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()));
440+
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, nodeTemplateName));
433441
}
434442
return functionCallResult;
435443
}

0 commit comments

Comments
 (0)