Skip to content

Commit

Permalink
fix(core): render list
Browse files Browse the repository at this point in the history
Fixes #7253
  • Loading branch information
loicmathieu committed Feb 12, 2025
1 parent bd9ba88 commit b45a44b
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
23 changes: 21 additions & 2 deletions core/src/main/java/io/kestra/core/models/property/Property.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.Map;
import java.util.Objects;

import static io.kestra.core.utils.Rethrow.throwFunction;

/**
* Define a plugin properties that will be rendered and converted to a target type at use time.
*
Expand Down Expand Up @@ -136,12 +138,29 @@ public static <T, I> T asList(Property<T> property, RunContext runContext, Class
*
* @see io.kestra.core.runners.RunContextProperty#asList(Class, Map)
*/
@SuppressWarnings("unchecked")
public static <T, I> T asList(Property<T> property, RunContext runContext, Class<I> itemClazz, Map<String, Object> variables) throws IllegalVariableEvaluationException {
if (property.value == null) {
String rendered = runContext.render(property.expression, variables);
JavaType type = MAPPER.getTypeFactory().constructCollectionLikeType(List.class, itemClazz);
try {
property.value = MAPPER.readValue(rendered, type);
String trimmedExpression = property.expression.trim();
// We need to detect if the expression is already a list or if it's a pebble expression (for eg. referencing a variable containing a list).
// Doing that allows us to, if it's an expression, first render then read it as a list.
if (trimmedExpression.startsWith("{{") && trimmedExpression.endsWith("}}")) {
property.value = MAPPER.readValue(runContext.render(property.expression, variables), type);
}
// Otherwise if it's already a list, we read it as a list first then render it from run context which handle list rendering by rendering each item of the list
else {
List<?> asRawList = MAPPER.readValue(runContext.render(property.expression, variables), List.class);
property.value = (T) asRawList.stream()
.map(throwFunction(item -> {
if (item instanceof String str) {
return MAPPER.convertValue(str, itemClazz);
}
return item;
}))
.toList();
}
} catch (JsonProcessingException e) {
throw new IllegalVariableEvaluationException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,30 @@ void arrayAndMapToRender() throws Exception {
assertThat(output.getMap().get("mapKey2"), is("mapValue2"));
}

@Test
void aListToRender() throws Exception {
var task = DynamicPropertyExampleTask.builder()
.items(new Property<>("""
["python test.py --input1 \\"{{ item1 }}\\" --input2 \\"{{ item2 }}\\""]"""))
.properties(new Property<>("""
{
"key1": "{{value1}}",
"key2": "{{value2}}"
}"""))
.build();
var runContext = runContextFactory.of(Map.ofEntries(
entry("item1", "item1"),
entry("item2", "item2"),
entry("value1", "value1"),
entry("value2", "value2")
));

var output = task.run(runContext);

assertThat(output, notNullValue());
assertThat(output.getList(), containsInAnyOrder("python test.py --input1 \"item1\" --input2 \"item2\""));
}

@Builder
@Getter
private static class TestObj {
Expand Down

0 comments on commit b45a44b

Please sign in to comment.