Skip to content

Commit aaf8b5f

Browse files
build api params dynamically
1 parent 6783d1d commit aaf8b5f

8 files changed

Lines changed: 124 additions & 77 deletions

File tree

engine/schema/src/main/resources/nimble/resource-types/load-balancer-attachment.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ data_types:
2626
type: string
2727
description: The ID of the virtual machine.
2828
required: true
29+
metadata:
30+
api-parameter: virtualmachineid
2931
ip:
3032
type: string
3133
description: The internal IP address of the virtual machine.

engine/schema/src/main/resources/nimble/resource-types/virtual-machine.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ data_types:
2727
description: The ID of the network.
2828
required: true
2929
metadata:
30-
api-parameter: kubernetesversionid
30+
api-parameter: networkid
3131
ip:
3232
type: string
3333
description: The IP address of the network.

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ public void setUnresolvedPropertiesByGetAttribute(Set<ToscaProperty> unresolvedP
6262
this.unresolvedPropertiesByGetAttribute = unresolvedPropertiesByGetAttribute;
6363
}
6464

65-
public String getApiName() {
66-
return "createVPC";
65+
public Map<String, String> getApiParams() {
66+
Map<String, String> params = new HashMap<>();
67+
68+
for (ToscaProperty property : properties.values()) {
69+
params.putAll(property.getApiRepresentationOfProperty());
70+
}
71+
72+
return params;
6773
}
6874
}

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

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

19+
import org.apache.cloudstack.tosca.parser.ToscaYamlHelper;
20+
21+
import java.util.HashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.stream.Collectors;
25+
1926
public class ToscaProperty {
2027
private final ToscaPropertyDefinition definition;
2128
private final Object rawValue;
22-
private volatile String evaluatedValue;
29+
private volatile Object evaluatedValue;
2330

24-
public ToscaProperty(ToscaPropertyDefinition definition, Object rawValue, String evaluatedValue) {
31+
public ToscaProperty(ToscaPropertyDefinition definition, Object rawValue, Object evaluatedValue) {
2532
this.definition = definition;
2633
this.rawValue = rawValue;
2734
this.evaluatedValue = evaluatedValue;
@@ -31,15 +38,58 @@ public Object getRawValue() {
3138
return rawValue;
3239
}
3340

34-
public String getEvaluatedValue() {
41+
public Object getEvaluatedValue() {
3542
return evaluatedValue;
3643
}
3744

38-
public void setEvaluatedValue(String evaluatedValue) {
45+
public void setEvaluatedValue(Object evaluatedValue) {
3946
this.evaluatedValue = evaluatedValue;
4047
}
4148

4249
public ToscaPropertyDefinition getDefinition() {
4350
return definition;
4451
}
52+
53+
protected Map<String, String> getApiRepresentationOfProperty() {
54+
ToscaTypeDefinition.Kind kind = definition.getType().getKind();
55+
if (kind == ToscaTypeDefinition.Kind.PRIMITIVE) {
56+
return Map.of(definition.getApiParameter(), String.valueOf(evaluatedValue));
57+
}
58+
59+
if (kind == ToscaTypeDefinition.Kind.COLLECTION && definition.getType().getCollectionType() == ToscaCollectionType.LIST) {
60+
return getApiRepresentationOfLists();
61+
}
62+
63+
if (kind == ToscaTypeDefinition.Kind.COLLECTION && definition.getType().getCollectionType() == ToscaCollectionType.MAP) {
64+
return getApiRepresentationOfMaps(0, ToscaYamlHelper.asMap(evaluatedValue), null);
65+
}
66+
67+
return getApiRepresentationOfMaps(0, ToscaYamlHelper.asMap(evaluatedValue), definition.getType().getDataType());
68+
}
69+
70+
private Map<String, String> getApiRepresentationOfLists() {
71+
ToscaTypeDefinition.Kind entrySchemaKind = definition.getType().getEntrySchema().getKind();
72+
if (entrySchemaKind == ToscaTypeDefinition.Kind.PRIMITIVE) {
73+
List<String> items = ToscaYamlHelper.asList(evaluatedValue).stream().map(item -> String.valueOf((Object) item)).collect(Collectors.toList());
74+
return Map.of(definition.getApiParameter(), String.join(",", items));
75+
}
76+
77+
Map<String, String> params = new HashMap<>();
78+
List<?> items = ToscaYamlHelper.asList(evaluatedValue);
79+
ToscaDataTypeDefinition dataTypeDefinition = definition.getType().getEntrySchema().getDataType();
80+
for (int i = 0; i < items.size(); i++) {
81+
params.putAll(getApiRepresentationOfMaps(i, ToscaYamlHelper.asMap(items.get(i)), dataTypeDefinition));
82+
}
83+
return params;
84+
}
85+
86+
private Map<String, String> getApiRepresentationOfMaps(int index, Map<String, Object> map, ToscaDataTypeDefinition dataTypeDefinition) {
87+
Map<String, String> params = new HashMap<>();
88+
String key = String.format("%s[%d].", definition.getApiParameter(), index);
89+
map.forEach((field, value) -> {
90+
String apiFieldName = dataTypeDefinition == null ? field : dataTypeDefinition.getProperties().get(field).getApiParameter();
91+
params.put(key + apiFieldName, String.valueOf(value));
92+
});
93+
return params;
94+
}
4595
}

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

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,13 @@ private CompletableFuture<String> provisionNode(ToscaNodeTemplate nodeTemplate)
184184
}
185185

186186
private void dispatchProvisioningCommand(ToscaNodeTemplate nodeTemplate, CallContext callContext) {
187-
Class<?> apiClass = apiServer.getCmdClass(nodeTemplate.getApiName());
187+
Class<?> apiClass = apiServer.getCmdClass(nodeTemplate.getType().getProvisioningApi());
188188
try {
189189
Object cmd = apiClass.getDeclaredConstructor().newInstance();
190190
if (cmd instanceof BaseAsyncCmd) {
191-
dispatchProvisioningAsynchronousCommand((BaseAsyncCmd) cmd, callContext);
191+
dispatchProvisioningAsynchronousCommand((BaseAsyncCmd) cmd, nodeTemplate.getApiParams(), callContext);
192192
} else if (cmd instanceof BaseCmd) {
193-
dispatchProvisioningSynchronousCommand((BaseCmd) cmd, callContext);
193+
dispatchProvisioningSynchronousCommand((BaseCmd) cmd, nodeTemplate.getApiParams(), callContext);
194194
} else {
195195
throw new Exception();
196196
}
@@ -200,25 +200,17 @@ private void dispatchProvisioningCommand(ToscaNodeTemplate nodeTemplate, CallCon
200200
}
201201
}
202202

203-
private void dispatchProvisioningAsynchronousCommand(BaseAsyncCmd asyncCmd, CallContext callContext) {
204-
Map<String, String> params = new HashMap<>(Map.of(
205-
"zoneid", "309ea14d-ce26-44eb-ac05-53106b0ccb17",
206-
"name", "vpc-" + new Random().nextInt(100000),
207-
"vpcofferingid", "3e70fd9b-bc5a-4d4b-89f1-40dc756e8058",
208-
"cidr", "10.0.0.0/16",
209-
"ctxUserId", String.valueOf(callContext.getCallingUserId()),
210-
"ctxAccountId", String.valueOf(callContext.getCallingAccountId())
211-
));
203+
private void dispatchProvisioningAsynchronousCommand(BaseAsyncCmd asyncCmd, Map<String, String> apiParams, CallContext callContext) {
212204
CreateVPCCmd cmd = new CreateVPCCmd();
213205
cmd = ComponentContext.inject(cmd);
214206
try {
215207
CallContext.register(callContext, null);
216-
apiDispatcher.dispatchCreateCmd(cmd, params);
217-
params.put("ctxStartEventId", "1");
208+
apiDispatcher.dispatchCreateCmd(cmd, apiParams);
209+
apiParams.put("ctxStartEventId", "1");
218210
Long objectId = ObjectUtils.defaultIfNull(cmd.getEntityId(), cmd.getApiResourceId());
219-
params.put("id", objectId.toString());
211+
apiParams.put("id", objectId.toString());
220212
AsyncJobVO job = new AsyncJobVO("", callContext.getCallingUserId(), callContext.getCallingAccountId(), CreateVPCCmd.class.getName(),
221-
ApiGsonHelper.getBuilder().create().toJson(params), objectId,
213+
ApiGsonHelper.getBuilder().create().toJson(apiParams), objectId,
222214
cmd.getApiResourceType() != null ? cmd.getApiResourceType().toString() : null,
223215
null);
224216
job.setDispatcher(asyncJobDispatcher.getName());
@@ -234,18 +226,13 @@ private void dispatchProvisioningAsynchronousCommand(BaseAsyncCmd asyncCmd, Call
234226
}
235227
}
236228

237-
private void dispatchProvisioningSynchronousCommand(BaseCmd syncCmd, CallContext callContext) {
229+
private void dispatchProvisioningSynchronousCommand(BaseCmd syncCmd, Map<String, String> apiParams, CallContext callContext) {
238230
logger.debug("Constructing provisioning command");
239231
CallContext.register(callContext, null);
240232
CreateVMGroupCmd cmd = new CreateVMGroupCmd();
241233
cmd = ComponentContext.inject(cmd);
242-
Map<String, String> params = Map.of(
243-
"domainid", "1",
244-
"account", "admin",
245-
"name", "instance-group-" + new Random().nextInt(100000)
246-
);
247234
try {
248-
apiDispatcher.dispatch(cmd, params, false);
235+
apiDispatcher.dispatch(cmd, apiParams, false);
249236
logger.info(cmd.getResponseObject());
250237
} catch (Exception e) {
251238

plugins/iac/nimble/src/main/java/org/apache/cloudstack/tosca/parser/ToscaNodeTypeParser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.cloudstack.tosca.model.ToscaDataTypeDefinition;
2222
import org.apache.cloudstack.tosca.model.ToscaNodeType;
2323
import org.apache.cloudstack.tosca.model.ToscaPropertyDefinition;
24+
import org.apache.commons.lang3.ObjectUtils;
2425
import org.apache.logging.log4j.LogManager;
2526
import org.apache.logging.log4j.Logger;
2627

plugins/iac/nimble/src/main/java/org/apache/cloudstack/tosca/parser/ToscaServiceTemplateParser.java

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -264,38 +264,7 @@ private ToscaProperty parsePropertyValue(String propertyName, Object propertyBod
264264
return null;
265265
}
266266

267-
String propertyValue = getPropertyValueAsString(propertyBody, type);
268-
return new ToscaProperty(propertyDefinition, propertyBody, propertyValue);
269-
}
270-
271-
private String getPropertyValueAsString(Object propertyBody, ToscaTypeDefinition type) {
272-
if (type.getKind() == ToscaTypeDefinition.Kind.PRIMITIVE) {
273-
return String.valueOf(propertyBody);
274-
}
275-
276-
if (type.getKind() == ToscaTypeDefinition.Kind.DATA_TYPE) {
277-
StringBuilder builder = new StringBuilder();
278-
ToscaDataTypeDefinition dataTypeDefinition = type.getEntrySchema().getDataType();
279-
for (ToscaPropertyDefinition propertyDefinition : dataTypeDefinition.getProperties().values()) {
280-
281-
}
282-
283-
}
284-
285-
if (type.getKind() == ToscaTypeDefinition.Kind.COLLECTION) {
286-
if (type.getCollectionType() == ToscaCollectionType.LIST && type.getEntrySchema().getKind() == ToscaTypeDefinition.Kind.PRIMITIVE) {
287-
List<String> items = (List<String>) ToscaYamlHelper.asList(propertyBody);
288-
return String.join(",", items);
289-
}
290-
291-
// provavelmente, vai ser melhor jogar esse metodo
292-
// para o getparams do nodetemplate, pq la tu vai conseguir identificar
293-
// que é um mapa e vai conseguir colocar varias chaves no formato <paramname>[<int>].<key> com os seus respectivos valores
294-
// [0].key1=value
295-
// [0].key2=value
296-
// [1].key1=value
297-
// [1].key2=value
298-
}
267+
return new ToscaProperty(propertyDefinition, propertyBody, propertyBody);
299268
}
300269

301270
private ToscaProperty parseGetInputPropertyValue(String propertyName, Map<String, Object> propertyBody, ToscaPropertyDefinition propertyDefinition, String nodeTemplateName, ToscaServiceTemplateParsingContext context) {

0 commit comments

Comments
 (0)