diff --git a/core/src/main/java/io/kestra/core/docs/JsonSchemaGenerator.java b/core/src/main/java/io/kestra/core/docs/JsonSchemaGenerator.java index 76a5398c738..2eade76ce5f 100644 --- a/core/src/main/java/io/kestra/core/docs/JsonSchemaGenerator.java +++ b/core/src/main/java/io/kestra/core/docs/JsonSchemaGenerator.java @@ -82,6 +82,7 @@ public Map schemas(Class cls, boolean arrayOf) } replaceAnyOfWithOneOf(objectNode); pullOfDefaultFromOneOf(objectNode); + removeRequiredOnPropsWithDefaults(objectNode); return JacksonMapper.toMap(objectNode); } catch (IllegalArgumentException e) { @@ -89,6 +90,27 @@ public Map schemas(Class cls, boolean arrayOf) } } + private void removeRequiredOnPropsWithDefaults(ObjectNode objectNode) { + objectNode.findParents("required").forEach(jsonNode -> { + if (jsonNode instanceof ObjectNode clazzSchema && clazzSchema.get("required") instanceof ArrayNode requiredPropsNode && clazzSchema.get("properties") instanceof ObjectNode properties) { + List requiredFieldValues = StreamSupport.stream(requiredPropsNode.spliterator(), false) + .map(JsonNode::asText) + .toList(); + + properties.fields().forEachRemaining(e -> { + int indexInRequiredArray = requiredFieldValues.indexOf(e.getKey()); + if (indexInRequiredArray != -1 && e.getValue() instanceof ObjectNode valueNode && valueNode.has("default")) { + requiredPropsNode.remove(indexInRequiredArray); + } + }); + + if (requiredPropsNode.isEmpty()) { + clazzSchema.remove("required"); + } + } + }); + } + private void replaceAnyOfWithOneOf(ObjectNode objectNode) { objectNode.findParents("anyOf").forEach(jsonNode -> { if (jsonNode instanceof ObjectNode oNode) { @@ -605,6 +627,7 @@ protected Map generate(Class cls, @Nullable Cla ObjectNode objectNode = generator.generateSchema(cls); replaceAnyOfWithOneOf(objectNode); pullOfDefaultFromOneOf(objectNode); + removeRequiredOnPropsWithDefaults(objectNode); return JacksonMapper.toMap(extractMainRef(objectNode)); } catch (IllegalArgumentException e) { diff --git a/core/src/test/java/io/kestra/core/docs/JsonSchemaGeneratorTest.java b/core/src/test/java/io/kestra/core/docs/JsonSchemaGeneratorTest.java index 274716f4a04..61f6497b97b 100644 --- a/core/src/test/java/io/kestra/core/docs/JsonSchemaGeneratorTest.java +++ b/core/src/test/java/io/kestra/core/docs/JsonSchemaGeneratorTest.java @@ -26,6 +26,7 @@ import io.kestra.plugin.core.log.Log; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.inject.Inject; +import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.experimental.SuperBuilder; import org.hamcrest.Matchers; @@ -238,6 +239,15 @@ void betaTask() { assertThat(((Map>) generate.get("properties")).get("beta").get("$beta"), is(true)); } + @SuppressWarnings("unchecked") + @Test + void requiredAreRemovedIfThereIsADefault() { + Map generate = jsonSchemaGenerator.properties(Task.class, RequiredWithDefault.class); + assertThat(generate, is(not(nullValue()))); + assertThat((List) generate.get("required"), not(containsInAnyOrder("requiredWithDefault"))); + assertThat((List) generate.get("required"), containsInAnyOrder("requiredWithNoDefault")); + } + @SuppressWarnings("unchecked") @Test void dashboard() throws URISyntaxException { @@ -324,6 +334,7 @@ private enum TestEnum { } @Schema(title = "Test class") + @Builder private static class TestClass { @Schema(title = "Test property") public String testProperty; @@ -360,4 +371,21 @@ public VoidOutput sendLogs(RunContext runContext, Flux logRecord) thr return null; } } + + @SuperBuilder + @ToString + @EqualsAndHashCode + @Getter + @NoArgsConstructor + @Plugin + public static class RequiredWithDefault extends Task { + @PluginProperty + @NotNull + @Builder.Default + private Property requiredWithDefault = Property.of(TaskWithEnum.TestClass.builder().testProperty("test").build()); + + @PluginProperty + @NotNull + private Property requiredWithNoDefault; + } } diff --git a/jdbc/src/test/java/io/kestra/jdbc/runner/JdbcServiceLivenessCoordinatorTest.java b/jdbc/src/test/java/io/kestra/jdbc/runner/JdbcServiceLivenessCoordinatorTest.java index dada1abeb2b..fa7f6a1671b 100644 --- a/jdbc/src/test/java/io/kestra/jdbc/runner/JdbcServiceLivenessCoordinatorTest.java +++ b/jdbc/src/test/java/io/kestra/jdbc/runner/JdbcServiceLivenessCoordinatorTest.java @@ -1,6 +1,7 @@ package io.kestra.jdbc.runner; import com.google.common.collect.ImmutableMap; +import io.kestra.core.junit.annotations.KestraTest; import io.kestra.core.models.conditions.ConditionContext; import io.kestra.core.models.executions.Execution; import io.kestra.core.models.executions.TaskRun; @@ -11,14 +12,7 @@ import io.kestra.core.queues.QueueFactoryInterface; import io.kestra.core.queues.QueueInterface; import io.kestra.core.repositories.LocalFlowRepositoryLoader; -import io.kestra.core.runners.RunContextFactory; -import io.kestra.core.runners.StandAloneRunner; -import io.kestra.core.runners.Worker; -import io.kestra.core.runners.WorkerJob; -import io.kestra.core.runners.WorkerTask; -import io.kestra.core.runners.WorkerTaskResult; -import io.kestra.core.runners.WorkerTrigger; -import io.kestra.core.runners.WorkerTriggerResult; +import io.kestra.core.runners.*; import io.kestra.core.services.SkipExecutionService; import io.kestra.core.tasks.test.SleepTrigger; import io.kestra.core.utils.Await; @@ -28,7 +22,6 @@ import io.kestra.plugin.core.flow.Sleep; import io.micronaut.context.ApplicationContext; import io.micronaut.context.annotation.Property; -import io.kestra.core.junit.annotations.KestraTest; import jakarta.inject.Inject; import jakarta.inject.Named; import org.junit.jupiter.api.BeforeAll; @@ -157,7 +150,7 @@ void taskResubmitSkipExecution() throws Exception { }); workerJobQueue.emit(workerTask); - boolean runningLatchAwait = runningLatch.await(2, TimeUnit.SECONDS); + boolean runningLatchAwait = runningLatch.await(10, TimeUnit.SECONDS); assertThat(runningLatchAwait, is(true)); worker.shutdown(); diff --git a/script/src/main/java/io/kestra/plugin/scripts/runner/docker/Docker.java b/script/src/main/java/io/kestra/plugin/scripts/runner/docker/Docker.java index a2f8750b4fe..25795c0c58d 100644 --- a/script/src/main/java/io/kestra/plugin/scripts/runner/docker/Docker.java +++ b/script/src/main/java/io/kestra/plugin/scripts/runner/docker/Docker.java @@ -337,6 +337,8 @@ public static Docker from(DockerOptions dockerOptions) { @Override public TaskRunnerResult run(RunContext runContext, TaskCommands taskCommands, List filesToDownload) throws Exception { + Boolean renderedDelete = runContext.render(delete).as(Boolean.class).orElseThrow(); + if (taskCommands.getContainerImage() == null && this.image == null) { throw new IllegalArgumentException("This task runner needs the `containerImage` property to be set"); } @@ -538,7 +540,7 @@ public void onComplete() { // come to a normal end. kill(); - if (Boolean.TRUE.equals(runContext.render(delete).as(Boolean.class).orElseThrow())) { + if (Boolean.TRUE.equals(renderedDelete)) { dockerClient.removeContainerCmd(exec.getId()).exec(); if (logger.isTraceEnabled()) { logger.trace("Container deleted: {}", exec.getId());