Compare commits

...

12 Commits

Author SHA1 Message Date
Loïc Mathieu
f43947b649 chore(tests): stop using the RunnerUtils in tests 2025-11-04 16:16:02 +01:00
Roman Acevedo
18b6b4ce5d test(kv): plain text header is sent now 2025-11-04 15:16:18 +01:00
Krie
dd65b4697e fix: preserve KV description when editing entries (fixes #12598) (#12606) 2025-11-04 15:04:27 +01:00
brian.mulier
9294c9f885 chore(version): upgrade to v1.2.0-SNAPSHOT 2025-11-04 14:04:13 +01:00
brian.mulier
ee63c33ef3 fix(ci): failsafe global-create-new-release-branch.yml 2025-11-04 13:49:59 +01:00
Roman Acevedo
d620dd7dec test: set retryWithFlowableErrors as FlakyTest 2025-11-04 13:46:14 +01:00
brian.mulier
02425586d6 fix(ci): failsafe global-create-new-release-branch.yml 2025-11-04 13:44:44 +01:00
brian.mulier
56d48ddf32 fix(ci): failsafe global-create-new-release-branch.yml 2025-11-04 13:41:32 +01:00
brian.mulier
1a5c79827b fix(ci): failsafe global-create-new-release-branch.yml 2025-11-04 13:36:06 +01:00
Florian Hussonnois
08b20fda68 fix(core): resolution of plugin must be done with a stable version 2025-11-04 11:29:47 +01:00
François Delbrayelle
7192ad1494 doc(http/request): fix doc about basic auth (#12626) 2025-11-04 10:44:36 +01:00
YannC
f164cddf7a Fix/sdk changes (#12411) (#12617)
* Fix/sdk changes (#12411)

* fix: kv controller remove namespace check

* clean(API): add query to filter parameter

* fix: flow update not deprecated

* clean(API): add deprecated on open api

* feat: executions annotations for skipping, follow method generation in sdk

* feat: add typing indication to validateTask

* fix(flowController): set correct hidden for json method in

* fix: optional params in delete executions endpoints

* fix: inputs/outputs as object

* change KV schema type to be object

* add back , deprecated = false on flow update, otherwise its marked as deprecated

* Revert "add back , deprecated = false on flow update, otherwise its marked as deprecated"

This reverts commit 3772404b68f14f0a80af9e0adb9952d58e9102b4.

* feat(API): add multipart to openAPI

* feat(API): add multipart to openAPI

* fix: only use plain-text for setKeyValue endpoint

* fix: KV command test

* chore: add multipart vendor annotations for custom generation on SDK

---------

Co-authored-by: YannC. <ycoornaert@kestra.io>
Co-authored-by: nKwiatkowski <nkwiatkowski@kestra.io>

* fix: kv test remove content type

---------

Co-authored-by: Roman Acevedo <roman.acevedo62@gmail.com>
Co-authored-by: nKwiatkowski <nkwiatkowski@kestra.io>
2025-11-04 08:37:08 +01:00
21 changed files with 484 additions and 423 deletions

View File

@@ -64,7 +64,8 @@ jobs:
cd kestra
# Create and push release branch
git checkout -b "$PUSH_RELEASE_BRANCH";
git checkout -B "$PUSH_RELEASE_BRANCH";
git pull origin "$PUSH_RELEASE_BRANCH" --rebase || echo "No existing branch to pull";
git push -u origin "$PUSH_RELEASE_BRANCH";
# Run gradle release

View File

@@ -62,7 +62,7 @@ public class KvUpdateCommand extends AbstractApiCommand {
Duration ttl = expiration == null ? null : Duration.parse(expiration);
MutableHttpRequest<String> request = HttpRequest
.PUT(apiUri("/namespaces/", tenantService.getTenantId(tenantId)) + namespace + "/kv/" + key, value)
.contentType(MediaType.APPLICATION_JSON_TYPE);
.contentType(MediaType.TEXT_PLAIN);
if (ttl != null) {
request.header("ttl", ttl.toString());

View File

@@ -28,6 +28,7 @@ import io.kestra.core.utils.IdUtils;
import io.kestra.core.utils.ListUtils;
import io.kestra.core.utils.MapUtils;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
@@ -77,10 +78,12 @@ public class Execution implements DeletedInterface, TenantInterface {
@With
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Schema(implementation = Object.class)
Map<String, Object> inputs;
@With
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Schema(implementation = Object.class)
Map<String, Object> outputs;
@JsonSerialize(using = ListOrMapOfLabelSerializer.class)
@@ -88,6 +91,7 @@ public class Execution implements DeletedInterface, TenantInterface {
List<Label> labels;
@With
@Schema(implementation = Object.class)
Map<String, Object> variables;
@NotNull

View File

@@ -9,6 +9,7 @@ import io.kestra.core.models.tasks.Task;
import io.kestra.core.models.tasks.retrys.AbstractRetry;
import io.kestra.core.utils.IdUtils;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
@@ -55,6 +56,7 @@ public class TaskRun implements TenantInterface {
@With
@JsonInclude(JsonInclude.Include.ALWAYS)
@Nullable
@Schema(implementation = Object.class)
Variables outputs;
@NotNull

View File

@@ -2,6 +2,7 @@ package io.kestra.core.plugins;
import io.kestra.core.contexts.KestraContext;
import io.kestra.core.utils.ListUtils;
import io.kestra.core.utils.Version;
import io.micronaut.core.type.Argument;
import io.micronaut.http.HttpMethod;
import io.micronaut.http.HttpRequest;
@@ -45,6 +46,8 @@ public class PluginCatalogService {
private final boolean icons;
private final boolean oss;
private final Version currentStableVersion;
/**
* Creates a new {@link PluginCatalogService} instance.
@@ -59,7 +62,10 @@ public class PluginCatalogService {
this.httpClient = httpClient;
this.icons = icons;
this.oss = communityOnly;
Version version = Version.of(KestraContext.getContext().getVersion());
this.currentStableVersion = new Version(version.majorVersion(), version.minorVersion(), version.patchVersion(), null);
// Immediately trigger an async load of plugin artifacts.
this.isLoaded.set(true);
this.plugins = CompletableFuture.supplyAsync(this::load);
@@ -189,9 +195,10 @@ public class PluginCatalogService {
}
private List<ApiPluginArtifact> getAllCompatiblePlugins() {
MutableHttpRequest<Object> request = HttpRequest.create(
HttpMethod.GET,
"/v1/plugins/artifacts/core-compatibility/" + KestraContext.getContext().getVersion()
"/v1/plugins/artifacts/core-compatibility/" + currentStableVersion
);
if (oss) {
request.getParameters().add("license", "OPENSOURCE");

View File

@@ -52,10 +52,11 @@ import java.util.OptionalInt;
- id: basic_auth_api
type: io.kestra.plugin.core.http.Request
uri: http://host.docker.internal:8080/api/v1/executions/dev/inputs_demo
auth:
type: BASIC
username: "{{ secret('API_USERNAME') }}"
password: "{{ secret('API_PASSWORD') }}"
options:
auth:
type: BASIC
username: "{{ secret('API_USERNAME') }}"
password: "{{ secret('API_PASSWORD') }}"
method: POST
contentType: multipart/form-data
formData:

View File

@@ -4,27 +4,19 @@ import io.kestra.core.junit.annotations.ExecuteFlow;
import io.kestra.core.junit.annotations.KestraTest;
import io.kestra.core.junit.annotations.LoadFlows;
import io.kestra.core.models.executions.Execution;
import io.kestra.core.models.flows.Flow;
import io.kestra.core.models.flows.State;
import io.kestra.core.queues.QueueException;
import io.kestra.core.queues.QueueFactoryInterface;
import io.kestra.core.queues.QueueInterface;
import io.kestra.core.repositories.FlowRepositoryInterface;
import io.kestra.core.runners.ConcurrencyLimit;
import io.kestra.core.runners.RunnerUtils;
import io.kestra.core.runners.TestRunnerUtils;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import static io.kestra.core.utils.Rethrow.throwRunnable;
import static org.assertj.core.api.Assertions.assertThat;
@KestraTest(startRunner = true)
@@ -34,14 +26,7 @@ class ConcurrencyLimitServiceTest {
private static final String TENANT_ID = "main";
@Inject
private RunnerUtils runnerUtils;
@Inject
@Named(QueueFactoryInterface.EXECUTION_NAMED)
private QueueInterface<Execution> executionQueue;
@Inject
private FlowRepositoryInterface flowRepositoryInterface;
private TestRunnerUtils runnerUtils;
@Inject
private ConcurrencyLimitService concurrencyLimitService;
@@ -57,7 +42,8 @@ class ConcurrencyLimitServiceTest {
void unqueueExecution() throws QueueException, TimeoutException {
// run a first flow so the second is queued
runnerUtils.runOneUntilRunning(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", execution -> execution.getState().isQueued());
assertThat(result.getState().isQueued()).isTrue();
Execution unqueued = concurrencyLimitService.unqueue(result, State.Type.RUNNING);
@@ -101,21 +87,4 @@ class ConcurrencyLimitServiceTest {
assertThat(list.getFirst().getNamespace()).isEqualTo(execution.getNamespace());
assertThat(list.getFirst().getFlowId()).isEqualTo(execution.getFlowId());
}
private Execution runUntilQueued(String namespace, String flowId) throws TimeoutException, QueueException {
return runUntilState(namespace, flowId, State.Type.QUEUED);
}
private Execution runUntilState(String namespace, String flowId, State.Type state) throws TimeoutException, QueueException {
Execution execution = this.createExecution(namespace, flowId);
return runnerUtils.awaitExecution(
it -> execution.getId().equals(it.getId()) && it.getState().getCurrent() == state,
throwRunnable(() -> this.executionQueue.emit(execution)),
Duration.ofSeconds(1));
}
private Execution createExecution(String namespace, String flowId) {
Flow flow = flowRepositoryInterface.findById(TENANT_ID, namespace, flowId).orElseThrow();
return Execution.newExecution(flow, null);
}
}

View File

@@ -1,4 +1,4 @@
version=1.1.0-SNAPSHOT
version=1.2.0-SNAPSHOT
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.parallel=true

View File

@@ -1,6 +1,7 @@
package io.kestra.jdbc.runner;
import io.kestra.core.junit.annotations.ExecuteFlow;
import io.kestra.core.junit.annotations.FlakyTest;
import io.kestra.core.junit.annotations.KestraTest;
import io.kestra.core.junit.annotations.LoadFlows;
import io.kestra.core.models.executions.Execution;
@@ -138,6 +139,7 @@ public abstract class JdbcRunnerRetryTest {
retryCaseTest.retryDynamicTask(execution);
}
@FlakyTest(description = "it seems this flow sometimes stay stuck in RUNNING")
@Test
@ExecuteFlow("flows/valids/retry-with-flowable-errors.yaml")
void retryWithFlowableErrors(Execution execution){

View File

@@ -1,6 +1,5 @@
package io.kestra.core.runners;
import com.google.common.annotations.VisibleForTesting;
import io.kestra.core.models.Label;
import io.kestra.core.models.executions.Execution;
import io.kestra.core.models.flows.Flow;
@@ -162,6 +161,34 @@ public class TestRunnerUtils {
return this.emitAndAwaitExecution(isRunningExecution(execution), execution, duration);
}
public Execution runOneUntil(String tenantId, String namespace, String flowId, Predicate<Execution> predicate)
throws QueueException {
return this.runOneUntil(tenantId, namespace, flowId, null, null, null, predicate);
}
public Execution runOneUntil(String tenantId, String namespace, String flowId, Integer revision, BiFunction<FlowInterface, Execution, Map<String, Object>> inputs, Duration duration, Predicate<Execution> predicate)
throws QueueException {
return this.runOneUntil(
flowRepository
.findById(tenantId, namespace, flowId, revision != null ? Optional.of(revision) : Optional.empty())
.orElseThrow(() -> new IllegalArgumentException("Unable to find flow '" + flowId + "'")),
inputs,
duration,
predicate
);
}
public Execution runOneUntil(Flow flow, BiFunction<FlowInterface, Execution, Map<String, Object>> inputs, Duration duration, Predicate<Execution> predicate)
throws QueueException {
if (duration == null) {
duration = DEFAULT_MAX_WAIT_DURATION;
}
Execution execution = Execution.newExecution(flow, inputs, null, Optional.empty());
return this.emitAndAwaitExecution(predicate, execution, duration);
}
public Execution emitAndAwaitExecution(Predicate<Execution> predicate, Execution execution) throws QueueException {
return emitAndAwaitExecution(predicate, execution, Duration.ofSeconds(20));
}
@@ -300,7 +327,6 @@ public class TestRunnerUtils {
return receive.get();
}
@VisibleForTesting
public Execution awaitChildExecution(Flow flow, Execution parentExecution, Execution execution, Duration duration)
throws QueueException {
return this.emitAndAwaitExecution(isTerminatedChildExecution(parentExecution, flow), execution, duration);

View File

@@ -553,7 +553,7 @@
value = JSON.stringify(value);
}
const contentType = ["DATE", "DATETIME"].includes(type) ? "text/plain" : "application/json";
const contentType = "text/plain";
const namespace = kv.value.namespace!;
const key = kv.value.key!;

View File

@@ -78,10 +78,17 @@ export const useBaseNamespacesStore = () => {
}
const data = response.data;
const contentLength = response.headers?.["content-length"];
let value = data;
if (contentLength === (data.length + 2).toString()) {
return `"${data}"`;
value = `"${data}"`;
}
return data;
return {
type: response.headers?.["content-type"] || "STRING",
value: value,
description: response.headers?.["description"] || "",
ttl: response.headers?.["ttl"] || undefined
};
}
async function loadInheritedKVs(this: any, id: string) {

View File

@@ -71,6 +71,9 @@ import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -206,7 +209,7 @@ public class ExecutionController {
@Parameter(description = "The current page") @QueryValue(defaultValue = "1") @Min(1) int page,
@Parameter(description = "The current page size") @QueryValue(defaultValue = "10") @Min(1) int size,
@Parameter(description = "The sort of current page") @Nullable @QueryValue List<String> sort,
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
//Deprecated params
@Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@@ -355,9 +358,9 @@ public class ExecutionController {
@ApiResponse(responseCode = "204", description = "On success")
public HttpResponse<Void> deleteExecution(
@Parameter(description = "The execution id") @PathVariable String executionId,
@Parameter(description = "Whether to delete execution logs") @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics") @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage") @QueryValue(defaultValue = "true") Boolean deleteStorage
@Parameter(description = "Whether to delete execution logs", required = false) @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics", required = false) @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage", required = false) @QueryValue(defaultValue = "true") Boolean deleteStorage
) throws IOException {
Optional<Execution> execution = executionRepository.findById(tenantService.resolveTenant(), executionId);
if (execution.isPresent()) {
@@ -376,9 +379,9 @@ public class ExecutionController {
public MutableHttpResponse<?> deleteExecutionsByIds(
@RequestBody(description = "The execution id") @Body List<String> executionsId,
@Parameter(description = "Whether to delete non-terminated executions") @Nullable @QueryValue(defaultValue = "false") Boolean includeNonTerminated,
@Parameter(description = "Whether to delete execution logs") @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics") @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage") @QueryValue(defaultValue = "true") Boolean deleteStorage
@Parameter(description = "Whether to delete execution logs", required = false) @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics", required = false) @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage", required = false) @QueryValue(defaultValue = "true") Boolean deleteStorage
) throws IOException {
List<Execution> executions = new ArrayList<>();
Set<ManualConstraintViolation<String>> invalids = new HashSet<>();
@@ -417,27 +420,27 @@ public class ExecutionController {
@ExecuteOn(TaskExecutors.IO)
@Operation(tags = {"Executions"}, summary = "Delete executions filter by query parameters")
public HttpResponse<?> deleteExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Parameter(description = "Whether to delete non-terminated executions") @Nullable @QueryValue(defaultValue = "false") Boolean includeNonTerminated,
@Parameter(description = "Whether to delete execution logs") @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics") @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage") @QueryValue(defaultValue = "true") Boolean deleteStorage
@Parameter(description = "Whether to delete execution logs", required = false) @QueryValue(defaultValue = "true") Boolean deleteLogs,
@Parameter(description = "Whether to delete execution metrics", required = false) @QueryValue(defaultValue = "true") Boolean deleteMetrics,
@Parameter(description = "Whether to delete execution files in the internal storage", required = false) @QueryValue(defaultValue = "true") Boolean deleteStorage
) throws IOException {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -690,7 +693,16 @@ public class ExecutionController {
@ExecuteOn(TaskExecutors.IO)
@Post(uri = "/{namespace}/{id}", consumes = MediaType.MULTIPART_FORM_DATA)
@Operation(tags = {"Executions"}, summary = "Create a new execution for a flow")
@Operation(
tags = {"Executions"},
summary = "Create a new execution for a flow",
extensions = @Extension(
name = "x-sdk-customization",
properties = {
@ExtensionProperty(name = "x-multipart", value = "true")
}
)
)
@ApiResponse(responseCode = "409", description = "if the flow is disabled")
@ApiResponse(responseCode = "200", description = "On execution created", content = {@Content(schema = @Schema(implementation = ExecutionResponse.class))})
@SingleResult
@@ -1020,22 +1032,22 @@ public class ExecutionController {
@Post(uri = "/restart/by-query")
@Operation(tags = {"Executions"}, summary = "Restart executions filter by query parameters")
public HttpResponse<?> restartExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) throws Exception {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -1080,13 +1092,32 @@ public class ExecutionController {
@ExecuteOn(TaskExecutors.IO)
@Post(uri = "/{executionId}/replay-with-inputs", consumes = MediaType.MULTIPART_FORM_DATA)
@Operation(tags = {"Executions"}, summary = "Create a new execution from an old one and start it from a specified task run id")
@Operation(
tags = {"Executions"},
summary = "Create a new execution from an old one and start it from a specified task run id",
extensions = @Extension(
name = "x-sdk-customization",
properties = {
@ExtensionProperty(name = "x-multipart", value = "true")
}
)
)
public Mono<Execution> replayExecutionWithinputs(
@Parameter(description = "the original execution id to clone") @PathVariable String executionId,
@Parameter(description = "The taskrun id") @Nullable @QueryValue String taskRunId,
@Parameter(description = "The flow revision to use for new execution") @Nullable @QueryValue Integer revision,
@Parameter(description = "Set a list of breakpoints at specific tasks 'id.value', separated by a coma.") @QueryValue Optional<String> breakpoints,
@RequestBody(description = "The inputs") @Body MultipartBody inputs
@RequestBody(
description = "The inputs (multipart map)",
content = @Content(
mediaType = MediaType.MULTIPART_FORM_DATA,
schema = @Schema(
type = "object",
additionalProperties = Schema.AdditionalPropertiesValue.TRUE,
additionalPropertiesSchema = Object.class
)
)
) @Body MultipartBody inputs
) {
Optional<Execution> execution = executionRepository.findById(tenantService.resolveTenant(), executionId);
if (execution.isEmpty()) {
@@ -1263,22 +1294,22 @@ public class ExecutionController {
@ApiResponse(responseCode = "200", description = "On success", content = {@Content(schema = @Schema(implementation = BulkResponse.class))})
@ApiResponse(responseCode = "422", description = "Changed state with errors", content = {@Content(schema = @Schema(implementation = BulkErrorResponse.class))})
public HttpResponse<?> updateExecutionsStatusByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Parameter(description = "The new state of the executions") @NotNull @QueryValue State.Type newStatus
) throws QueueException {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
@@ -1541,22 +1572,22 @@ public class ExecutionController {
@Post(uri = "/resume/by-query")
@Operation(tags = {"Executions"}, summary = "Resume executions filter by query parameters")
public HttpResponse<?> resumeExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) throws Exception {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -1650,22 +1681,22 @@ public class ExecutionController {
@Post(uri = "/pause/by-query")
@Operation(tags = {"Executions"}, summary = "Pause executions filter by query parameters")
public HttpResponse<?> pauseExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) throws Exception {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -1694,22 +1725,22 @@ public class ExecutionController {
@Delete(uri = "/kill/by-query")
@Operation(tags = {"Executions"}, summary = "Kill executions filter by query parameters")
public HttpResponse<?> killExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) throws QueueException {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -1738,22 +1769,22 @@ public class ExecutionController {
@Post(uri = "/replay/by-query")
@Operation(tags = {"Executions"}, summary = "Create new executions from old ones filter by query parameters. Keep the flow revision")
public HttpResponse<?> replayExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Parameter(description = "If latest revision should be used") @Nullable @QueryValue(defaultValue = "false") Boolean latestRevision
) throws Exception {
@@ -1829,7 +1860,17 @@ public class ExecutionController {
@ExecuteOn(TaskExecutors.IO)
@Get(uri = "/{executionId}/follow", produces = MediaType.TEXT_EVENT_STREAM)
@Operation(tags = {"Executions"}, summary = "Follow an execution")
@Operation(
tags = {"Executions"},
summary = "Follow an execution",
extensions = @Extension(
name = "x-sdk-customization",
properties = {
@ExtensionProperty(name = "x-replace-follow-execution", value = "true"),
@ExtensionProperty(name = "x-skipped", value = "true")
}
)
)
public Flux<Event<Execution>> followExecution(
@Parameter(description = "The execution id") @PathVariable String executionId
) {
@@ -2046,22 +2087,22 @@ public class ExecutionController {
@Post(uri = "/labels/by-query")
@Operation(tags = {"Executions"}, summary = "Set label on executions filter by query parameters")
public HttpResponse<?> setLabelsOnTerminatedExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@RequestBody(description = "The labels to add to the execution") @Body @NotNull @Valid List<Label> setLabels
) {
@@ -2163,22 +2204,22 @@ public class ExecutionController {
@Post(uri = "/unqueue/by-query")
@Operation(tags = {"Executions"}, summary = "Unqueue executions filter by query parameters")
public HttpResponse<?> unqueueExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter,
@Parameter(description = "The new state of the unqueued executions") @Nullable @QueryValue State.Type newState
) throws Exception {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
@@ -2277,22 +2318,22 @@ public class ExecutionController {
@Post(uri = "/force-run/by-query")
@Operation(tags = {"Executions"}, summary = "Force run executions filter by query parameters")
public HttpResponse<?> forceRunExecutionsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include") @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", examples = {
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the executions to include", deprecated = true) @Nullable @QueryValue(value = "scope") List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A flow id filter", deprecated = true) @Nullable @QueryValue String flowId,
@Deprecated @Parameter(description = "The start datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Deprecated @Parameter(description = "The end datetime", deprecated = true) @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Deprecated @Parameter(description = "A time range filter relative to the current time", deprecated = true, examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Deprecated @Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
@Deprecated @Parameter(description = "A state filter", deprecated = true) @Nullable @QueryValue List<State.Type> state,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Deprecated @Parameter(description = "The trigger execution id", deprecated = true) @Nullable @QueryValue String triggerExecutionId,
@Deprecated @Parameter(description = "A execution child filter", deprecated = true) @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) throws Exception {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -2367,7 +2408,17 @@ public class ExecutionController {
@ExecuteOn(TaskExecutors.IO)
@Get(uri = "/{executionId}/follow-dependencies", produces = MediaType.TEXT_EVENT_STREAM)
@Operation(tags = {"Executions"}, summary = "Follow all execution dependencies executions")
@Operation(
tags = {"Executions"},
summary = "Follow all execution dependencies executions",
extensions = @Extension(
name = "x-sdk-customization",
properties = {
@ExtensionProperty(name = "x-replace-follow-dependencies-execution", value = "true"),
@ExtensionProperty(name = "x-skipped", value = "true")
}
)
)
public Flux<Event<ExecutionStatusEvent>> followDependenciesExecutions(
@Parameter(description = "The execution id") @PathVariable String executionId,
@Parameter(description = "If true, list only destination dependencies, otherwise list also source dependencies") @QueryValue(defaultValue = "false") boolean destinationOnly,

View File

@@ -46,6 +46,7 @@ import io.micronaut.validation.Validated;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
@@ -222,7 +223,7 @@ public class FlowController {
@Parameter(description = "The current page") @QueryValue(defaultValue = "1") @Min(1) int page,
@Parameter(description = "The current page size") @QueryValue(defaultValue = "10") @Min(1) int size,
@Parameter(description = "The sort of current page") @Nullable @QueryValue List<String> sort,
@Parameter(description = "Filters") @QueryFilterFormat() List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat() List<QueryFilter> filters,
// Deprecated params
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include", deprecated = true) @Nullable @QueryValue List<FlowScope> scope,
@@ -277,7 +278,7 @@ public class FlowController {
*/
@ExecuteOn(TaskExecutors.IO)
@Post(consumes = MediaType.ALL)
@Operation(tags = {"Flows"}, summary = "Create a flow from json object", deprecated = true)
@Operation(tags = {"Flows"}, summary = "Create a flow from json object", deprecated = true, hidden = true)
@Deprecated(forRemoval = true, since = "0.18")
@Hidden // we hide it otherwise this is the one that will be included in the OpenAPI spec instead of the YAML one.
public HttpResponse<Flow> createFlowFromJson(
@@ -334,7 +335,8 @@ public class FlowController {
summary = "Update a complete namespace from json object",
description = "All flow will be created / updated for this namespace.\n" +
"Flow that already created but not in `flows` will be deleted if the query delete is `true`",
deprecated = true
deprecated = true,
hidden = true
)
@Deprecated(forRemoval = true, since = "0.18")
@Hidden // we hide it otherwise this is the one that will be included in the OpenAPI spec instead of the YAML one.
@@ -437,7 +439,7 @@ public class FlowController {
@Put(uri = "{namespace}/{id}", consumes = MediaType.APPLICATION_YAML)
@ExecuteOn(TaskExecutors.IO)
@Operation(tags = {"Flows"}, summary = "Update a flow")
@Operation(tags = {"Flows"}, summary = "Update a flow")// force deprecated = false otherwise it is marked as deprecated, dont know why
@ApiResponse(responseCode = "200", description = "On success", content = {@Content(schema = @Schema(implementation = FlowWithSource.class))})
public HttpResponse<FlowWithSource> updateFlow(
@Parameter(description = "The flow namespace") @PathVariable String namespace,
@@ -476,9 +478,9 @@ public class FlowController {
/**
* @deprecated use {@link #updateFlow(String, String, String)} instead
*/
@Put(uri = "{namespace}/{id}", consumes = MediaType.ALL)
@Put(uri = "{namespace}/{id}", consumes = MediaType.APPLICATION_JSON)
@ExecuteOn(TaskExecutors.IO)
@Operation(tags = {"Flows"}, summary = "Update a flow", deprecated = true)
@Operation(tags = {"Flows"}, operationId = "updateFlowFromJson", summary = "Update a flow", deprecated = true, hidden = true)
@Deprecated(forRemoval = true, since = "0.18")
@Hidden // we hide it otherwise this is the one that will be included in the OpenAPI spec instead of the JSON one.
public HttpResponse<Flow> updateFlowFromJson(
@@ -666,7 +668,7 @@ public class FlowController {
@Post(uri = "/validate/task", consumes = MediaType.APPLICATION_YAML)
@Operation(tags = {"Flows"}, summary = "Validate a task")
public ValidateConstraintViolation validateTask(
@RequestBody(description = "A task definition that can be from tasks or triggers") @Body String task,
@RequestBody(description = "A task definition that can be from tasks or triggers") @Schema(implementation = Object.class) @Body String task,
@Parameter(description = "The type of task") @QueryValue TaskValidationType section
) {
ValidateConstraintViolation.ValidateConstraintViolationBuilder<?, ?> validateConstraintViolationBuilder = ValidateConstraintViolation.builder();
@@ -703,12 +705,12 @@ public class FlowController {
summary = "Export flows as a ZIP archive of yaml sources."
)
public HttpResponse<byte[]> exportFlowsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat() List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat() List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include") @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include", deprecated = true) @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels
) throws IOException {
filters = mapLegacyQueryParamsToNewFilters(filters, query, scope, namespace, labels);
@@ -741,12 +743,12 @@ public class FlowController {
summary = "Delete flows returned by the query parameters."
)
public HttpResponse<BulkResponse> deleteFlowsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat() List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include") @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include", deprecated = true) @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels
) {
filters = mapLegacyQueryParamsToNewFilters(filters, query, scope, namespace, labels);
@@ -784,12 +786,12 @@ public class FlowController {
summary = "Disable flows returned by the query parameters."
)
public HttpResponse<BulkResponse> disableFlowsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat() List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat() List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include") @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include", deprecated = true) @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels
) {
filters = mapLegacyQueryParamsToNewFilters(filters, query, scope, namespace, labels);
@@ -816,12 +818,12 @@ public class FlowController {
summary = "Enable flows returned by the query parameters."
)
public HttpResponse<BulkResponse> enableFlowsByQuery(
@Parameter(description = "Filters") @QueryFilterFormat() List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat() List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include") @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "The scope of the flows to include", deprecated = true) @Nullable @QueryValue List<FlowScope> scope,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A labels filter as a list of 'key:value'", deprecated = true) @Nullable @QueryValue @Format("MULTI") List<String> labels
) {
filters = mapLegacyQueryParamsToNewFilters(filters, query, scope, namespace, labels);

View File

@@ -122,7 +122,7 @@ public class KVController {
}
@ExecuteOn(TaskExecutors.IO)
@Put(uri = "/namespaces/{namespace}/kv/{key}", consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
@Put(uri = "/namespaces/{namespace}/kv/{key}", consumes = {MediaType.TEXT_PLAIN})
@Operation(tags = {"KV"}, summary = "Puts a key-value pair in store")
public void setKeyValue(
HttpHeaders httpHeaders,

View File

@@ -27,6 +27,7 @@ import io.micronaut.scheduling.annotation.ExecuteOn;
import io.micronaut.validation.Validated;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import jakarta.inject.Inject;
import jakarta.validation.constraints.Min;
import org.slf4j.event.Level;
@@ -66,7 +67,7 @@ public class LogController {
@Parameter(description = "The current page") @QueryValue(defaultValue = "1") @Min(1) int page,
@Parameter(description = "The current page size") @QueryValue(defaultValue = "10") @Min(1) int size,
@Parameter(description = "The sort of current page") @Nullable @QueryValue List<String> sort,
@Parameter(description = "Filters") @Nullable @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @Nullable @QueryFilterFormat List<QueryFilter> filters,
// Deprecated params
@Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Parameter(description = "A namespace filter prefix",deprecated = true) @Nullable @QueryValue String namespace,

View File

@@ -19,6 +19,7 @@ import io.micronaut.scheduling.annotation.ExecuteOn;
import io.micronaut.validation.Validated;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import jakarta.inject.Inject;
import java.io.IOException;
@@ -45,7 +46,7 @@ public class NamespaceSecretController<META extends ApiSecretMeta> {
@Parameter(description = "The current page") @QueryValue(value = "page", defaultValue = "1") int page,
@Parameter(description = "The current page size") @QueryValue(value = "size", defaultValue = "10") int size,
@Parameter(description = "The sort of current page") @Nullable @QueryValue(value = "sort") List<String> sort,
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters
) throws IllegalArgumentException, IOException {
final String tenantId = this.tenantService.resolveTenant();
List<String> items = secretService.inheritedSecrets(tenantId, namespace).get(namespace).stream().toList();

View File

@@ -32,6 +32,7 @@ import io.micronaut.scheduling.annotation.ExecuteOn;
import io.micronaut.validation.Validated;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
@@ -82,7 +83,7 @@ public class TriggerController {
@Parameter(description = "The current page") @QueryValue(defaultValue = "1") @Min(1) int page,
@Parameter(description = "The current page size") @QueryValue(defaultValue = "10") @Min(1) int size,
@Parameter(description = "The sort of current page") @Nullable @QueryValue List<String> sort,
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
// Deprecated params
@Parameter(description = "A string filter",deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@@ -205,10 +206,10 @@ public class TriggerController {
@Post(uri = "/unlock/by-query")
@Operation(tags = {"Triggers"}, summary = "Unlock triggers by query parameters")
public MutableHttpResponse<?> unlockTriggersByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace
) {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -280,13 +281,13 @@ public class TriggerController {
if (abstractTrigger == null) {
throw new HttpStatusException(HttpStatus.NOT_FOUND, String.format("Flow %s has no trigger %s", newTrigger.getFlowId(), newTrigger.getTriggerId()));
}
if (abstractTrigger instanceof RealtimeTriggerInterface) {
throw new IllegalArgumentException("Realtime triggers can not be updated through the API, please edit the trigger from the flow.");
}
Trigger updatedTrigger;
if (newTrigger.getBackfill() != null) {
try {
updatedTrigger = setTriggerBackfill(newTrigger, maybeFlow.get(), abstractTrigger);
@@ -296,13 +297,13 @@ public class TriggerController {
} else {
updatedTrigger = setTriggerDisabled(newTrigger.uid(), newTrigger.getDisabled(), abstractTrigger, maybeFlow.get());
}
if (updatedTrigger == null) {
return HttpResponse.notFound();
}
return HttpResponse.ok(updatedTrigger);
}
@ExecuteOn(TaskExecutors.IO)
@Post(uri = "/{namespace}/{flowId}/{triggerId}/restart")
@Operation(tags = {"Triggers"}, summary = "Restart a trigger")
@@ -369,10 +370,10 @@ public class TriggerController {
@Post(uri = "/backfill/pause/by-query")
@Operation(tags = {"Triggers"}, summary = "Pause backfill for given triggers")
public MutableHttpResponse<?> pauseBackfillByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace
) throws QueueException {
// Updating the backfill within the flux does not works
List<Trigger> triggers = triggerRepository
@@ -408,10 +409,10 @@ public class TriggerController {
@Post(uri = "/backfill/unpause/by-query")
@Operation(tags = {"Triggers"}, summary = "Unpause backfill for given triggers")
public MutableHttpResponse<?> unpauseBackfillByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace
) throws QueueException {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -477,10 +478,10 @@ public class TriggerController {
@Post(uri = "/backfill/delete/by-query")
@Operation(tags = {"Triggers"}, summary = "Delete backfill for given triggers")
public MutableHttpResponse<?> deleteBackfillByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace
) throws QueueException {
filters = RequestUtils.getFiltersOrDefaultToLegacyMapping(
filters,
@@ -521,10 +522,10 @@ public class TriggerController {
@Post(uri = "/set-disabled/by-query")
@Operation(tags = {"Triggers"}, summary = "Disable/enable triggers by query parameters")
public MutableHttpResponse<?> disabledTriggersByQuery(
@Parameter(description = "Filters") @QueryFilterFormat List<QueryFilter> filters,
@Parameter(description = "Filters", in = ParameterIn.QUERY) @QueryFilterFormat List<QueryFilter> filters,
@Deprecated @Parameter(description = "A string filter") @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix") @Nullable @QueryValue String namespace,
@Deprecated @Parameter(description = "A string filter", deprecated = true) @Nullable @QueryValue(value = "q") String query,
@Deprecated @Parameter(description = "A namespace filter prefix", deprecated = true) @Nullable @QueryValue String namespace,
@Parameter(description = "The disabled state") @QueryValue(defaultValue = "true") Boolean disabled
) throws QueueException {
@@ -557,24 +558,24 @@ public class TriggerController {
public void setTriggerDisabled(Trigger trigger, Boolean disabled) throws QueueException {
Optional<Flow> maybeFlow = this.flowRepository.findById(this.tenantService.resolveTenant(), trigger.getNamespace(), trigger.getFlowId());
if (maybeFlow.isEmpty()) {
return; // Flow doesn't exist
}
Optional<AbstractTrigger> maybeAbstractTrigger = maybeFlow.flatMap(flow -> flow.getTriggers().stream().filter(t -> t.getId().equals(trigger.getTriggerId())).findFirst());
if (maybeAbstractTrigger.isEmpty()) {
return; // Trigger doesn't exist
}
if (maybeAbstractTrigger.get() instanceof RealtimeTriggerInterface) {
return; // RealTimeTriggers can't be disabled/enabled through API.
}
setTriggerDisabled(trigger.uid(), disabled, maybeAbstractTrigger.get(), maybeFlow.get());
}
private Trigger setTriggerDisabled(String triggerUID, Boolean disabled, AbstractTrigger triggerDefinition, Flow flow) throws QueueException {
return this.triggerRepository.lock(triggerUID, throwFunction(current -> {
if (disabled.equals(current.getDisabled())) {
@@ -583,46 +584,46 @@ public class TriggerController {
return doSetTriggerDisabled(current, disabled, flow, triggerDefinition);
}));
}
private Trigger setTriggerBackfill(Trigger newTrigger, Flow flow, AbstractTrigger abstractTrigger) throws Exception {
return this.triggerRepository.lock(newTrigger.uid(), throwFunction(current -> doSetTriggerBackfill(current, newTrigger.getBackfill(), flow, abstractTrigger)));
}
protected Trigger doSetTriggerDisabled(Trigger currentState, Boolean disabled, Flow flow, AbstractTrigger trigger) throws QueueException {
Trigger.TriggerBuilder<?, ?> builder = currentState.toBuilder().disabled(disabled);
if (disabled) {
builder = builder.nextExecutionDate(null);
}
Trigger updated = builder.build();
triggerQueue.emit(updated);
return updated;
}
protected Trigger doSetTriggerBackfill(Trigger currentState, Backfill backfill, Flow flow, AbstractTrigger trigger) throws Exception {
Trigger updated;
ZonedDateTime nextExecutionDate = null;
RunContext runContext = runContextFactory.of(flow, trigger);
ConditionContext conditionContext = conditionService.conditionContext(runContext, flow, null);
// We must set up the backfill before the update to calculate the next execution date
updated = currentState.withBackfill(backfill);
if (trigger instanceof PollingTriggerInterface pollingTriggerInterface) {
nextExecutionDate = pollingTriggerInterface.nextEvaluationDate(conditionContext, Optional.of(updated));
}
updated = updated
.toBuilder()
.nextExecutionDate(nextExecutionDate)
.build();
triggerQueue.emit(updated);
return updated;
}
public int backfillsAction(List<Trigger> triggers, BACKFILL_ACTION action) throws QueueException {
AtomicInteger count = new AtomicInteger();
triggers.forEach(throwConsumer(trigger -> {

View File

@@ -24,7 +24,7 @@ import io.kestra.core.repositories.FlowRepositoryInterface;
import io.kestra.core.runners.FlowInputOutput;
import io.kestra.core.runners.InputsTest;
import io.kestra.core.runners.LocalPath;
import io.kestra.core.runners.RunnerUtils;
import io.kestra.core.runners.TestRunnerUtils;
import io.kestra.core.serializers.JacksonMapper;
import io.kestra.core.storages.StorageContext;
import io.kestra.core.storages.StorageInterface;
@@ -121,7 +121,7 @@ class ExecutionControllerRunnerTest {
private JdbcTestUtils jdbcTestUtils;
@Inject
protected RunnerUtils runnerUtils;
protected TestRunnerUtils runnerUtils;
@Inject
private StorageInterface storageInterface;
@@ -412,30 +412,30 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Run child execution starting from a specific task and wait until it finishes
Thread.sleep(100);
Execution createdChidExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), ImmutableMap.of()),
Execution.class
);
assertThat(createdChidExec).isNotNull();
assertThat(createdChidExec.getParentId()).isEqualTo(parentExecution.getId());
assertThat(createdChidExec.getTaskRunList().size()).isEqualTo(4);
assertThat(createdChidExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 3)
.mapToObj(value -> createdChidExec.getTaskRunList().get(value))
.forEach(taskRun -> assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS));
assertThat(createdChidExec.getTaskRunList().get(3).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(createdChidExec.getTaskRunList().get(3).getAttempts().size()).isEqualTo(1);
Execution finishedChildExecution = runnerUtils.awaitChildExecution(
flow.get(),
parentExecution, throwRunnable(() -> {
Thread.sleep(100);
Execution createdChidExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), ImmutableMap.of()),
Execution.class
);
assertThat(createdChidExec).isNotNull();
assertThat(createdChidExec.getParentId()).isEqualTo(parentExecution.getId());
assertThat(createdChidExec.getTaskRunList().size()).isEqualTo(4);
assertThat(createdChidExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 3)
.mapToObj(value -> createdChidExec.getTaskRunList().get(value))
.forEach(taskRun -> assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS));
assertThat(createdChidExec.getTaskRunList().get(3).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(createdChidExec.getTaskRunList().get(3).getAttempts().size()).isEqualTo(1);
}),
parentExecution,
createdChidExec,
Duration.ofSeconds(15));
assertThat(finishedChildExecution).isNotNull();
@@ -465,26 +465,26 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Run child execution starting from a specific task and wait until it finishes
Thread.sleep(100);
MultipartBody multipartBody = MultipartBody.builder()
.addPart("condition", "success")
.build();
Execution replay = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay-with-inputs", multipartBody)
.contentType(MediaType.MULTIPART_FORM_DATA_TYPE),
Execution.class
);
assertThat(replay).isNotNull();
assertThat(replay.getParentId()).isEqualTo(parentExecution.getId());
assertThat(replay.getState().getCurrent()).isEqualTo(Type.CREATED);
Execution finishedChildExecution = runnerUtils.awaitChildExecution(
flow.get(),
parentExecution, throwRunnable(() -> {
Thread.sleep(100);
MultipartBody multipartBody = MultipartBody.builder()
.addPart("condition", "success")
.build();
Execution replay = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay-with-inputs", multipartBody)
.contentType(MediaType.MULTIPART_FORM_DATA_TYPE),
Execution.class
);
assertThat(replay).isNotNull();
assertThat(replay.getParentId()).isEqualTo(parentExecution.getId());
assertThat(replay.getState().getCurrent()).isEqualTo(Type.CREATED);
}),
parentExecution,
replay,
Duration.ofSeconds(15));
assertThat(finishedChildExecution).isNotNull();
@@ -515,27 +515,27 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Run child execution starting from a specific task and wait until it finishes
Thread.sleep(100);
MultipartBody multipartBody = MultipartBody.builder()
.addPart("condition", "success")
.build();
Execution replay = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay-with-inputs?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), multipartBody)
.contentType(MediaType.MULTIPART_FORM_DATA_TYPE),
Execution.class
);
assertThat(replay).isNotNull();
assertThat(replay.getParentId()).isEqualTo(parentExecution.getId());
assertThat(replay.getTaskRunList().size()).isEqualTo(2);
assertThat(replay.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
Execution finishedChildExecution = runnerUtils.awaitChildExecution(
flow.get(),
parentExecution, throwRunnable(() -> {
Thread.sleep(100);
MultipartBody multipartBody = MultipartBody.builder()
.addPart("condition", "success")
.build();
Execution replay = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay-with-inputs?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), multipartBody)
.contentType(MediaType.MULTIPART_FORM_DATA_TYPE),
Execution.class
);
assertThat(replay).isNotNull();
assertThat(replay.getParentId()).isEqualTo(parentExecution.getId());
assertThat(replay.getTaskRunList().size()).isEqualTo(2);
assertThat(replay.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
}),
parentExecution,
replay,
Duration.ofSeconds(15));
assertThat(finishedChildExecution).isNotNull();
@@ -563,23 +563,23 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Run child execution starting from a specific task and wait until it finishes
Thread.sleep(100);
Execution createdChidExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), ImmutableMap.of()),
Execution.class
);
assertThat(createdChidExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(createdChidExec.getState().getHistories()).hasSize(4);
assertThat(createdChidExec.getTaskRunList()).hasSize(20);
assertThat(createdChidExec.getId()).isNotEqualTo(parentExecution.getId());
runnerUtils.awaitChildExecution(
flow.get(),
parentExecution, throwRunnable(() -> {
Thread.sleep(100);
Execution createdChidExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + parentExecution.getId() + "/replay?taskRunId=" + parentExecution.findTaskRunByTaskIdAndValue(referenceTaskId, List.of()).getId(), ImmutableMap.of()),
Execution.class
);
assertThat(createdChidExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(createdChidExec.getState().getHistories()).hasSize(4);
assertThat(createdChidExec.getTaskRunList()).hasSize(20);
assertThat(createdChidExec.getId()).isNotEqualTo(parentExecution.getId());
}),
parentExecution,
createdChidExec,
Duration.ofSeconds(30));
}
@@ -599,33 +599,31 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Restart execution and wait until it finishes
Execution restartedExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + firstExecution.getId() + "/restart", ImmutableMap.of()),
Execution.class
);
assertThat(restartedExec).isNotNull();
assertThat(restartedExec.getId()).isEqualTo(firstExecution.getId());
assertThat(restartedExec.getParentId()).isNull();
assertThat(restartedExec.getTaskRunList().size()).isEqualTo(3);
assertThat(restartedExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 2)
.mapToObj(value -> restartedExec.getTaskRunList().get(value)).forEach(taskRun -> {
assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS);
assertThat(taskRun.getAttempts().size()).isEqualTo(1);
assertThat(restartedExec.getTaskRunList().get(2).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(restartedExec.getTaskRunList().get(2).getAttempts().size()).isEqualTo(1);
});
Execution finishedRestartedExecution = runnerUtils.awaitExecution(
execution -> execution.getId().equals(firstExecution.getId()) &&
execution.getTaskRunList().size() == 4 &&
execution.getState().isTerminated(),
() -> {
Execution restartedExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + firstExecution.getId() + "/restart", ImmutableMap.of()),
Execution.class
);
assertThat(restartedExec).isNotNull();
assertThat(restartedExec.getId()).isEqualTo(firstExecution.getId());
assertThat(restartedExec.getParentId()).isNull();
assertThat(restartedExec.getTaskRunList().size()).isEqualTo(3);
assertThat(restartedExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 2)
.mapToObj(value -> restartedExec.getTaskRunList().get(value)).forEach(taskRun -> {
assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS);
assertThat(taskRun.getAttempts().size()).isEqualTo(1);
assertThat(restartedExec.getTaskRunList().get(2).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(restartedExec.getTaskRunList().get(2).getAttempts().size()).isEqualTo(1);
});
},
execution -> execution.getTaskRunList().size() == 4 && execution.getState().isTerminated(),
restartedExec,
Duration.ofSeconds(15)
);
@@ -662,35 +660,33 @@ class ExecutionControllerRunnerTest {
assertThat(flow.isPresent()).isTrue();
// Restart execution and wait until it finishes
Execution restartedExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + firstExecution.getId() + "/restart", ImmutableMap.of()),
Execution.class
);
assertThat(restartedExec).isNotNull();
assertThat(restartedExec.getId()).isEqualTo(firstExecution.getId());
assertThat(restartedExec.getParentId()).isNull();
assertThat(restartedExec.getTaskRunList().size()).isEqualTo(4);
assertThat(restartedExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 2)
.mapToObj(value -> restartedExec.getTaskRunList().get(value)).forEach(taskRun -> {
assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS);
assertThat(taskRun.getAttempts().size()).isEqualTo(1);
assertThat(restartedExec.getTaskRunList().get(2).getState().getCurrent()).isEqualTo(State.Type.RUNNING);
assertThat(restartedExec.getTaskRunList().get(3).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(restartedExec.getTaskRunList().get(2).getAttempts()).isNotNull();
assertThat(restartedExec.getTaskRunList().get(3).getAttempts().size()).isEqualTo(1);
});
Execution finishedRestartedExecution = runnerUtils.awaitExecution(
execution -> execution.getId().equals(firstExecution.getId()) &&
execution.getTaskRunList().size() == 5 &&
execution.getState().isTerminated(),
() -> {
Execution restartedExec = client.toBlocking().retrieve(
HttpRequest
.POST("/api/v1/main/executions/" + firstExecution.getId() + "/restart", ImmutableMap.of()),
Execution.class
);
assertThat(restartedExec).isNotNull();
assertThat(restartedExec.getId()).isEqualTo(firstExecution.getId());
assertThat(restartedExec.getParentId()).isNull();
assertThat(restartedExec.getTaskRunList().size()).isEqualTo(4);
assertThat(restartedExec.getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
IntStream
.range(0, 2)
.mapToObj(value -> restartedExec.getTaskRunList().get(value)).forEach(taskRun -> {
assertThat(taskRun.getState().getCurrent()).isEqualTo(State.Type.SUCCESS);
assertThat(taskRun.getAttempts().size()).isEqualTo(1);
assertThat(restartedExec.getTaskRunList().get(2).getState().getCurrent()).isEqualTo(State.Type.RUNNING);
assertThat(restartedExec.getTaskRunList().get(3).getState().getCurrent()).isEqualTo(State.Type.RESTARTED);
assertThat(restartedExec.getTaskRunList().get(2).getAttempts()).isNotNull();
assertThat(restartedExec.getTaskRunList().get(3).getAttempts().size()).isEqualTo(1);
});
},
execution -> execution.getTaskRunList().size() == 5 && execution.getState().isTerminated(),
restartedExec,
Duration.ofSeconds(15)
);
@@ -1748,7 +1744,7 @@ class ExecutionControllerRunnerTest {
void shouldUnqueueExecutionAQueuedFlow() throws QueueException, TimeoutException {
// run a first flow so the second is queued
runnerUtils.runOneUntilRunning(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
var response = client.toBlocking().exchange(HttpRequest.POST("/api/v1/main/executions/" + result.getId() + "/unqueue", null));
assertThat(response.getStatus().getCode()).isEqualTo(HttpStatus.OK.getCode());
@@ -1756,7 +1752,7 @@ class ExecutionControllerRunnerTest {
// waiting for the flow to complete successfully
runnerUtils.awaitExecution(
execution -> execution.getId().equals(result.getId()) && execution.getState().isSuccess(),
() -> {},
result,
Duration.ofSeconds(10)
);
@@ -1777,7 +1773,7 @@ class ExecutionControllerRunnerTest {
void shouldUnqueueAQueuedFlowToCancelledState() throws QueueException, TimeoutException {
// run a first flow so the second is queued
runnerUtils.runOneUntilRunning(TENANT_ID, "io.kestra.tests", "flow-concurrency-queue");
Execution result1 = runUntilQueued("io.kestra.tests", "flow-concurrency-queue");
Execution result1 = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
var cancelResponse = client.toBlocking().exchange(
HttpRequest.POST("/api/v1/executions/" + result1.getId() + "/unqueue?state=CANCELLED", null)
@@ -1794,9 +1790,9 @@ class ExecutionControllerRunnerTest {
void shouldUnqueueExecutionByIdsQueuedFlows() throws TimeoutException, QueueException {
// run a first flow so the others are queued
runnerUtils.runOneUntilRunning(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result1 = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result2 = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result3 = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result1 = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
Execution result2 = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
Execution result3 = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
BulkResponse response = client.toBlocking().retrieve(
HttpRequest.POST("/api/v1/main/executions/unqueue/by-ids", List.of(result1.getId(), result2.getId(), result3.getId())),
@@ -1810,7 +1806,7 @@ class ExecutionControllerRunnerTest {
void shouldForceRunExecutionAQueuedFlow() throws QueueException, TimeoutException {
// run a first flow so the second is queued
runnerUtils.runOneUntilRunning(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runUntilQueued(TESTS_FLOW_NS, "flow-concurrency-queue");
Execution result = runnerUtils.runOneUntil(TENANT_ID, TESTS_FLOW_NS, "flow-concurrency-queue", exec -> exec.getState().isQueued());
var response = client.toBlocking().exchange(HttpRequest.POST("/api/v1/main/executions/" + result.getId() + "/force-run", null));
assertThat(response.getStatus().getCode()).isEqualTo(HttpStatus.OK.getCode());
@@ -1821,7 +1817,7 @@ class ExecutionControllerRunnerTest {
// waiting for the flow to complete successfully
runnerUtils.awaitExecution(
execution -> execution.getId().equals(result.getId()) && execution.getState().isSuccess(),
() -> {},
result,
Duration.ofSeconds(10)
);
}
@@ -2021,22 +2017,11 @@ class ExecutionControllerRunnerTest {
.build();
}
private Execution runUntilQueued(String namespace, String flowId) throws TimeoutException, QueueException {
return runUntilState(namespace, flowId, State.Type.QUEUED);
}
private Execution createExecution(String namespace, String flowId) {
Flow flow = flowRepositoryInterface.findById(TENANT_ID, namespace, flowId).orElseThrow();
return Execution.newExecution(flow, null);
}
private Execution runUntilState(String namespace, String flowId, State.Type state) throws TimeoutException, QueueException {
Execution execution = this.createExecution(namespace, flowId);
return runnerUtils.awaitExecution(
it -> execution.getId().equals(it.getId()) && it.getState().getCurrent() == state,
throwRunnable(() -> this.executionQueue.emit(execution)),
Duration.ofSeconds(1));
}
@Test
@LoadFlows({"flows/valids/minimal.yaml"})
@@ -2113,7 +2098,7 @@ class ExecutionControllerRunnerTest {
// wait for the exec to be terminated
Execution terminated = runnerUtils.awaitExecution(
it -> execution.getId().equals(it.getId()) && it.getState().isTerminated(),
() -> {},
execution,
Duration.ofSeconds(10));
assertThat(terminated.getState().getCurrent()).isEqualTo(State.Type.SUCCESS);
assertThat(terminated.getTaskRunList()).hasSize(1);

View File

@@ -1,9 +1,5 @@
package io.kestra.webserver.controllers.api;
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.within;
import io.kestra.core.exceptions.ResourceExpiredException;
import io.kestra.core.junit.annotations.KestraTest;
import io.kestra.core.models.kv.KVType;
@@ -26,6 +22,14 @@ import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.reactor.http.client.ReactorHttpClient;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
@@ -39,12 +43,9 @@ import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static io.kestra.core.tenant.TenantService.MAIN_TENANT;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.within;
@KestraTest(resolveParameters = false)
class KVControllerTest {
@@ -201,16 +202,16 @@ class KVControllerTest {
static Stream<Arguments> kvSetKeyValueArgs() {
return Stream.of(
Arguments.of(MediaType.APPLICATION_JSON, "{\"hello\":\"world\"}", Map.class),
Arguments.of(MediaType.APPLICATION_JSON, "[\"hello\",\"world\"]", List.class),
Arguments.of(MediaType.APPLICATION_JSON, "\"hello\"", String.class),
Arguments.of(MediaType.APPLICATION_JSON, "1", Integer.class),
Arguments.of(MediaType.APPLICATION_JSON, "1.0", BigDecimal.class),
Arguments.of(MediaType.APPLICATION_JSON, "true", Boolean.class),
Arguments.of(MediaType.APPLICATION_JSON, "false", Boolean.class),
Arguments.of(MediaType.APPLICATION_JSON, "2021-09-01", LocalDate.class),
Arguments.of(MediaType.APPLICATION_JSON, "2021-09-01T01:02:03Z", Instant.class),
Arguments.of(MediaType.APPLICATION_JSON, "\"PT5S\"", Duration.class)
Arguments.of(MediaType.TEXT_PLAIN, "{\"hello\":\"world\"}", Map.class),
Arguments.of(MediaType.TEXT_PLAIN, "[\"hello\",\"world\"]", List.class),
Arguments.of(MediaType.TEXT_PLAIN, "\"hello\"", String.class),
Arguments.of(MediaType.TEXT_PLAIN, "1", Integer.class),
Arguments.of(MediaType.TEXT_PLAIN, "1.0", BigDecimal.class),
Arguments.of(MediaType.TEXT_PLAIN, "true", Boolean.class),
Arguments.of(MediaType.TEXT_PLAIN, "false", Boolean.class),
Arguments.of(MediaType.TEXT_PLAIN, "2021-09-01", LocalDate.class),
Arguments.of(MediaType.TEXT_PLAIN, "2021-09-01T01:02:03Z", Instant.class),
Arguments.of(MediaType.TEXT_PLAIN, "\"PT5S\"", Duration.class)
);
}
@@ -293,7 +294,7 @@ class KVControllerTest {
assertThat(httpClientResponseException.getStatus().getCode()).isEqualTo(HttpStatus.UNPROCESSABLE_ENTITY.getCode());
assertThat(httpClientResponseException.getMessage()).isEqualTo(expectedErrorMessage);
httpClientResponseException = Assertions.assertThrows(HttpClientResponseException.class, () -> client.toBlocking().exchange(HttpRequest.PUT("/api/v1/main/namespaces/" + NAMESPACE + "/kv/bad$key", "\"content\"").contentType(MediaType.APPLICATION_JSON)));
httpClientResponseException = Assertions.assertThrows(HttpClientResponseException.class, () -> client.toBlocking().exchange(HttpRequest.PUT("/api/v1/main/namespaces/" + NAMESPACE + "/kv/bad$key", "\"content\"").contentType(MediaType.TEXT_PLAIN)));
assertThat(httpClientResponseException.getStatus().getCode()).isEqualTo(HttpStatus.UNPROCESSABLE_ENTITY.getCode());
assertThat(httpClientResponseException.getMessage()).isEqualTo(expectedErrorMessage);