mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-26 14:00:23 -05:00
Compare commits
1 Commits
run-develo
...
fix/gh-118
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
655de98781 |
@@ -130,7 +130,7 @@ public class FlowInputOutput {
|
||||
private Mono<Map<String, Object>> readData(List<Input<?>> inputs, Execution execution, Publisher<CompletedPart> data, boolean uploadFiles) {
|
||||
return Flux.from(data)
|
||||
.publishOn(Schedulers.boundedElastic())
|
||||
.<AbstractMap.SimpleEntry<String, String>>handle((input, sink) -> {
|
||||
.<Map.Entry<String, String>>handle((input, sink) -> {
|
||||
if (input instanceof CompletedFileUpload fileUpload) {
|
||||
boolean oldStyleInput = false;
|
||||
if ("files".equals(fileUpload.getName())) {
|
||||
@@ -150,7 +150,7 @@ public class FlowInputOutput {
|
||||
.getContextStorageURI()
|
||||
);
|
||||
fileUpload.discard();
|
||||
sink.next(new AbstractMap.SimpleEntry<>(inputId, from.toString()));
|
||||
sink.next(Map.entry(inputId, from.toString()));
|
||||
} else {
|
||||
try {
|
||||
final String fileExtension = FileInput.findFileInputExtension(inputs, fileName);
|
||||
@@ -165,7 +165,7 @@ public class FlowInputOutput {
|
||||
return;
|
||||
}
|
||||
URI from = storageInterface.from(execution, inputId, fileName, tempFile);
|
||||
sink.next(new AbstractMap.SimpleEntry<>(inputId, from.toString()));
|
||||
sink.next(Map.entry(inputId, from.toString()));
|
||||
} finally {
|
||||
if (!tempFile.delete()) {
|
||||
tempFile.deleteOnExit();
|
||||
@@ -178,13 +178,13 @@ public class FlowInputOutput {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sink.next(new AbstractMap.SimpleEntry<>(input.getName(), new String(input.getBytes())));
|
||||
sink.next(Map.entry(input.getName(), new String(input.getBytes())));
|
||||
} catch (IOException e) {
|
||||
sink.error(e);
|
||||
}
|
||||
}
|
||||
})
|
||||
.collectMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue);
|
||||
.collectMap(Map.Entry::getKey, Map.Entry::getValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +334,7 @@ public class FlowInputOutput {
|
||||
}
|
||||
|
||||
// validate and parse input value
|
||||
if (value == null) {
|
||||
if (value == null || "NULL".equals(value.toString().toUpperCase(Locale.ROOT))) {
|
||||
if (input.getRequired()) {
|
||||
resolvable.resolveWithError(input.toConstraintViolationException("missing required input", null));
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,7 @@ import io.micronaut.http.multipart.CompletedFileUpload;
|
||||
import io.micronaut.http.multipart.CompletedPart;
|
||||
import io.micronaut.test.annotation.MockBean;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -34,6 +35,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
@KestraTest
|
||||
class FlowInputOutputTest {
|
||||
@@ -335,6 +337,44 @@ class FlowInputOutputTest {
|
||||
Assertions.assertEquals(TEST_SECRET_VALUE, results.get("input"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotGetDefaultWhenPassingNullForNotRequiredInput() {
|
||||
// Given
|
||||
StringInput input = StringInput.builder()
|
||||
.id("input")
|
||||
.type(Type.STRING)
|
||||
.defaults(Property.ofValue("default"))
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
Mono<CompletedPart> data = Mono.just(new MemoryCompletedPart("input", "null".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
// When
|
||||
Map<String, Object> results = flowInputOutput.readExecutionInputs(List.of(input), null, DEFAULT_TEST_EXECUTION, data).block();
|
||||
|
||||
// Then
|
||||
Assertions.assertNull(results.get("input"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotGetErrorWhenPassingNullForRequiredInput() {
|
||||
// Given
|
||||
StringInput input = StringInput.builder()
|
||||
.id("input")
|
||||
.type(Type.STRING)
|
||||
.defaults(Property.ofValue("default"))
|
||||
.required(true)
|
||||
.build();
|
||||
|
||||
Mono<CompletedPart> data = Mono.just(new MemoryCompletedPart("input", "null".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
// When
|
||||
ConstraintViolationException exception = Assertions.assertThrows(ConstraintViolationException.class, () ->
|
||||
flowInputOutput.readExecutionInputs(List.of(input), null, DEFAULT_TEST_EXECUTION, data).block()
|
||||
);
|
||||
assertThat(exception.getMessage()).isEqualTo("input: Invalid input for `input`, missing required input, but received `null`");
|
||||
}
|
||||
|
||||
private static class MemoryCompletedPart implements CompletedPart {
|
||||
|
||||
protected final String name;
|
||||
|
||||
@@ -5,9 +5,14 @@ export const inputsToFormData = (submitor, inputsList, values) => {
|
||||
let inputValuesCloned = _cloneDeep(values)
|
||||
|
||||
for (const input of inputsList || []) {
|
||||
if (inputValuesCloned[input.id] === undefined || inputValuesCloned[input.id] === "") {
|
||||
if (inputValuesCloned[input.id] === undefined) {
|
||||
delete inputValuesCloned[input.id];
|
||||
}
|
||||
|
||||
// Input was explicitly filled with empty string
|
||||
if (inputValuesCloned[input.id] === "") {
|
||||
inputValuesCloned[input.id] = undefined;
|
||||
}
|
||||
|
||||
// Required to have "undefined" value for boolean
|
||||
if (input.type === "BOOLEAN" && inputValuesCloned[input.id] === "undefined") {
|
||||
@@ -34,6 +39,8 @@ export const inputsToFormData = (submitor, inputsList, values) => {
|
||||
} else {
|
||||
formData.append(inputName, inputValue);
|
||||
}
|
||||
} else if (input.type !== "BOOLEAN") {
|
||||
formData.append(inputName, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user