> jsonPathReplacement = jsonPathExtractor.extract(value);
- if (!payloadArgument.getSourceType().isMergeAllowed()
- && jsonPathReplacement.isEmpty()) {
- throw JsonPathReplacementException.noJsonPathFoundException(value);
- }
-
- return jsonPathReplacement.orElse(Pair.of(null, value));
- }
-
- private DocumentContext merge(DocumentContext documentContext, JsonPath jsonPath,
- JsonNode replacement, String value) {
- if (jsonPath != null) {
- documentContext = mergeJsonPath(documentContext, jsonPath, replacement);
- } else {
- documentContext = mergeRoot(documentContext, replacement, value);
- }
- return documentContext;
- }
-
- private DocumentContext mergeRoot(DocumentContext documentContext, JsonNode replacement,
- String value) {
- JsonNode currentJsonNode = documentContext.json();
- JsonNode merged;
- try {
- merged = mergeNewValueWithOldValue(currentJsonNode, replacement);
- } catch (JsonProcessingException e) {
- throw PayloadException.genericJsonProcessingException(e, value);
- }
-
- documentContext = JsonPath.parse(merged);
- return documentContext;
- }
-
- private DocumentContext mergeJsonPath(DocumentContext documentContext, JsonPath jsonPath,
- JsonNode replacement) {
- try {
- JsonNode currentJsonNode = documentContext.read(jsonPath);
- replacement = mergeNewValueWithOldValue(currentJsonNode, replacement);
- } catch (JsonProcessingException e) {
- throw PayloadException.genericJsonProcessingException(e, replacement.toString());
- }
-
- try {
- documentContext = documentContext.set(jsonPath, replacement);
- } catch (PathNotFoundException e) {
- throw JsonPathReplacementException.pathNotFoundException(jsonPath);
- }
- return documentContext;
- }
-
- private JsonNode mergeNewValueWithOldValue(JsonNode jsonNode, JsonNode replacement)
- throws JsonProcessingException {
- if (replacement.isObject() && jsonNode != null) {
- return objectMapper
- .readerForUpdating(jsonNode)
- .readTree(replacement.toString());
- }
- return replacement;
- }
-
- private JsonNode extractPayloadFragment(SourceType sourceType, String replacementSource,
- JsonPath jsonPath) {
- try {
- return extractPayloadFragment(sourceType, replacementSource);
- } catch (JsonParseException exception) {
- if (jsonPath != null) {
- throw JsonPathReplacementException.jsonParseException(exception, jsonPath,
- replacementSource);
- } else {
- throw PayloadException.jsonParseException(exception, replacementSource);
- }
- } catch (JsonProcessingException exception) {
- throw JsonPathReplacementException.genericJsonProcessingException(exception, jsonPath,
- replacementSource);
- } catch (IOException e) {
- throw PayloadException.ioException(e);
- }
- }
-
- private JsonNode extractPayloadFragment(SourceType sourceType, String replacementSource)
- throws IOException {
- RawPayload rawPayload = sourceResolver.resolve(replacementSource);
-
- return typedPayloadFragmentResolver.resolveFragment(rawPayload, sourceType).jsonNode();
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/PropertyCreatingJacksonJsonNodeJsonProvider.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/PropertyCreatingJacksonJsonNodeJsonProvider.java
deleted file mode 100644
index 0653e8a5..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/PropertyCreatingJacksonJsonNodeJsonProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
-
-/**
- * This implementation of JsonProvider creating new json objects if
- * json properties on JSONPath expressions are not available.
- *
- *
- * Solution inspired by:
- * this comment
- */
-public class PropertyCreatingJacksonJsonNodeJsonProvider extends JacksonJsonNodeJsonProvider {
- public PropertyCreatingJacksonJsonNodeJsonProvider(ObjectMapper objectMapper) {
- super(objectMapper);
- }
-
- @Override
- public Object getMapValue(Object obj, String key) {
- Object o = super.getMapValue(obj, key);
- if (o == UNDEFINED) {
- ObjectNode newChild = objectMapper.createObjectNode();
- if (obj instanceof ObjectNode objectNode) {
- objectNode.set(key, newChild);
- }
- return newChild;
- } else {
- return o;
- }
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/ExactSourceResolver.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/ExactSourceResolver.java
deleted file mode 100644
index 86e251fb..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/ExactSourceResolver.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.source;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import java.nio.charset.StandardCharsets;
-
-@ApplicationScoped
-public class ExactSourceResolver {
-
- RawPayload resolve(String rawSource) {
- byte[] result = rawSource.getBytes(StandardCharsets.UTF_8);
- return new RawPayload(result);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/FileSourceResolver.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/FileSourceResolver.java
deleted file mode 100644
index afd5d7b1..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/FileSourceResolver.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.source;
-
-import dev.streamx.cli.util.FileSourceUtils;
-import jakarta.enterprise.context.ApplicationScoped;
-
-@ApplicationScoped
-public class FileSourceResolver {
-
- boolean applies(String rawSource) {
- return FileSourceUtils.applies(rawSource);
- }
-
- RawPayload resolve(String rawSource) {
- return new RawPayload(FileSourceUtils.resolve(rawSource));
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/RawPayload.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/RawPayload.java
deleted file mode 100644
index 5aa495e2..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/RawPayload.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.source;
-
-public record RawPayload(byte[] source) {
-
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/SourceResolver.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/SourceResolver.java
deleted file mode 100644
index 7451ecd7..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/source/SourceResolver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.source;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-
-@ApplicationScoped
-public class SourceResolver {
-
- @Inject
- FileSourceResolver fileSourceResolver;
-
- @Inject
- ExactSourceResolver exactSourceResolver;
-
- public RawPayload resolve(String rawSource) {
- if (fileSourceResolver.applies(rawSource)) {
- return fileSourceResolver.resolve(rawSource);
- }
-
- return exactSourceResolver.resolve(rawSource);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/SourceType.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/SourceType.java
deleted file mode 100644
index c25a5c78..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/SourceType.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.typed;
-
-public enum SourceType {
- JSON(true),
- STRING(false),
- BINARY(false);
-
- private final boolean mergeAllowed;
-
- SourceType(boolean mergeAllowed) {
- this.mergeAllowed = mergeAllowed;
- }
-
- public boolean isMergeAllowed() {
- return mergeAllowed;
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayload.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayload.java
deleted file mode 100644
index 86291946..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayload.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.typed;
-
-import com.fasterxml.jackson.databind.JsonNode;
-
-public record TypedPayload(JsonNode jsonNode) {
-
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayloadFragmentResolver.java b/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayloadFragmentResolver.java
deleted file mode 100644
index 6284e78e..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/publish/payload/typed/TypedPayloadFragmentResolver.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload.typed;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.TextNode;
-import com.fasterxml.jackson.databind.util.TokenBuffer;
-import dev.streamx.cli.command.ingestion.PayloadProcessing;
-import dev.streamx.cli.command.ingestion.publish.payload.source.RawPayload;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-@ApplicationScoped
-public class TypedPayloadFragmentResolver {
-
- private static final ObjectMapper BINARY_SERIALIZATION_OBJECT_MAPPER = new ObjectMapper();
-
- @Inject
- @PayloadProcessing
- ObjectMapper objectMapper;
-
- public TypedPayload resolveFragment(RawPayload rawPayload, SourceType sourceType)
- throws IOException {
- final byte[] bytes = rawPayload.source();
- return switch (sourceType) {
- case JSON -> new TypedPayload(objectMapper.readTree(bytes));
- case BINARY -> new TypedPayload(toJsonNode(bytes));
- case STRING -> {
- String content = new String(bytes, StandardCharsets.UTF_8);
-
- yield new TypedPayload(TextNode.valueOf(content));
- }
- };
- }
-
- private static JsonNode toJsonNode(byte[] datum) throws IOException {
- if (datum == null) {
- return null;
- }
-
- try (var generator = new TokenBuffer(BINARY_SERIALIZATION_OBJECT_MAPPER, false)) {
- generator.writeString(new String(datum, StandardCharsets.ISO_8859_1));
-
- return BINARY_SERIALIZATION_OBJECT_MAPPER.readTree(generator.asParser());
- }
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamCommand.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamCommand.java
index 0c663b25..74ec9864 100644
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamCommand.java
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamCommand.java
@@ -2,60 +2,65 @@
import static dev.streamx.cli.util.Output.printf;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.streamx.ce.serialization.DeserializerException;
+import com.streamx.ce.serialization.json.CloudEventJsonDeserializer;
+import com.streamx.clients.ingestion.exceptions.StreamxClientException;
+import com.streamx.clients.ingestion.publisher.Publisher;
import dev.streamx.cli.VersionProvider;
import dev.streamx.cli.command.ingestion.BaseIngestionCommand;
+import dev.streamx.cli.command.ingestion.stream.parser.JsonBase64Encoder;
import dev.streamx.cli.command.ingestion.stream.parser.StreamIngestionJsonParser;
import dev.streamx.cli.util.ExceptionUtils;
import dev.streamx.cli.util.FileUtils;
-import dev.streamx.clients.ingestion.exceptions.StreamxClientException;
-import dev.streamx.clients.ingestion.publisher.Publisher;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
+import io.cloudevents.CloudEvent;
import jakarta.inject.Inject;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.List;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
@Command(name = StreamCommand.COMMAND_NAME,
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class,
- description = "Send stream of messages from file"
+ description = "Send stream of events from file"
)
public class StreamCommand extends BaseIngestionCommand {
- public static final String COMMAND_NAME = "stream";
+ // TODO "_v2" is a temporary postfix for now
+ public static final String COMMAND_NAME = "stream_v2";
+
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+ private static final CloudEventJsonDeserializer deserializer = new CloudEventJsonDeserializer();
@ArgGroup(exclusive = false, multiplicity = "1")
StreamIngestionArguments streamIngestionArguments;
+
@Inject
StreamIngestionJsonParser ingestionJsonParser;
@Override
- protected String getChannel() {
- return streamIngestionArguments.getChannel();
- }
-
- @Override
- protected void perform(Publisher publisher) throws StreamxClientException {
+ protected void perform(Publisher publisher) throws StreamxClientException {
Path streamFile = Paths.get(streamIngestionArguments.getSourceFile());
+ List jsonFieldsToEncodeToBase64 = StreamProperties
+ .getJsonFieldsToEncodeToBase64(streamFile);
try (FileInputStream fis = new FileInputStream(streamFile.toFile())) {
- ingestionJsonParser.parse(fis, message -> {
-
- String action = getRequiredProperty(message, "action");
- String key = getRequiredProperty(message, "key");
-
- SuccessResult result = publisher.send(message);
-
- printf("Sent data %s message using stream to '%s' with key '%s' at %d%n",
- action, getChannel(), key, result.getEventTime());
+ ingestionJsonParser.parse(fis, cloudEventNode -> {
+ JsonBase64Encoder.encodeFields(cloudEventNode, jsonFieldsToEncodeToBase64);
+ CloudEvent inputEvent = toCloudEvent(cloudEventNode);
+ CloudEvent responseEvent = publisher.send(inputEvent);
+ printf("Sent %s event using stream with key '%s' at %s%n",
+ inputEvent.getType(), inputEvent.getSubject(), responseEvent.getTime());
});
- } catch (IOException | IllegalArgumentException e) {
+ } catch (IOException | DeserializerException e) {
throw new RuntimeException(
ExceptionUtils.appendLogSuggestion(
"Error performing stream publication using '"
@@ -66,10 +71,8 @@ protected void perform(Publisher publisher) throws StreamxClientExcept
}
}
- private static String getRequiredProperty(JsonNode message, String property) {
- if (!message.has(property) || !message.get(property).isTextual()) {
- throw new IllegalArgumentException("Missing or invalid '%s' field".formatted(property));
- }
- return message.get(property).asText();
+ private static CloudEvent toCloudEvent(JsonNode cloudEventNode) throws JsonProcessingException {
+ byte[] cloudEventJsonBytes = objectMapper.writeValueAsBytes(cloudEventNode);
+ return deserializer.deserialize(cloudEventJsonBytes);
}
}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamIngestionArguments.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamIngestionArguments.java
index 9ac53923..c943acf7 100644
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamIngestionArguments.java
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamIngestionArguments.java
@@ -4,18 +4,11 @@
public class StreamIngestionArguments {
- @Parameters(index = "0", description = "Channel that message will be published to", arity = "1")
- String channel;
- @Parameters(index = "1", description = "Source file for the stream publication. "
- + "Can contain one or many messages", arity = "1")
+ @Parameters(index = "0", description = "Source file for the stream publication. "
+ + "Can contain one or many events", arity = "1")
String sourceFile;
-
public String getSourceFile() {
return sourceFile;
}
-
- public String getChannel() {
- return channel;
- }
}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamProperties.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamProperties.java
new file mode 100644
index 00000000..a98d5c96
--- /dev/null
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/StreamProperties.java
@@ -0,0 +1,44 @@
+package dev.streamx.cli.command.ingestion.stream;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import org.apache.commons.lang3.StringUtils;
+import org.jboss.logging.Logger;
+
+class StreamProperties {
+
+ private static final Logger logger = Logger.getLogger(StreamProperties.class);
+ private static final String PROPERTIES_FILE_NAME = ".stream.properties";
+ private static final String JSON_FIELDS_AS_BASE64 = "json.fields.as-base64";
+
+ private StreamProperties() {
+ // no instances
+ }
+
+ public static List getJsonFieldsToEncodeToBase64(Path streamFile) {
+ Path propertiesFile = streamFile.resolveSibling(PROPERTIES_FILE_NAME);
+ if (Files.exists(propertiesFile)) {
+ try (InputStream fileStream = Files.newInputStream(propertiesFile)) {
+ Properties properties = new Properties();
+ properties.load(fileStream);
+ String fields = properties.getProperty(JSON_FIELDS_AS_BASE64);
+ if (StringUtils.isNotBlank(fields)) {
+ return Arrays.stream(fields.split(","))
+ .map(String::trim)
+ .filter(StringUtils::isNotEmpty)
+ .toList();
+ }
+ } catch (IOException ex) {
+ logger.warn("Error reading properties from " + propertiesFile, ex);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64Encoder.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64Encoder.java
new file mode 100644
index 00000000..a6906d1d
--- /dev/null
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64Encoder.java
@@ -0,0 +1,44 @@
+package dev.streamx.cli.command.ingestion.stream.parser;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import java.util.Base64;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+
+public class JsonBase64Encoder {
+
+ private JsonBase64Encoder() {
+ // no instances
+ }
+
+ public static void encodeFields(JsonNode root, List fieldPaths) {
+ for (String fieldPath : fieldPaths) {
+ fieldPath = StringUtils.prependIfMissing(fieldPath, "/");
+ JsonNode node = root.at(fieldPath);
+
+ if (node.isMissingNode() || !node.isTextual()) {
+ continue;
+ }
+
+ TextNode encodedTextNode = createTextNodeWithEncodedContent(node);
+ replaceNode(root, fieldPath, encodedTextNode);
+ }
+ }
+
+ private static TextNode createTextNodeWithEncodedContent(JsonNode node) {
+ String encodedText = Base64.getEncoder().encodeToString(node.asText().getBytes());
+ return TextNode.valueOf(encodedText);
+ }
+
+ private static void replaceNode(JsonNode root, String fieldPath, JsonNode newValue) {
+ String parentPath = StringUtils.substringBeforeLast(fieldPath, "/");
+ String fieldName = StringUtils.substringAfterLast(fieldPath, "/");
+
+ JsonNode parentNode = root.at(parentPath);
+ if (parentNode instanceof ObjectNode obj) {
+ obj.set(fieldName, newValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionJsonParser.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionJsonParser.java
index 32a08758..4d9475a7 100644
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionJsonParser.java
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionJsonParser.java
@@ -6,8 +6,8 @@
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.streamx.clients.ingestion.exceptions.StreamxClientException;
import dev.streamx.cli.exception.PayloadException;
-import dev.streamx.clients.ingestion.exceptions.StreamxClientException;
import jakarta.enterprise.context.ApplicationScoped;
import java.io.IOException;
import java.io.InputStream;
@@ -34,7 +34,7 @@ public void parse(InputStream inputStream, StreamIngestionProcessor processor)
}
if (jsonToken != null) {
throw new JsonParseException(
- "Unexpected token '%s' at messages index %s".formatted(jsonToken, index));
+ "Unexpected token '%s' at events index %s".formatted(jsonToken, index));
}
parser.nextToken();
} catch (JsonParseException e) {
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionProcessor.java b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionProcessor.java
index 41ec547b..9a864574 100644
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionProcessor.java
+++ b/core/src/main/java/dev/streamx/cli/command/ingestion/stream/parser/StreamIngestionProcessor.java
@@ -1,11 +1,11 @@
package dev.streamx.cli.command.ingestion.stream.parser;
import com.fasterxml.jackson.databind.JsonNode;
-import dev.streamx.clients.ingestion.exceptions.StreamxClientException;
+import com.streamx.clients.ingestion.exceptions.StreamxClientException;
import java.io.IOException;
@FunctionalInterface
public interface StreamIngestionProcessor {
- void apply(JsonNode message) throws IOException, StreamxClientException;
+ void apply(JsonNode cloudEventNode) throws IOException, StreamxClientException;
}
diff --git a/core/src/main/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommand.java b/core/src/main/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommand.java
deleted file mode 100644
index 11378f3b..00000000
--- a/core/src/main/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package dev.streamx.cli.command.ingestion.unpublish;
-
-import static dev.streamx.cli.util.Output.printf;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import dev.streamx.cli.VersionProvider;
-import dev.streamx.cli.command.ingestion.BaseIngestionCommand;
-import dev.streamx.cli.command.ingestion.IngestionTargetArguments;
-import dev.streamx.clients.ingestion.exceptions.StreamxClientException;
-import dev.streamx.clients.ingestion.publisher.Publisher;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
-import picocli.CommandLine.ArgGroup;
-import picocli.CommandLine.Command;
-
-@Command(name = UnpublishCommand.COMMAND_NAME,
- mixinStandardHelpOptions = true,
- versionProvider = VersionProvider.class,
- description = "Send unpublication data"
-)
-public class UnpublishCommand extends BaseIngestionCommand {
-
- public static final String COMMAND_NAME = "unpublish";
-
- @ArgGroup(exclusive = false, multiplicity = "1")
- IngestionTargetArguments ingestionTargetArguments;
-
- @Override
- protected String getChannel() {
- return ingestionTargetArguments.getChannel();
- }
-
- @Override
- protected void perform(Publisher publisher) throws StreamxClientException {
- SuccessResult result = publisher.unpublish(ingestionTargetArguments.getKey());
-
- printf("Sent data unpublication message to '%s' with key '%s' at %d%n",
- ingestionTargetArguments.getChannel(), result.getKey(), result.getEventTime());
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/GitClient.java b/core/src/main/java/dev/streamx/cli/command/init/GitClient.java
deleted file mode 100644
index 4c2e6c81..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/GitClient.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import dev.streamx.cli.exception.GitException;
-import dev.streamx.cli.util.os.OsCommandStrategy;
-import dev.streamx.cli.util.os.ProcessBuilder;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.jboss.logging.Logger;
-
-@ApplicationScoped
-public class GitClient {
-
- @Inject
- OsCommandStrategy strategy;
-
- @Inject
- Logger logger;
-
- public void clone(String cloneUrl, String outputDir) {
- try {
- ProcessBuilder processBuilder = strategy.create(
- "git clone %s %s".formatted(cloneUrl, outputDir));
-
- processBuilder.addEnv("GIT_TERMINAL_PROMPT", "0");
-
- Process process = processBuilder.start();
- process.waitFor();
-
- if (process.exitValue() != 0) {
- throw GitException.gitCloneException(process);
- }
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void removeGitMetadata(String directoryPath) throws IOException {
- File directory = Path.of(directoryPath).resolve(".git").toFile();
- FileUtils.deleteDirectory(directory);
- }
-
- public void validateGitInstalled() {
- logger.info("Verifying git installation...");
- try {
- Process process = strategy.create("git --version").start();
- process.waitFor();
- byte[] stdOutBytes = process.getInputStream().readAllBytes();
-
- if (process.exitValue() != 0) {
- throwGitNotInstalled(process);
- } else if (!new String(stdOutBytes).startsWith("git version")) {
- throwGitNotInstalled(process);
- }
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void throwGitNotInstalled(Process process) {
- logger.info("Git not installed...");
- throw GitException.gitNotInstalledException(process);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/InitCommand.java b/core/src/main/java/dev/streamx/cli/command/init/InitCommand.java
deleted file mode 100644
index 1abee651..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/InitCommand.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import static dev.streamx.cli.util.Output.printf;
-
-import dev.streamx.cli.VersionProvider;
-import dev.streamx.cli.command.init.project.template.ProjectTemplateSource;
-import dev.streamx.cli.config.ArgumentConfigSource;
-import dev.streamx.cli.exception.GitException;
-import dev.streamx.cli.util.ExceptionUtils;
-import jakarta.inject.Inject;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.jboss.logging.Logger;
-import org.jetbrains.annotations.NotNull;
-import picocli.CommandLine.Command;
-import picocli.CommandLine.Parameters;
-
-@Command(name = InitCommand.COMMAND_NAME,
- mixinStandardHelpOptions = true,
- versionProvider = VersionProvider.class,
- description = "Initialize new StreamX project.")
-public class InitCommand implements Runnable {
-
- public static final String COMMAND_NAME = "init";
-
- @Parameters(
- paramLabel = "outputDir", description = "path of newly created project",
- defaultValue = "streamx-sample-project", arity = "0..1"
- )
- void outputDir(String outputDir) {
- ArgumentConfigSource.registerValue(
- InitProjectConfig.STREAMX_INIT_PROJECT_TEMPLATE_OUTPUT_DIR, outputDir);
- }
-
- @Inject
- InitProjectConfig config;
-
- @Inject
- ProjectTemplateSource projectTemplateSource;
-
- @Inject
- Logger logger;
-
- @Inject
- GitClient gitClient;
-
- @Override
- public void run() {
- try {
- gitClient.validateGitInstalled();
- validateOutputDir();
-
- String outputDir = normalizeOutputDirPath(Path.of(config.outputDir()));
- printf("Initializing StreamX project...%n");
- gitClient.clone(projectTemplateSource.getRepoUrl(), outputDir);
- gitClient.removeGitMetadata(outputDir);
- printf("Project is ready in '%s'.%n", outputDir);
- } catch (GitException e) {
- logGitOutput(e);
- throw throwGenericException(e);
- } catch (Exception e) {
- throw throwGenericException(e);
- }
- }
-
- private void validateOutputDir() {
- Path path = Path.of(config.outputDir());
- String outputDir = normalizeOutputDirPath(path);
- logger.infov("Verifying output directory: {0}", outputDir);
- if (Files.exists(path)) {
- throw new RuntimeException(outputDir + " already exists");
- }
- }
-
- private static @NotNull String normalizeOutputDirPath(Path path) {
- Path outputDirPath = path.normalize().toAbsolutePath();
- return outputDirPath.toString();
- }
-
- private void logGitOutput(GitException e) {
- try {
- String stdOut = new String(e.getProcess().getInputStream().readAllBytes());
- logger.infov("Git command stdOut: \n{0}", stdOut, e);
- String stdErr = new String(e.getProcess().getErrorStream().readAllBytes());
- logger.errorv("Git command stdErr: \n{0}", stdErr, e);
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private RuntimeException throwGenericException(Exception e) {
- return new RuntimeException(
- ExceptionUtils.appendLogSuggestion(
- "Unable to initialize new project.\n"
- + "\n"
- + "Details:\n"
- + e.getMessage()), e);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/InitProjectConfig.java b/core/src/main/java/dev/streamx/cli/command/init/InitProjectConfig.java
deleted file mode 100644
index 7d628f06..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/InitProjectConfig.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import io.smallrye.config.ConfigMapping;
-import io.smallrye.config.WithDefault;
-import io.smallrye.config.WithName;
-
-@ConfigMapping
-public interface InitProjectConfig {
-
- String STREAMX_INIT_PROJECT_TEMPLATE_OUTPUT_DIR =
- "streamx.cli.init.project.template.output-dir";
-
- @WithName(STREAMX_INIT_PROJECT_TEMPLATE_OUTPUT_DIR)
- @WithDefault("streamx-sample-project")
- String outputDir();
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/project/template/ConfigurableProjectTemplateSource.java b/core/src/main/java/dev/streamx/cli/command/init/project/template/ConfigurableProjectTemplateSource.java
deleted file mode 100644
index 15f45032..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/project/template/ConfigurableProjectTemplateSource.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package dev.streamx.cli.command.init.project.template;
-
-public class ConfigurableProjectTemplateSource implements ProjectTemplateSource {
-
- private final String projectTemplateUrl;
-
- public ConfigurableProjectTemplateSource(String projectTemplateUrl) {
- this.projectTemplateUrl = projectTemplateUrl;
- }
-
- @Override
- public String getRepoUrl() {
- return projectTemplateUrl;
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProdProjectTemplateSource.java b/core/src/main/java/dev/streamx/cli/command/init/project/template/ProdProjectTemplateSource.java
deleted file mode 100644
index 330d55c7..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProdProjectTemplateSource.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package dev.streamx.cli.command.init.project.template;
-
-public class ProdProjectTemplateSource implements ProjectTemplateSource {
-
- public static final String PROD_PROJECT_TEMPLATE_SOURCE_URL =
- "https://github.com/streamx-dev/streamx-sample-project.git";
-
- @Override
- public String getRepoUrl() {
- return PROD_PROJECT_TEMPLATE_SOURCE_URL;
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateBeanConfiguration.java b/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateBeanConfiguration.java
deleted file mode 100644
index 83ab76e9..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateBeanConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package dev.streamx.cli.command.init.project.template;
-
-import static dev.streamx.cli.command.init.project.template.ProdProjectTemplateSource.PROD_PROJECT_TEMPLATE_SOURCE_URL;
-
-import io.quarkus.arc.DefaultBean;
-import io.quarkus.arc.profile.IfBuildProfile;
-import jakarta.enterprise.context.Dependent;
-import jakarta.enterprise.inject.Produces;
-import org.eclipse.microprofile.config.inject.ConfigProperty;
-
-@Dependent
-public class ProjectTemplateBeanConfiguration {
-
- public static final String REPO_URL = "streamx.cli.init.project.template.repo-url";
-
- @Produces
- @IfBuildProfile("prod")
- ProjectTemplateSource prodTemplateSource() {
- return new ProdProjectTemplateSource();
- }
-
- @Produces
- @DefaultBean
- ProjectTemplateSource configurableTemplateSource(
- @ConfigProperty(name = REPO_URL,
- defaultValue = PROD_PROJECT_TEMPLATE_SOURCE_URL)
- String url
- ) {
- return new ConfigurableProjectTemplateSource(url);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateSource.java b/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateSource.java
deleted file mode 100644
index 08872287..00000000
--- a/core/src/main/java/dev/streamx/cli/command/init/project/template/ProjectTemplateSource.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package dev.streamx.cli.command.init.project.template;
-
-public interface ProjectTemplateSource {
-
- String getRepoUrl();
-}
diff --git a/core/src/main/java/dev/streamx/cli/command/meshprocessing/ContainerWatcher.java b/core/src/main/java/dev/streamx/cli/command/meshprocessing/ContainerWatcher.java
index 029014f1..f82d3d30 100644
--- a/core/src/main/java/dev/streamx/cli/command/meshprocessing/ContainerWatcher.java
+++ b/core/src/main/java/dev/streamx/cli/command/meshprocessing/ContainerWatcher.java
@@ -2,9 +2,9 @@
import static dev.streamx.cli.util.Output.print;
-import dev.streamx.runner.event.ContainerFailed;
-import dev.streamx.runner.event.ContainerStarted;
-import dev.streamx.runner.event.ContainerStopped;
+import com.streamx.runner.event.ContainerFailed;
+import com.streamx.runner.event.ContainerStarted;
+import com.streamx.runner.event.ContainerStopped;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@@ -12,14 +12,14 @@
public class ContainerWatcher {
void onContainerStarted(@Observes ContainerStarted event) {
- print("🟢 " + event.getContainerName() + " ready.");
+ print("🟢 " + event.containerName() + " ready.");
}
void onContainerStopped(@Observes ContainerStopped event) {
- print("🔴 " + event.getContainerName() + " stopped.");
+ print("🔴 " + event.containerName() + " stopped.");
}
void onContainerFailed(@Observes ContainerFailed event) {
- print("❌ " + event.getContainerName() + " failed.");
+ print("❌ " + event.containerName() + " failed.");
}
}
diff --git a/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolver.java b/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolver.java
index 92856e9e..9090474d 100644
--- a/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolver.java
+++ b/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolver.java
@@ -1,8 +1,8 @@
package dev.streamx.cli.command.meshprocessing;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.streamx.mesh.model.ServiceMesh;
import dev.streamx.cli.interpolation.Interpolating;
-import dev.streamx.mesh.model.ServiceMesh;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.io.IOException;
diff --git a/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshManager.java b/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshManager.java
index 56ec249e..d21aaa33 100644
--- a/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshManager.java
+++ b/core/src/main/java/dev/streamx/cli/command/meshprocessing/MeshManager.java
@@ -1,17 +1,17 @@
package dev.streamx.cli.command.meshprocessing;
+import static com.streamx.runner.main.Main.StreamxApp.printSummary;
import static dev.streamx.cli.util.Output.print;
-import static dev.streamx.runner.main.Main.StreamxApp.printSummary;
+import com.streamx.mesh.model.ServiceMesh;
+import com.streamx.runner.StreamxRunner;
+import com.streamx.runner.event.MeshReloadUpdate;
+import com.streamx.runner.validation.excpetion.DockerContainerNonUniqueException;
+import com.streamx.runner.validation.excpetion.DockerEnvironmentException;
import dev.streamx.cli.ExecutionExceptionHandler;
import dev.streamx.cli.command.run.RunningMeshPropertiesGenerator;
import dev.streamx.cli.exception.DockerException;
import dev.streamx.cli.util.ExceptionUtils;
-import dev.streamx.mesh.model.ServiceMesh;
-import dev.streamx.runner.StreamxRunner;
-import dev.streamx.runner.event.MeshReloadUpdate;
-import dev.streamx.runner.validation.excpetion.DockerContainerNonUniqueException;
-import dev.streamx.runner.validation.excpetion.DockerEnvironmentException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
@@ -108,7 +108,7 @@ private void doStart() {
print("");
RunningMeshPropertiesGenerator.generateRootAuthToken(this.runner.getMeshContext());
if (started) {
- printSummary(this.runner, normalizedMeshPath);
+ printSummary(runner, normalizedMeshPath, serviceMesh);
}
}
@@ -179,7 +179,7 @@ public void reload() {
}
void onMeshStarted(@Observes MeshReloadUpdate event) {
- switch (event.getEvent()) {
+ switch (event.event()) {
case MESH_UNCHANGED -> print("\nMesh definition is unchanged. Skip reloading...");
case FULL_RELOAD_STARTED -> print("\nMesh file changed. Processing full reload...");
case INCREMENTAL_RELOAD_STARTED ->
diff --git a/core/src/main/java/dev/streamx/cli/command/run/RunCommand.java b/core/src/main/java/dev/streamx/cli/command/run/RunCommand.java
index 345f1127..729eb7fb 100644
--- a/core/src/main/java/dev/streamx/cli/command/run/RunCommand.java
+++ b/core/src/main/java/dev/streamx/cli/command/run/RunCommand.java
@@ -1,5 +1,7 @@
package dev.streamx.cli.command.run;
+import com.streamx.runner.StreamxRunner;
+import com.streamx.runner.exception.ContainerStartupTimeoutException;
import dev.streamx.cli.BannerPrinter;
import dev.streamx.cli.VersionProvider;
import dev.streamx.cli.command.meshprocessing.MeshConfig;
@@ -7,8 +9,6 @@
import dev.streamx.cli.command.meshprocessing.MeshResolver;
import dev.streamx.cli.command.meshprocessing.MeshSource;
import dev.streamx.cli.exception.DockerException;
-import dev.streamx.runner.StreamxRunner;
-import dev.streamx.runner.exception.ContainerStartupTimeoutException;
import io.quarkus.runtime.Quarkus;
import jakarta.inject.Inject;
import java.nio.file.Path;
@@ -21,7 +21,8 @@
description = "Run a StreamX Mesh locally.")
public class RunCommand implements Runnable {
- public static final String COMMAND_NAME = "run";
+ // TODO "_v2" is a temporary postfix for now
+ public static final String COMMAND_NAME = "run_v2";
@ArgGroup
MeshSource meshSource;
diff --git a/core/src/main/java/dev/streamx/cli/command/run/RunningMeshPropertiesGenerator.java b/core/src/main/java/dev/streamx/cli/command/run/RunningMeshPropertiesGenerator.java
index 7d021ac2..a9356186 100644
--- a/core/src/main/java/dev/streamx/cli/command/run/RunningMeshPropertiesGenerator.java
+++ b/core/src/main/java/dev/streamx/cli/command/run/RunningMeshPropertiesGenerator.java
@@ -2,8 +2,8 @@
import static dev.streamx.cli.command.ingestion.IngestionClientConfig.STREAMX_INGESTION_AUTH_TOKEN;
+import com.streamx.runner.mesh.MeshContext;
import dev.streamx.cli.config.DotStreamxGeneratedConfigSource;
-import dev.streamx.runner.mesh.MeshContext;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
diff --git a/core/src/main/java/dev/streamx/cli/exception/DockerException.java b/core/src/main/java/dev/streamx/cli/exception/DockerException.java
index cbfcd4ab..b3e7ce17 100644
--- a/core/src/main/java/dev/streamx/cli/exception/DockerException.java
+++ b/core/src/main/java/dev/streamx/cli/exception/DockerException.java
@@ -1,8 +1,8 @@
package dev.streamx.cli.exception;
+import com.streamx.runner.config.StreamxBaseConfig;
+import com.streamx.runner.validation.excpetion.DockerContainerNonUniqueException.ContainerStatus;
import dev.streamx.cli.util.ExceptionUtils;
-import dev.streamx.runner.config.StreamxBaseConfig;
-import dev.streamx.runner.validation.excpetion.DockerContainerNonUniqueException.ContainerStatus;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
diff --git a/core/src/main/java/dev/streamx/cli/exception/GitException.java b/core/src/main/java/dev/streamx/cli/exception/GitException.java
deleted file mode 100644
index 8b5f4f8d..00000000
--- a/core/src/main/java/dev/streamx/cli/exception/GitException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package dev.streamx.cli.exception;
-
-public class GitException extends RuntimeException {
-
- private final Process process;
-
- private GitException(String message, Process process) {
- super(message);
- this.process = process;
- }
-
- public static GitException gitCloneException(Process process) {
- return new GitException("git clone failed.",
- process);
- }
-
- public static GitException gitNotInstalledException(Process process) {
- return new GitException("""
- Could not find a Git executable.
-
- Make sure that:
- * Git is installed,
- * Git is available on $PATH""",
- process);
- }
-
- public Process getProcess() {
- return process;
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/exception/JsonPathReplacementException.java b/core/src/main/java/dev/streamx/cli/exception/JsonPathReplacementException.java
deleted file mode 100644
index 72a2893f..00000000
--- a/core/src/main/java/dev/streamx/cli/exception/JsonPathReplacementException.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package dev.streamx.cli.exception;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.jayway.jsonpath.JsonPath;
-
-public class JsonPathReplacementException extends RuntimeException {
-
- private JsonPathReplacementException(String message, Exception exception) {
- super(message, exception);
- }
-
- public static JsonPathReplacementException noJsonPathFoundException(String valueArg) {
- return new JsonPathReplacementException("""
- Could not find valid JSONPath expression in given option.
-
- Option: %s
-
- Verify:
- * if given JSONPath expression is valid \
- (according to https://github.com/json-path/JsonPath docs),
- * if '=' is present in option"""
- .formatted(valueArg), null);
- }
-
- public static JsonPathReplacementException jsonParseException(JsonParseException exception,
- JsonPath jsonPath, String value) {
- return new JsonPathReplacementException("""
- Replacement is not recognised as valid JSON.
-
- Supplied JSONPath expression:
- %s
- Supplied replacement:
- %s
-
- Make sure that:
- * you need a JSON node as replacement
- (alternatively use '-s' to specify raw text replacement
- or use '-b' to specify is binary replacement),
- * it's valid JSON,
- * object property names are properly single-quoted (') or double-quoted ("),
- * strings are properly single-quoted (') or double-quoted (")
-
- Details: %s"""
- .formatted(jsonPath.getPath(), value, exception.getMessage()), exception);
- }
-
- public static JsonPathReplacementException genericJsonProcessingException(Exception exception,
- JsonPath jsonPath, String value) {
- return new JsonPathReplacementException("""
- Replacement could not be parsed.
-
- Supplied JSONPath expression:
- %s
- Supplied replacement:
- %s
-
- Details: %s"""
- .formatted(jsonPath.getPath(), value, exception.getMessage()), exception);
- }
-
- public static JsonPathReplacementException pathNotFoundException(JsonPath jsonPath) {
- return new JsonPathReplacementException("""
- JSONPath expression could not be found.
-
- Supplied JSONPath expression:
- %s"""
- .formatted(jsonPath.getPath()), null);
- }
-
-}
diff --git a/core/src/main/java/dev/streamx/cli/exception/KubernetesException.java b/core/src/main/java/dev/streamx/cli/exception/KubernetesException.java
deleted file mode 100644
index b8250a5f..00000000
--- a/core/src/main/java/dev/streamx/cli/exception/KubernetesException.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package dev.streamx.cli.exception;
-
-import static dev.streamx.cli.command.cloud.MetadataUtils.SERVICEMESH_CRD_NAME;
-
-import dev.streamx.cli.util.ExceptionUtils;
-import io.fabric8.kubernetes.client.KubernetesClientException;
-
-public class KubernetesException extends RuntimeException {
-
- private static final String MISSING_CRD_MESSAGE = """
- The required CustomResourceDefinition (CRD) "%s" is not installed on the cluster.
-
- Make sure that:
- * You are connected to the correct Kubernetes cluster. You can verify your current cluster \
- context by running:
-
- kubectl config current-context
-
- * StreamX Operator Custom Resource Definitions are installed on the cluster.""".formatted(
- SERVICEMESH_CRD_NAME);
- private static final String K8S_CLIENT_CONNECTION_EXCEPTION_MESSAGE = """
- Encountered an error while attempting to communicate with the cluster:
- %s
-
- Make sure that:
- * Your kubeconfig file is properly configured. You can verify the setup by running:
-
- kubectl config view
-
- * You are connected to the correct Kubernetes cluster. You can verify your current \
- cluster context by running:
-
- kubectl config current-context
-
- * The kubeconfig file is accessible and points to a valid cluster configuration.""";
- public static final String K8S_CLIENT_METHOD_EXCEPTION_MESSAGE
- = "Error updating resource %s [%s] in namespace '%s': HTTP %d (%s)";
-
- private KubernetesException(String message, Exception exception) {
- super(message, exception);
- }
-
- private KubernetesException(String message) {
- super(message);
- }
-
- public static KubernetesException serviceMeshCrdNotFound() {
- return new KubernetesException(MISSING_CRD_MESSAGE);
- }
-
- public static KubernetesException kubernetesClientException(KubernetesClientException e) {
- if (e.getStatus() != null) {
- // We are able to communicate with the cluster, Kubernetes returned error response
- return new KubernetesException(
- ExceptionUtils.appendLogSuggestion(K8S_CLIENT_METHOD_EXCEPTION_MESSAGE.formatted(
- e.getName(), e.getResourcePlural(), e.getNamespace(), e.getCode(),
- e.getStatus().getReason())),
- e);
- }
- return new KubernetesException(
- ExceptionUtils.appendLogSuggestion(K8S_CLIENT_CONNECTION_EXCEPTION_MESSAGE.formatted(
- e.getMessage())), e);
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/exception/PayloadException.java b/core/src/main/java/dev/streamx/cli/exception/PayloadException.java
index 1f6550d3..fd0ed959 100644
--- a/core/src/main/java/dev/streamx/cli/exception/PayloadException.java
+++ b/core/src/main/java/dev/streamx/cli/exception/PayloadException.java
@@ -17,15 +17,6 @@ private PayloadException(String message) {
super(message);
}
- public static PayloadException payloadNotFound() {
- return new PayloadException("""
- Payload definition not found.
-
- Make sure that:
- * there is an optional third parameter that points to the file containing the payload,
- * or there is at least one Payload Defining Option (-s/-b/-j)""");
- }
-
public static PayloadException jsonParseException(JsonParseException exception, String payload) {
return new PayloadException("""
Payload could not be parsed.
diff --git a/core/src/main/java/dev/streamx/cli/exception/UnableToConnectIngestionServiceException.java b/core/src/main/java/dev/streamx/cli/exception/UnableToConnectIngestionServiceException.java
deleted file mode 100644
index aa49007f..00000000
--- a/core/src/main/java/dev/streamx/cli/exception/UnableToConnectIngestionServiceException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package dev.streamx.cli.exception;
-
-import dev.streamx.cli.util.ExceptionUtils;
-
-public class UnableToConnectIngestionServiceException extends RuntimeException {
-
- private static final String MESSAGE = """
- Unable to connect to the ingestion service.
-
- The ingestion service URL: %s
-
- Verify:
- * if the mesh is up and running,
- * if the ingestion service URL is set correctly\
- (if it's not - set proper '--ingestion-url' option)""";
-
- private final String ingestionUrl;
-
- public UnableToConnectIngestionServiceException(String ingestionUrl, Throwable cause) {
- super(cause);
- this.ingestionUrl = ingestionUrl;
- }
-
- @Override
- public String getMessage() {
- return ExceptionUtils.appendLogSuggestion(MESSAGE.formatted(ingestionUrl));
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/exception/UnknownChannelException.java b/core/src/main/java/dev/streamx/cli/exception/UnknownChannelException.java
deleted file mode 100644
index 50cb31b1..00000000
--- a/core/src/main/java/dev/streamx/cli/exception/UnknownChannelException.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package dev.streamx.cli.exception;
-
-public class UnknownChannelException extends Exception {
-
- private final String channel;
- private final String availableChannels;
-
- public UnknownChannelException(String channel, String availableChannels) {
- this.channel = channel;
- this.availableChannels = availableChannels;
- }
-
- public String getChannel() {
- return channel;
- }
-
- public String getAvailableChannels() {
- return availableChannels;
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/license/LicenseProcessorEntrypoint.java b/core/src/main/java/dev/streamx/cli/license/LicenseProcessorEntrypoint.java
index 7c0e25d5..6a0a6ab6 100644
--- a/core/src/main/java/dev/streamx/cli/license/LicenseProcessorEntrypoint.java
+++ b/core/src/main/java/dev/streamx/cli/license/LicenseProcessorEntrypoint.java
@@ -84,7 +84,7 @@ private void proceedLicenseAcceptance(LicenseSettings licenseSettings, LocalDate
return;
}
- if (acceptingStrategy.isLicenseAccepted()) {
+ if (getAcceptingStrategy().isLicenseAccepted()) {
licenseSettingsStore.acceptLicense(licenseSettings, now);
} else {
throw LicenseException.licenseAcceptanceRejectedException();
@@ -108,4 +108,8 @@ private static String getLicenseText(LastLicenseFetch licenseSettings) {
licenseSettings.licenseUrl()
);
}
+
+ AcceptingStrategy getAcceptingStrategy() {
+ return acceptingStrategy;
+ }
}
diff --git a/core/src/main/java/dev/streamx/cli/util/CollectionUtils.java b/core/src/main/java/dev/streamx/cli/util/CollectionUtils.java
deleted file mode 100644
index 9833e13d..00000000
--- a/core/src/main/java/dev/streamx/cli/util/CollectionUtils.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package dev.streamx.cli.util;
-
-import java.util.Collection;
-
-public final class CollectionUtils {
-
- private CollectionUtils() {
- }
-
- public static boolean isEmpty(Collection> collection) {
- return collection == null || collection.isEmpty();
- }
-}
diff --git a/core/src/main/java/dev/streamx/cli/util/FileSourceUtils.java b/core/src/main/java/dev/streamx/cli/util/FileSourceUtils.java
deleted file mode 100644
index 8e4ff5b9..00000000
--- a/core/src/main/java/dev/streamx/cli/util/FileSourceUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package dev.streamx.cli.util;
-
-import dev.streamx.cli.exception.PayloadException;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-
-public class FileSourceUtils {
-
- public static final String FILE_STRATEGY_PREFIX = "file://";
-
- private FileSourceUtils() {
- // No instances
- }
-
-
- public static boolean applies(String rawSource) {
- return rawSource != null && rawSource.startsWith(FILE_STRATEGY_PREFIX);
- }
-
- public static byte[] resolve(String rawSource) {
- String source = rawSource.substring(FILE_STRATEGY_PREFIX.length());
-
- return readFile(source);
- }
-
- private static byte[] readFile(String data) {
- Path path = Path.of(data);
- try {
- return Files.readAllBytes(path);
- } catch (NoSuchFileException e) {
- throw PayloadException.noSuchFileException(e, path);
- } catch (IOException e) {
- throw PayloadException.fileReadingException(e, path);
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/OsUtils.java b/core/src/test/java/dev/streamx/cli/OsUtils.java
index 924bdb84..5e78ac52 100644
--- a/core/src/test/java/dev/streamx/cli/OsUtils.java
+++ b/core/src/test/java/dev/streamx/cli/OsUtils.java
@@ -1,11 +1,8 @@
package dev.streamx.cli;
-import dev.streamx.runner.validation.DockerEnvironmentValidator;
-import org.apache.commons.lang3.StringEscapeUtils;
+import com.streamx.runner.validation.DockerEnvironmentValidator;
public class OsUtils {
- public static final String ESCAPED_LINE_SEPARATOR =
- StringEscapeUtils.escapeJson(System.lineSeparator());
public static boolean isDockerAvailable() {
try {
diff --git a/core/src/test/java/dev/streamx/cli/command/MeshStopper.java b/core/src/test/java/dev/streamx/cli/command/MeshStopper.java
index d3660c7b..8f4119c0 100644
--- a/core/src/test/java/dev/streamx/cli/command/MeshStopper.java
+++ b/core/src/test/java/dev/streamx/cli/command/MeshStopper.java
@@ -1,6 +1,6 @@
package dev.streamx.cli.command;
-import dev.streamx.runner.StreamxRunner;
+import com.streamx.runner.StreamxRunner;
import io.quarkus.runtime.ApplicationLifecycleManager;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/ConfigurationInterpolationTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/ConfigurationInterpolationTest.java
deleted file mode 100644
index 96c18c15..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/ConfigurationInterpolationTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
-
-import com.fasterxml.jackson.databind.exc.InvalidFormatException;
-import dev.streamx.operator.crd.ServiceMesh;
-import io.quarkus.test.junit.QuarkusTest;
-import jakarta.inject.Inject;
-import java.nio.file.Path;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class ConfigurationInterpolationTest {
-
- @Inject
- ServiceMeshResolver cut;
-
- @AfterEach
- void cleanup() {
- var propertiesToClear = Set.of(
- "string.array.property", "string.property", "integer.property", "boolean.property");
-
- propertiesToClear.forEach(System::clearProperty);
- }
-
- @Test
- void shouldConfigurationBeInterpolatedFromProperties() {
- // Three properties overriding application.properties values
- System.setProperty("string.array.property", "stringArrayValue");
- System.setProperty("string.property", "stringValue");
- System.setProperty("integer.property", "0");
- // One extra property
- System.setProperty("boolean.property", "true");
-
- Path meshPath = ProjectUtils.getResourcePath(Path.of("configuration-interpolation.yaml"));
- ServiceMesh serviceMesh = cut.resolveMesh(meshPath);
-
- assertThat(serviceMesh.getSpec().getSources().get("cli").getOutgoing().get(0))
- .isEqualTo("stringArrayValue");
- assertThat(serviceMesh.getSpec().getProcessing().get("relay").getImage())
- .isEqualTo("stringValue");
- assertThat(serviceMesh.getSpec().getDeploymentConfig().getDelivery()
- .get("web-delivery-service").getReplicas()).isEqualTo(0);
- assertThat(serviceMesh.getSpec().getDeploymentConfig().getDelivery()
- .get("web-delivery-service").isStateful()).isTrue();
- }
-
- @Test
- void shouldConfigurationBeInterpolatedFromFile() {
- // Three properties comes from application.properties
- System.clearProperty("string.array.property");
- System.clearProperty("string.property");
- System.clearProperty("integer.property");
- // This one is declared only to let the mesh load
- System.setProperty("boolean.property", "true");
-
- Path meshPath = ProjectUtils.getResourcePath(Path.of("configuration-interpolation.yaml"));
- ServiceMesh serviceMesh = cut.resolveMesh(meshPath);
-
- assertThat(serviceMesh.getSpec().getSources().get("cli").getOutgoing().get(0))
- .isEqualTo("stringArrayValueFromFile");
- assertThat(serviceMesh.getSpec().getProcessing().get("relay").getImage())
- .isEqualTo("stringValueFromFile");
- assertThat(serviceMesh.getSpec().getDeploymentConfig().getDelivery()
- .get("web-delivery-service").getReplicas()).isEqualTo(1);
- }
-
- @Test
- void shouldConfigurationInterpolationFailOnMissingProperty() {
- System.clearProperty("boolean.property");
-
- final Path meshPath = ProjectUtils
- .getResourcePath(Path.of("configuration-interpolation.yaml"));
-
- RuntimeException ex = assertThrowsExactly(RuntimeException.class,
- () -> cut.resolveMesh(meshPath));
- assertThat(ex).hasRootCauseExactlyInstanceOf(NoSuchElementException.class);
- }
-
- @Test
- void shouldConfigurationInterpolationFailOnWrongType() {
- System.setProperty("boolean.property", "10");
-
- final Path meshPath = ProjectUtils
- .getResourcePath(Path.of("configuration-interpolation.yaml"));
-
- RuntimeException ex = assertThrowsExactly(RuntimeException.class,
- () -> cut.resolveMesh(meshPath));
- assertThat(ex).hasRootCauseExactlyInstanceOf(InvalidFormatException.class);
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/KubernetesClientProfile.java b/core/src/test/java/dev/streamx/cli/command/cloud/KubernetesClientProfile.java
deleted file mode 100644
index 9b7c08ef..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/KubernetesClientProfile.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import io.quarkus.test.junit.QuarkusTestProfile;
-import java.util.Map;
-
-public class KubernetesClientProfile implements QuarkusTestProfile {
-
- @Override
- public Map getConfigOverrides() {
- return Map.of("%test.quarkus.kubernetes-client.devservices.enabled", "true");
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/ProjectPathsResolverTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/ProjectPathsResolverTest.java
deleted file mode 100644
index 89d84431..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/ProjectPathsResolverTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import io.quarkus.test.component.QuarkusComponentTest;
-import jakarta.inject.Inject;
-import java.nio.file.Path;
-import org.junit.jupiter.api.Test;
-
-@QuarkusComponentTest
-class ProjectPathsResolverTest {
-
- @Inject
- ProjectPathsResolver cut;
-
- @Test
- void shouldReturnDefaultDeploymentPath() {
- Path deploymentPath = cut.resolveDeploymentPath(
- ProjectUtils.getResourcePath(Path.of("mesh.yaml")));
- assertThat(deploymentPath).endsWith(Path.of("deployment.yaml"));
- }
-
- @Test
- void shouldReturnCustomDeploymentPath() {
- Path deploymentPath = cut.resolveDeploymentPath(
- ProjectUtils.getResourcePath(Path.of("custom-name.yaml")));
- assertThat(deploymentPath).endsWith(Path.of("deployment.custom-name.yaml"));
- }
-
- @Test
- void shouldReturnSecretPath() {
- Path secretPath = cut.resolveSecretPath(ProjectUtils.getProjectPath(), "global.properties");
- assertThat(secretPath).endsWith(Path.of("project", "secrets", "global.properties"));
- }
-
- @Test
- void shouldReturnConfigPath() {
- Path secretPath = cut.resolveConfigPath(ProjectUtils.getProjectPath(), "global.properties");
- assertThat(secretPath).endsWith(Path.of("project", "configs", "global.properties"));
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/ProjectUtils.java b/core/src/test/java/dev/streamx/cli/command/cloud/ProjectUtils.java
deleted file mode 100644
index d19abe8c..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/ProjectUtils.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public final class ProjectUtils {
-
- private static final String PROJECT_PATH = "project/";
-
- public static Path getResourcePath(Path resourcePath) {
- return getProjectPath().resolve(resourcePath);
- }
-
- public static Path getProjectPath() {
- try {
- return Paths.get(ProjectUtils.class.getResource(PROJECT_PATH).toURI());
- } catch (URISyntaxException e) {
- throw new RuntimeException("Could not map project path to URI", e);
- }
- }
-
- public static String getResource(String resourceName) throws IOException {
- try (InputStream is = ServiceMeshResolverTest.class.getResourceAsStream(
- PROJECT_PATH + resourceName)) {
- return new String(is.readAllBytes(), StandardCharsets.UTF_8)
- .replace("\r\n", "\n");
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshCrdProvider.java b/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshCrdProvider.java
deleted file mode 100644
index 09418cce..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshCrdProvider.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import dev.streamx.cli.command.cloud.deploy.DeployCommandIT;
-import io.fabric8.kubernetes.client.KubernetesClient;
-import io.fabric8.kubernetes.client.dsl.NonDeletingOperation;
-import io.quarkus.arc.properties.IfBuildProperty;
-import io.quarkus.runtime.StartupEvent;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.event.Observes;
-import jakarta.inject.Inject;
-
-@ApplicationScoped
-@IfBuildProperty(name = "%test.quarkus.kubernetes-client.devservices.enabled",
- stringValue = "true")
-public class ServiceMeshCrdProvider {
-
- @Inject
- KubernetesClient kubernetesClient;
-
- void onStart(@Observes StartupEvent ev) {
- kubernetesClient.apiextensions().v1().customResourceDefinitions()
- .load(DeployCommandIT.class.getResourceAsStream("servicemeshes.streamx.dev-v1.yml"))
- .createOr(NonDeletingOperation::update);
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshResolverTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshResolverTest.java
deleted file mode 100644
index d79e92f7..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/ServiceMeshResolverTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package dev.streamx.cli.command.cloud;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import dev.streamx.cli.command.cloud.ServiceMeshResolver.ConfigSourcesPaths;
-import dev.streamx.cli.interpolation.Interpolating;
-import dev.streamx.mesh.model.AbstractContainer;
-import dev.streamx.operator.crd.ServiceMesh;
-import dev.streamx.operator.crd.deployment.ServiceMeshDeploymentConfig;
-import io.quarkus.test.junit.QuarkusTest;
-import jakarta.inject.Inject;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Set;
-import org.jetbrains.annotations.NotNull;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class ServiceMeshResolverTest {
-
- @Inject
- ServiceMeshResolver cut;
- @Inject
- @Interpolating
- ObjectMapper objectMapper;
-
-
- @Test
- void shouldThrowExceptionForEmptyMeshFile() {
- Path meshPath = ProjectUtils.getResourcePath(Path.of("empty-mesh.yaml"));
- RuntimeException runtimeException = assertThrowsExactly(RuntimeException.class,
- () -> cut.resolveMesh(meshPath));
- assertThat(runtimeException.getMessage()).isEqualTo(
- "Mesh file with provided path '" + meshPath + "' is empty.");
- }
-
- @Test
- void shouldReturnServiceMeshWithDefaultDeploymentName() throws IOException {
- ServiceMesh serviceMesh = getServiceMesh("mesh.yaml");
- assertNotNull(serviceMesh);
- String deploymentConfigYaml = mapDeploymentConfigToYaml(serviceMesh);
- String expected = ProjectUtils.getResource("deployment.yaml");
- assertEquals(expected, deploymentConfigYaml);
- }
-
- @Test
- void shouldReturnServiceMeshWithCustomDeploymentName() throws IOException {
- ServiceMesh serviceMesh = getServiceMesh("custom-name.yaml");
- assertNotNull(serviceMesh);
- String deploymentConfigYaml = mapDeploymentConfigToYaml(serviceMesh);
- String expected = ProjectUtils.getResource("deployment.custom-name.yaml");
- assertEquals(expected, deploymentConfigYaml);
- }
-
- @Test
- void shouldReturnServiceMeshWithoutDeployment() {
- ServiceMesh serviceMesh = getServiceMesh("nodeployment.yaml");
- assertNotNull(serviceMesh);
- assertNull(serviceMesh.getSpec().getDeploymentConfig());
- }
-
- @Test
- void shouldReturnMessageAboutInvalidMeshPath() {
- RuntimeException runtimeException = assertThrowsExactly(RuntimeException.class,
- () -> cut.resolveMesh(Path.of("nonexisting.mesh.yaml")));
- assertEquals("Mesh file with provided path 'nonexisting.mesh.yaml' does not exist.",
- runtimeException.getMessage());
- }
-
- @Test
- void shouldReturnAllConfigurableContainers() {
- ServiceMesh serviceMesh = getServiceMesh("with-configs.yaml");
- List containers = cut.extractContainers(serviceMesh);
- assertEquals(4, containers.size());
- }
-
- @Test
- void shouldReturnAllConfigSourcesPaths() {
- ServiceMesh serviceMesh = getServiceMesh("with-configs.yaml");
- ConfigSourcesPaths configSourcesPaths = cut.extractConfigSourcesPaths(serviceMesh);
- Set expectedEnvsPaths = Set.of(
- "global.properties",
- "ingestion/rest.properties",
- "processing/relay.properties",
- "delivery/wds.properties",
- "delivery/wds/nginx.properties",
- "shared.properties"
- );
- assertThat(configSourcesPaths.configEnvPaths()).containsExactlyInAnyOrderElementsOf(
- expectedEnvsPaths);
- assertThat(configSourcesPaths.secretEnvPaths()).containsExactlyInAnyOrderElementsOf(
- expectedEnvsPaths);
- Set expectedVolumesPaths = Set.of(
- "ingestion/rest/file.txt",
- "processing/relay/file.txt",
- "delivery/wds/file.txt",
- "delivery/wds/dir",
- "delivery/wds/nginx/file.txt",
- "shared"
- );
- assertThat(configSourcesPaths.configVolumePaths()).containsExactlyInAnyOrderElementsOf(
- expectedVolumesPaths);
- assertThat(configSourcesPaths.secretVolumePaths()).containsExactlyInAnyOrderElementsOf(
- expectedVolumesPaths);
- }
-
- @Test
- void shouldMapEmptyDeploymentFileToNull() {
- Path meshPath = ProjectUtils.getResourcePath(Path.of("empty-deployment.yaml"));
- ServiceMesh serviceMesh = cut.resolveMesh(meshPath);
- assertThat(serviceMesh.getSpec().getDeploymentConfig()).isNull();
- }
-
- @NotNull
- private ServiceMesh getServiceMesh(String meshName) {
- Path meshPath = ProjectUtils.getResourcePath(Path.of(meshName));
- return cut.resolveMesh(meshPath);
- }
-
- @NotNull
- private String mapDeploymentConfigToYaml(ServiceMesh serviceMesh) throws JsonProcessingException {
- ServiceMeshDeploymentConfig deploymentConfig = serviceMesh.getSpec().getDeploymentConfig();
- return objectMapper.writeValueAsString(deploymentConfig);
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ConfigServiceTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ConfigServiceTest.java
deleted file mode 100644
index da445a2f..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ConfigServiceTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package dev.streamx.cli.command.cloud.deploy;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.when;
-
-import dev.streamx.cli.command.cloud.ProjectPathsResolver;
-import dev.streamx.cli.command.cloud.ProjectUtils;
-import dev.streamx.cli.command.cloud.deploy.Config.ConfigType;
-import io.quarkus.test.InjectMock;
-import io.quarkus.test.component.QuarkusComponentTest;
-import jakarta.inject.Inject;
-import java.nio.file.Path;
-import java.util.Map;
-import org.junit.jupiter.api.Test;
-
-@QuarkusComponentTest
-class ConfigServiceTest {
-
- @Inject
- ConfigService cut;
-
- @InjectMock
- ProjectPathsResolver projectPathsResolver;
-
- @InjectMock
- DataService dataService;
-
- @Test
- void shouldReturnDirType() {
- ConfigType configType = cut.getConfigType(
- ProjectUtils.getResourcePath(Path.of("configs", "shared")));
- assertEquals(ConfigType.DIR, configType);
- }
-
- @Test
- void shouldReturnFileType() {
- ConfigType configType = cut.getConfigType(
- ProjectUtils.getResourcePath(Path.of("configs", "global.properties")));
- assertEquals(ConfigType.FILE, configType);
- }
-
- @Test
- void shouldReturnCorrectLabelValue() {
- assertEquals("file", ConfigType.FILE.getLabelValue());
- assertEquals("dir", ConfigType.DIR.getLabelValue());
- }
-
- @Test
- void shouldReturnEnvConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "global.properties";
- Path configPath = ProjectUtils.getResourcePath(Path.of("configs", configName));
- when(projectPathsResolver.resolveConfigPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("key", "value");
- when(dataService.loadDataFromProperties(configPath)).thenReturn(data);
- Config configEnv = cut.getConfigEnv(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.FILE);
- }
-
- @Test
- void shouldReturnSecretEnvConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "shared.properties";
- Path configPath = ProjectUtils.getResourcePath(Path.of("secrets", configName));
- when(projectPathsResolver.resolveSecretPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("secretKey", "secretValue");
- when(dataService.loadDataFromProperties(configPath)).thenReturn(data);
- Config configEnv = cut.getSecretEnv(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.FILE);
- }
-
- @Test
- void shouldReturnFileVolumeConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "delivery/wds/file.txt";
- Path configPath = ProjectUtils.getResourcePath(Path.of("configs", configName));
- when(projectPathsResolver.resolveConfigPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("file.txt", "File content");
- when(dataService.loadDataFromFiles(configPath)).thenReturn(data);
- Config configEnv = cut.getConfigVolume(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.FILE);
- }
-
- @Test
- void shouldReturnDirVolumeConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "delivery/wds/dir";
- Path configPath = ProjectUtils.getResourcePath(Path.of("configs", configName));
- when(projectPathsResolver.resolveConfigPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("file.txt", "File content", "file1.txt", "File1 content");
- when(dataService.loadDataFromFiles(configPath)).thenReturn(data);
- Config configEnv = cut.getConfigVolume(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.DIR);
- }
-
- @Test
- void shouldReturnSecretFileVolumeConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "delivery/wds/file.txt";
- Path configPath = ProjectUtils.getResourcePath(Path.of("secrets", configName));
- when(projectPathsResolver.resolveSecretPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("secret-file.txt", "File content");
- when(dataService.loadDataFromFiles(configPath)).thenReturn(data);
- Config configEnv = cut.getSecretVolume(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.FILE);
- }
-
- @Test
- void shouldReturnSecretDirVolumeConfig() {
- Path projectPath = ProjectUtils.getProjectPath();
- String configName = "delivery/wds/dir";
- Path configPath = ProjectUtils.getResourcePath(Path.of("secrets", configName));
- when(projectPathsResolver.resolveSecretPath(projectPath, configName)).thenReturn(configPath);
- Map data = Map.of("secret-file.txt", "File content", "secret-file1.txt",
- "File1 content");
- when(dataService.loadDataFromFiles(configPath)).thenReturn(data);
- Config configEnv = cut.getSecretVolume(projectPath, configName);
- assertEquals(configEnv.name(), configName);
- assertEquals(configEnv.data(), data);
- assertEquals(configEnv.configType(), ConfigType.DIR);
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DataServiceTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DataServiceTest.java
deleted file mode 100644
index 743ed928..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DataServiceTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package dev.streamx.cli.command.cloud.deploy;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
-
-import dev.streamx.cli.command.cloud.ProjectUtils;
-import java.nio.file.Path;
-import java.util.Map;
-import org.junit.jupiter.api.Test;
-
-class DataServiceTest {
-
- DataService cut = new DataService();
-
- @Test
- void shouldReturnDataWithAllProperties() {
- Path propertiesPath = ProjectUtils.getResourcePath(Path.of("configs", "global.properties"));
- Map data = cut.loadDataFromProperties(propertiesPath);
- Map expectedProperties = Map.of(
- "CONFIG_GLOBAL_PROP_NAME", "config-global-prop-value",
- "CONFIG_GLOBAL_ANOTHER_PROP_NAME", "config-global-another-prop-value");
- assertThat(data).containsExactlyInAnyOrderEntriesOf(expectedProperties);
- }
-
- @Test
- void shouldThrowExceptionAboutInvalidPropertiesFile() {
- Path propertiesPath = ProjectUtils.getResourcePath(
- Path.of("configs", "nonexistent.properties"));
- RuntimeException nonexistentFileException = assertThrowsExactly(IllegalStateException.class,
- () -> cut.loadDataFromProperties(propertiesPath));
- assertThat(nonexistentFileException.getMessage()).isEqualTo("Path " + propertiesPath
- + " provided in Mesh must be a valid properties file.");
- Path dirPath = ProjectUtils.getResourcePath(Path.of("configs"));
- RuntimeException dirIsNotValidPropertiesFileException = assertThrowsExactly(
- IllegalStateException.class, () -> cut.loadDataFromProperties(dirPath));
- assertThat(dirIsNotValidPropertiesFileException.getMessage()).isEqualTo("Path " + dirPath
- + " provided in Mesh must be a valid properties file.");
- }
-
- @Test
- void shouldThrowExceptionAboutInvalidPropertyKey() {
- Path propertiesPath = ProjectUtils.getResourcePath(
- Path.of("configs", "invalid", "invalid_prop_key.properties"));
- RuntimeException nonexistentFileException = assertThrowsExactly(IllegalArgumentException.class,
- () -> cut.loadDataFromProperties(propertiesPath));
- assertThat(nonexistentFileException.getMessage()).isEqualTo(
- "Invalid properties key: invalid[]key in environmentFrom: " + propertiesPath
- + ". Valid property key must consist of alphanumeric characters, '-', '_' or '.'.");
- }
-
- @Test
- void shouldThrowExceptionAboutInvalidFileName() {
- Path configPath = ProjectUtils.getResourcePath(
- Path.of("configs", "invalid", "invalid[]name.txt"));
- RuntimeException nonexistentFileException = assertThrowsExactly(IllegalArgumentException.class,
- () -> cut.loadDataFromFiles(configPath));
- assertThat(nonexistentFileException.getMessage()).isEqualTo(
- "Invalid file name: invalid[]name.txt in volumesFrom: " + configPath
- + ". Valid file name must consist of alphanumeric characters, '-', '_' or '.'.");
- }
-
- @Test
- void shouldThrowExceptionAboutInvalidFileNameInDir() {
- Path configPath = ProjectUtils.getResourcePath(
- Path.of("configs", "invalid"));
- RuntimeException nonexistentFileException = assertThrowsExactly(IllegalArgumentException.class,
- () -> cut.loadDataFromFiles(configPath));
- assertThat(nonexistentFileException.getMessage()).isEqualTo(
- "Invalid file name: invalid[]name.txt in volumesFrom: " + configPath
- + ". Valid file name must consist of alphanumeric characters, '-', '_' or '.'.");
- }
-
- @Test
- void shouldReturnDataMatchingFileContent() {
- Path propertiesPath = ProjectUtils.getResourcePath(Path.of("configs", "shared", "file.txt"));
- Map data = cut.loadDataFromFiles(propertiesPath);
- Map expectedData = Map.of("file.txt", "shared/file.txt");
- assertThat(data).containsExactlyInAnyOrderEntriesOf(expectedData);
- }
-
- @Test
- void shouldReturnDataMatchingDirContent() {
- Path propertiesPath = ProjectUtils.getResourcePath(Path.of("configs", "shared"));
- Map data = cut.loadDataFromFiles(propertiesPath);
- Map expectedData = Map.of(
- "file.txt", "shared/file.txt",
- "file1.txt", "shared/file1.txt");
- assertThat(data).containsExactlyInAnyOrderEntriesOf(expectedData);
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DeployCommandIT.java b/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DeployCommandIT.java
deleted file mode 100644
index adece73c..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/DeployCommandIT.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package dev.streamx.cli.command.cloud.deploy;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import dev.streamx.cli.command.cloud.KubernetesClientProfile;
-import dev.streamx.cli.command.cloud.ProjectUtils;
-import io.quarkus.test.junit.TestProfile;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import java.nio.file.Path;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
-
-@QuarkusMainTest
-@EnabledIf("dev.streamx.cli.OsUtils#isDockerAvailable")
-@TestProfile(KubernetesClientProfile.class)
-public class DeployCommandIT {
-
- @Test
- void shouldDeployProject(QuarkusMainLauncher launcher) {
- String meshPath = ProjectUtils.getResourcePath(Path.of("with-configs.yaml")).toString();
- LaunchResult result = launcher.launch("deploy", "-f=" + meshPath);
- assertThat(result.getOutput()).contains("successfully deployed to 'default' namespace.");
- }
-
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/KubernetesServiceTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/deploy/KubernetesServiceTest.java
deleted file mode 100644
index df4aa5f3..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/KubernetesServiceTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package dev.streamx.cli.command.cloud.deploy;
-
-import static dev.streamx.cli.command.cloud.MetadataUtils.COMPONENT_LABEL;
-import static dev.streamx.cli.command.cloud.MetadataUtils.CONFIG_TYPE_LABEL;
-import static dev.streamx.cli.command.cloud.MetadataUtils.INSTANCE_LABEL;
-import static dev.streamx.cli.command.cloud.MetadataUtils.MANAGED_BY_LABEL;
-import static dev.streamx.cli.command.cloud.MetadataUtils.MANAGED_BY_LABEL_VALUE;
-import static dev.streamx.cli.command.cloud.MetadataUtils.NAME_LABEL;
-import static dev.streamx.cli.command.cloud.MetadataUtils.PART_OF_LABEL;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import dev.streamx.cli.command.cloud.KubernetesService;
-import dev.streamx.cli.command.cloud.deploy.Config.ConfigType;
-import dev.streamx.operator.Component;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.api.model.ObjectMeta;
-import io.fabric8.kubernetes.api.model.Secret;
-import io.quarkus.test.component.QuarkusComponentTest;
-import jakarta.inject.Inject;
-import java.util.Map;
-import org.junit.jupiter.api.Test;
-
-@QuarkusComponentTest
-class KubernetesServiceTest {
-
- private static final String MESH_NAME = "sx";
- @Inject
- KubernetesService cut;
-
- @Test
- void shouldReturnConfigMapWithRequiredMetadataAndData() {
- Map data = Map.of("key", "value");
- ConfigType configType = ConfigType.FILE;
- Config config = new Config("test/default.conf", data, configType);
- ConfigMap configMap = cut.buildConfigMap(MESH_NAME, config);
- ObjectMeta metadata = configMap.getMetadata();
- assertThat(metadata.getName()).isEqualTo("sx-extcfg-test-default-conf");
- Map expectedLabels = Map.of(
- NAME_LABEL, "test-default-conf",
- INSTANCE_LABEL, "sx-extcfg-test-default-conf",
- COMPONENT_LABEL, Component.EXTERNAL_CONFIG.getName(),
- MANAGED_BY_LABEL, MANAGED_BY_LABEL_VALUE,
- CONFIG_TYPE_LABEL, configType.getLabelValue(),
- PART_OF_LABEL, "sx"
- );
- assertThat(metadata.getLabels()).containsExactlyInAnyOrderEntriesOf(expectedLabels);
- assertThat(configMap.getData()).containsExactlyInAnyOrderEntriesOf(data);
- }
-
- @Test
- void shouldReturnSecretWithRequiredMetadataAndData() {
- ConfigType configType = ConfigType.DIR;
- Map data = Map.of("key", "value");
- Config config = new Config("test/default.conf", data, configType);
- Secret secret = cut.buildSecret(MESH_NAME, config);
- ObjectMeta metadata = secret.getMetadata();
- assertThat(metadata.getName()).isEqualTo("sx-extsec-test-default-conf");
- Map expectedLabels = Map.of(
- NAME_LABEL, "test-default-conf",
- INSTANCE_LABEL, "sx-extsec-test-default-conf",
- COMPONENT_LABEL, Component.EXTERNAL_SECRET.getName(),
- MANAGED_BY_LABEL, MANAGED_BY_LABEL_VALUE,
- CONFIG_TYPE_LABEL, configType.getLabelValue(),
- PART_OF_LABEL, "sx"
- );
- assertThat(metadata.getLabels()).containsExactlyInAnyOrderEntriesOf(expectedLabels);
- assertThat(secret.getStringData()).containsExactlyInAnyOrderEntriesOf(data);
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ProjectResourcesExtractorTest.java b/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ProjectResourcesExtractorTest.java
deleted file mode 100644
index 1dcca3a6..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/deploy/ProjectResourcesExtractorTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package dev.streamx.cli.command.cloud.deploy;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import dev.streamx.cli.command.cloud.KubernetesService;
-import dev.streamx.cli.command.cloud.ProjectUtils;
-import dev.streamx.cli.command.cloud.ServiceMeshResolver.ConfigSourcesPaths;
-import dev.streamx.cli.command.cloud.deploy.Config.ConfigType;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.api.model.Secret;
-import io.quarkus.test.InjectMock;
-import io.quarkus.test.component.QuarkusComponentTest;
-import jakarta.inject.Inject;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.junit.jupiter.api.Test;
-
-@QuarkusComponentTest
-class ProjectResourcesExtractorTest {
-
- @InjectMock
- ConfigService configService;
-
- @InjectMock
- KubernetesService kubernetesService;
-
- @Inject
- ProjectResourcesExtractor projectResourcesExtractor;
-
- @Test
- void shouldReturnExtractedConfigMaps() {
- String meshName = "sx";
- Path projectPath = ProjectUtils.getProjectPath();
- ConfigSourcesPaths configSourcesPaths = new ConfigSourcesPaths(
- Set.of("global.properties"),
- Collections.emptySet(),
- Set.of("shared/file.txt"),
- Collections.emptySet());
- Config config = new Config("name", Map.of("key", "value"), ConfigType.FILE);
- when(configService.getConfigEnv(projectPath, "global.properties")).thenReturn(config);
- when(configService.getConfigVolume(projectPath, "shared/file.txt")).thenReturn(config);
- when(kubernetesService.buildConfigMap(meshName, config)).thenReturn(mock(ConfigMap.class));
- List configMaps = projectResourcesExtractor.getConfigMaps(projectPath,
- configSourcesPaths, meshName);
- assertThat(configMaps).hasSize(2);
- }
-
- @Test
- void shouldReturnExtractedSecrets() {
- String meshName = "sx";
- Path projectPath = ProjectUtils.getProjectPath();
- ConfigSourcesPaths configSourcesPaths = new ConfigSourcesPaths(
- Collections.emptySet(),
- Set.of("global.properties"),
- Collections.emptySet(),
- Set.of("shared/file.txt"));
- Config config = new Config("name", Map.of("key", "value"), ConfigType.FILE);
- when(configService.getSecretEnv(projectPath, "global.properties")).thenReturn(config);
- when(configService.getSecretVolume(projectPath, "shared/file.txt")).thenReturn(config);
- when(kubernetesService.buildSecret(meshName, config)).thenReturn(mock(Secret.class));
- List secrets = projectResourcesExtractor.getSecrets(projectPath,
- configSourcesPaths, meshName);
- assertThat(secrets).hasSize(2);
- }
-}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/cloud/undeploy/UndeployCommandIT.java b/core/src/test/java/dev/streamx/cli/command/cloud/undeploy/UndeployCommandIT.java
deleted file mode 100644
index 7b7d13fe..00000000
--- a/core/src/test/java/dev/streamx/cli/command/cloud/undeploy/UndeployCommandIT.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package dev.streamx.cli.command.cloud.undeploy;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import dev.streamx.cli.command.cloud.KubernetesClientProfile;
-import io.quarkus.test.junit.TestProfile;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
-
-@QuarkusMainTest
-@EnabledIf("dev.streamx.cli.OsUtils#isDockerAvailable")
-@TestProfile(KubernetesClientProfile.class)
-class UndeployCommandIT {
-
- @Test
- void shouldUndeployProject(QuarkusMainLauncher launcher) {
- LaunchResult result = launcher.launch("undeploy");
- assertThat(result.getOutput()).contains(
- "StreamX project successfully undeployed from 'default' namespace.");
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/dev/DevCommandTest.java b/core/src/test/java/dev/streamx/cli/command/dev/DevCommandTest.java
deleted file mode 100644
index 8fd0e9c4..00000000
--- a/core/src/test/java/dev/streamx/cli/command/dev/DevCommandTest.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package dev.streamx.cli.command.dev;
-
-import static dev.streamx.cli.command.util.MeshTestsUtils.cleanUpMesh;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import com.github.dockerjava.api.DockerClient;
-import dev.streamx.cli.command.MeshStopper;
-import dev.streamx.cli.command.dev.DevCommandTest.DevCommandProfile;
-import dev.streamx.cli.command.dev.event.DashboardStarted;
-import dev.streamx.cli.command.dev.event.DevReady;
-import dev.streamx.runner.event.MeshReloadUpdate;
-import dev.streamx.runner.event.MeshStarted;
-import io.quarkus.arc.properties.IfBuildProperty;
-import io.quarkus.test.junit.QuarkusTestProfile;
-import io.quarkus.test.junit.TestProfile;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.enterprise.event.Observes;
-import jakarta.inject.Inject;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
-import org.awaitility.Awaitility;
-import org.jetbrains.annotations.NotNull;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
-import org.junit.jupiter.api.io.TempDir;
-import org.testcontainers.DockerClientFactory;
-import org.testcontainers.shaded.com.github.dockerjava.core.command.ExecStartResultCallback;
-import org.testcontainers.shaded.org.apache.commons.io.IOUtils;
-
-
-@QuarkusMainTest
-@EnabledIf("dev.streamx.cli.OsUtils#isDockerAvailable")
-@TestProfile(DevCommandProfile.class)
-class DevCommandTest {
-
- public static final String MESH_PROPERTY_NAME = "test.mesh.path";
- public static final String HOST_DIRECTORY = "target/test-classes";
- public static final String MESHES_DIRECTORY = HOST_DIRECTORY + "/dev/streamx/cli/command/dev";
- public static final String INITIAL_MESH = MESHES_DIRECTORY + "/initial-mesh.yaml";
- public static final String FAILING_MESH = MESHES_DIRECTORY + "/failing-mesh.yaml";
- public static final String INCREMENTAL_RELOADED_MESH =
- MESHES_DIRECTORY + "/incremental-reloaded-mesh.yaml";
-
- @TempDir
- public Path temp;
-
- @AfterEach
- void awaitDockerResourcesAreRemoved() {
- Awaitility.await()
- .until(() -> {
- try {
- Set cleanedUpContainers =
- Set.of("pulsar", "pulsar-init", "streamx-dashboard",
- "rest-ingestion", "relay", "web-delivery-service");
- cleanUpMesh(cleanedUpContainers);
-
- return true;
- } catch (Exception e) {
- return false;
- }
- });
- }
-
- @Test
- void shouldReactOnMeshChanges(QuarkusMainLauncher launcher) {
- // given
- var meshPath = temp.resolve("mesh.yaml");
- String meshPathString = meshPath
- .toAbsolutePath()
- .normalize()
- .toString();
-
- System.setProperty(MESH_PROPERTY_NAME, meshPathString);
-
- // when
- LaunchResult result = launcher.launch("dev", "-f=" + meshPathString);
-
- // then
- var errorOutput = getErrorOutput(result);
-
- assertThat(errorOutput).doesNotContain(StateVerifier.MESH_CONTENT_DIFFERENT);
- assertThat(errorOutput).doesNotContain(StateVerifier.PROJECT_DIR_DIFFERENT);
- assertThat(errorOutput).isBlank();
-
- assertThat(result.exitCode()).isZero();
- assertThat(result.getOutput()).contains("StreamX Dashboard started on");
- }
-
- @NotNull
- private static String getErrorOutput(LaunchResult result) {
- var errorOutput = result.getErrorOutput();
- if (!errorOutput.isBlank()) {
- System.err.println(errorOutput);
- }
- return errorOutput;
- }
-
- @ApplicationScoped
- @IfBuildProperty(name = "streamx.dev.test.profile", stringValue = "true")
- public static class StateVerifier {
- private static final String PROJECT_DIR_DIFFERENT =
- "Provided project directory contend is different than container project.";
- private static final String INITIAL_MESH_NOT_EMPTY =
- "Initial mesh file must be empty.";
- private static final String DASHBOARD_NOT_STARTED =
- "Dashboard did not start";
- private static final String MESH_CONTENT_DIFFERENT =
- "Provided mesh and container mesh have different content.";
-
- private final DockerClient client = DockerClientFactory.instance().client();
-
- private AtomicBoolean dashboardStarted = new AtomicBoolean(false);
-
- @Inject
- MeshStopper meshStopper;
-
- @Inject
- DashboardRunner dashboardRunner;
-
- void onMeshStarted(@Observes MeshStarted event) throws Exception {
- Path meshPath = getMeshPath();
-
- Files.copy(Path.of(FAILING_MESH), meshPath, StandardCopyOption.REPLACE_EXISTING);
- }
-
- void onDevReady(@Observes DevReady event) throws Exception {
- if (!dashboardStarted.get()) {
- System.err.println(DASHBOARD_NOT_STARTED);
- }
-
- Path meshPath = getMeshPath();
-
- if (Files.size(meshPath) > 0) {
- System.err.println(INITIAL_MESH_NOT_EMPTY);
- }
- Files.copy(Path.of(INITIAL_MESH), meshPath, StandardCopyOption.REPLACE_EXISTING);
- }
-
- void onMeshReload(@Observes MeshReloadUpdate event) throws Exception {
- Path meshPath = getMeshPath();
-
- switch (event.getEvent()) {
- case FULL_RELOAD_FINISHED -> {
- compareMeshContent(INITIAL_MESH);
- compareProjectDirectoryContent();
-
- Files.copy(Path.of(FAILING_MESH), meshPath, StandardCopyOption.REPLACE_EXISTING);
- }
- case INCREMENTAL_RELOAD_FAILED -> {
- Files.copy(Path.of(INCREMENTAL_RELOADED_MESH), meshPath,
- StandardCopyOption.REPLACE_EXISTING);
- }
- case INCREMENTAL_RELOAD_FINISHED -> {
- Files.deleteIfExists(meshPath);
-
- dashboardRunner.stopStreamxDashboard();
- meshStopper.scheduleStop();
- }
- default -> {
-
- }
- }
- }
-
- private @NotNull Path getMeshPath() {
- String meshPath = System.getProperty(MESH_PROPERTY_NAME);
- Path meshFile = Path.of(meshPath);
- return meshFile;
- }
-
- void onDashboardStarted(@Observes DashboardStarted event) {
- dashboardStarted.set(true);
- }
-
- private void compareProjectDirectoryContent() throws InterruptedException {
- var command = "ls -1 /data/project";
-
- var containerMeshContent = executeCommand(client, command);
-
- var containerDirectoryContent = extractContainerFiles(containerMeshContent);
- var directoryContent = extractHostFiles();
-
- if (!containerDirectoryContent.equals(directoryContent)) {
- System.err.println(PROJECT_DIR_DIFFERENT);
- }
- }
-
- @NotNull
- private static Set extractHostFiles() {
- return Arrays.stream(new File(HOST_DIRECTORY).listFiles())
- .map(File::getName)
- .collect(Collectors.toSet());
- }
-
- @NotNull
- private static Set extractContainerFiles(byte[] containerMeshContent) {
- var lines = IOUtils.readLines(new ByteArrayInputStream(containerMeshContent),
- StandardCharsets.UTF_8);
-
- return lines.stream()
- .filter(Objects::nonNull)
- .map(String::trim)
- .collect(Collectors.toSet());
- }
-
- private void compareMeshContent(String mesh) throws InterruptedException, IOException {
- var command = "cat /data/mesh.yaml";
-
- var containerMeshContent = executeCommand(client, command);
- var meshPath = Paths.get(mesh);
-
- if (!Arrays.equals(Files.readAllBytes(meshPath), containerMeshContent)) {
- System.err.println(MESH_CONTENT_DIFFERENT);
- }
- }
-
- private byte[] executeCommand(DockerClient client, String command) throws InterruptedException {
- var execId = client
- .execCreateCmd("streamx-dashboard")
- .withCmd("sh", "-c", command)
- .withAttachStdout(true)
- .exec()
- .getId();
-
- var outputStream = new ByteArrayOutputStream();
- var results = new ExecStartResultCallback(outputStream, null);
-
- client.execStartCmd(execId)
- .exec(results)
- .awaitCompletion();
-
- return outputStream.toByteArray();
- }
- }
-
- public static class DevCommandProfile implements QuarkusTestProfile {
-
- @Override
- public Map getConfigOverrides() {
- return Map.of(
- "streamx.dev.test.profile", "true",
- "streamx.container.startup-timeout-seconds", "15"
- );
- }
- }
-
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/dev/DockerValidatorTest.java b/core/src/test/java/dev/streamx/cli/command/dev/DockerValidatorTest.java
deleted file mode 100644
index 7b3b1d99..00000000
--- a/core/src/test/java/dev/streamx/cli/command/dev/DockerValidatorTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package dev.streamx.cli.command.dev;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchException;
-
-import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.command.PullImageResultCallback;
-import com.github.dockerjava.api.command.RemoveContainerCmd;
-import com.github.dockerjava.api.exception.ConflictException;
-import dev.streamx.runner.validation.excpetion.DockerContainerNonUniqueException;
-import dev.streamx.runner.validation.excpetion.DockerEnvironmentException;
-import io.quarkus.arc.impl.Reflections;
-import io.quarkus.test.junit.QuarkusTest;
-import jakarta.inject.Inject;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
-import org.mockito.Mockito;
-import org.testcontainers.DockerClientFactory;
-
-
-@QuarkusTest
-@EnabledIf("dev.streamx.cli.OsUtils#isDockerAvailable")
-class DockerValidatorTest {
-
- public static final String HELLO_WORLD_IMAGE = "hello-world:latest";
- public static final String HELLO_WORLD_CONTAINER_NAME = "dockerValidatorTestContainer";
-
- @Inject
- DockerValidator uut;
-
- @BeforeAll
- static void initialize() throws InterruptedException {
- DockerClient client = DockerClientFactory.instance().client();
- prepareContainer(client, HELLO_WORLD_CONTAINER_NAME);
- }
-
- @AfterAll
- static void destroy() {
- DockerClient client = DockerClientFactory.instance().client();
- dropContainer(client, HELLO_WORLD_CONTAINER_NAME).exec();
- }
-
- @Test
- void shouldDetectDuplicatedContainers() {
- // given
- var usedContainers = Set.of(HELLO_WORLD_CONTAINER_NAME);
-
- // when
- var exception = catchException(() -> uut.validateDockerEnvironment(usedContainers));
-
- // then
- assertThat(exception)
- .isInstanceOf(DockerContainerNonUniqueException.class)
- .hasMessage("Containers with names '" + HELLO_WORLD_CONTAINER_NAME + "' already exists.");
- }
-
- @ParameterizedTest
- @ValueSource(strings = {
- "RunnerValidatorTest",
- "streamx",
- "Container",
- })
- void shouldNotDetectDuplicatedContainers(String testedContainerName) {
- // given
- var usedContainers = Set.of(testedContainerName);
-
- // when
- var exception = catchException(() -> uut.validateDockerEnvironment(usedContainers));
-
- // then
- assertThat(exception).isNull();
- }
-
- private static RemoveContainerCmd dropContainer(DockerClient client,
- String containerName) {
- return client.removeContainerCmd(containerName);
- }
-
- private static void prepareContainer(DockerClient client, String containerName)
- throws InterruptedException {
- client.pullImageCmd(HELLO_WORLD_IMAGE)
- .exec(new PullImageResultCallback())
- .awaitCompletion(30, TimeUnit.SECONDS);
-
- try {
- client.createContainerCmd(HELLO_WORLD_IMAGE)
- .withName(containerName)
- .exec();
- } catch (ConflictException e) {
- // container already exists
- }
- }
-
- @Test
- void shouldValidateNoDockerEnvironment() {
- DockerClientFactory dockerClientFactory = DockerClientFactory.instance();
-
- try {
- // given
- DockerEnvironmentException dockerEnvironmentException =
- new DockerEnvironmentException(new RuntimeException());
- Reflections.writeField(DockerClientFactory.class, "cachedClientFailure",
- dockerClientFactory, dockerEnvironmentException);
-
- // when
- Exception exception = catchException(() -> uut.validateDockerEnvironment(Mockito.mock()));
-
- // then
- assertThat(exception)
- .isInstanceOf(DockerEnvironmentException.class);
- } finally {
- Reflections.writeField(DockerClientFactory.class, "cachedClientFailure",
- dockerClientFactory, null);
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/BaseIngestionCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/BaseIngestionCommandTest.java
index 75a87397..e1e42218 100644
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/BaseIngestionCommandTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/BaseIngestionCommandTest.java
@@ -1,21 +1,27 @@
package dev.streamx.cli.command.ingestion;
import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-import static dev.streamx.clients.ingestion.StreamxClient.INGESTION_ENDPOINT_PATH_V1;
+import static com.streamx.clients.ingestion.StreamxClient.INGESTION_ENDPOINT_PATH_V2;
import static org.assertj.core.api.Assertions.assertThat;
+import com.fasterxml.jackson.databind.node.TextNode;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
+import com.streamx.ce.serialization.json.CloudEventJsonSerializer;
+import dev.streamx.cli.command.ingestion.batch.CloudEventBuilder;
+import io.cloudevents.CloudEvent;
import io.quarkus.test.junit.main.LaunchResult;
+import org.apache.hc.core5.http.HttpStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.RegisterExtension;
public abstract class BaseIngestionCommandTest {
+ protected static final String PUBLICATION_PATH = INGESTION_ENDPOINT_PATH_V2;
+
@RegisterExtension
protected static WireMockExtension wm = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
@@ -27,20 +33,17 @@ void setup() {
initializeWiremock();
}
- protected abstract void initializeWiremock();
+ private void initializeWiremock() {
+ setupMockPublicationResponse(
+ CloudEventBuilder.build(
+ "index.html", "some-event-type", "source", new TextNode("mock-response"))
+ );
+ }
protected static String getIngestionUrl() {
return "http://localhost:" + wm.getPort();
}
- protected static String getPublicationPath(String channel) {
- return INGESTION_ENDPOINT_PATH_V1 + "/channels/" + channel + "/messages";
- }
-
- protected static String getChannelsPath() {
- return INGESTION_ENDPOINT_PATH_V1 + "/channels";
- }
-
protected static void expectSuccess(LaunchResult result) {
assertThat(result.exitCode()).isZero();
assertThat(result.getErrorOutput()).isEmpty();
@@ -48,71 +51,17 @@ protected static void expectSuccess(LaunchResult result) {
protected static void expectError(LaunchResult result, String expectedErrorOutput) {
assertThat(result.exitCode()).isNotZero();
- assertThat(result.getErrorOutput().replace("\r\n", "\n")).contains(expectedErrorOutput);
+ assertThat(result.getErrorOutput().trim())
+ .isEqualToNormalizingNewlines(expectedErrorOutput.trim());
}
- protected static void setupMockChannelsSchemasResponse() {
+ protected static void setupMockPublicationResponse(CloudEvent response) {
ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(200)
- .withHeader(CONTENT_TYPE, APPLICATION_JSON)
- .withBody(
- """
- {
- "pages": {
- "type": "record",
- "name": "DataIngestionMessage",
- "namespace": "dev.streamx.ingestion.rest.test",
- "fields": [
- {
- "name": "key",
- "type": "string"
- },
- {
- "name": "action",
- "type": "string"
- },
- {
- "name": "eventTime",
- "type": [
- "null",
- "long"
- ]
- },
- {
- "name": "properties",
- "type": {
- "type": "map",
- "values": "string"
- }
- },
- {
- "name": "payload",
- "type": [
- "null",
- {
- "type": "record",
- "name": "Page",
- "namespace": "dev.streamx.blueprints.data",
- "fields": [
- {
- "name": "content",
- "type": [
- "null",
- "bytes"
- ],
- "default": null
- }
- ]
- }
- ]
- }
- ]
- }
- }
- """
- );
+ .withStatus(HttpStatus.SC_ACCEPTED)
+ .withBody(new CloudEventJsonSerializer().serialize(response))
+ .withHeader(CONTENT_TYPE, "application/cloudevents+json");
- wm.stubFor(WireMock.get(getChannelsPath())
+ wm.stubFor(WireMock.post(PUBLICATION_PATH)
.willReturn(mockResponse));
}
}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/IngestionArgumentsValidationTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/IngestionArgumentsValidationTest.java
deleted file mode 100644
index cc9d6799..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/IngestionArgumentsValidationTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package dev.streamx.cli.command.ingestion;
-
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import org.junit.jupiter.api.Test;
-
-@QuarkusMainTest
-public class IngestionArgumentsValidationTest extends BaseIngestionCommandTest {
-
- private static final String CHANNEL = "pages";
- private static final String KEY = "index.html";
-
- @Test
- public void shouldRejectIllegalIngestionUrl(QuarkusMainLauncher launcher) {
- // given
- String invalidIngestionUrl = "hattetepe:///in valid";
-
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + invalidIngestionUrl,
- CHANNEL, KEY);
-
- // then
- expectError(result,
- "Endpoint URI: hattetepe:///in valid/ingestion/v1 is malformed. "
- + "Illegal character in path");
- }
-
- @Test
- public void shouldRejectChannellessIngestion(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish");
-
- // then
- expectError(result, """
- Error: Missing required argument(s): ( )
- Usage: streamx unpublish [-hV] [[--ingestion-url=]]
- ( )
-
- Try 'streamx unpublish --help' for more information.""");
- }
-
- @Test
- public void shouldRejectIngestionWithMissingParameter(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish", "-s");
-
- // then
- expectError(result, """
- Missing required parameter for option '--string-fragment' ()
- Usage: streamx publish [-hV] [-p=]...
- [[--ingestion-url=]] (
- [payloadFile]) [[[-s= | -b= |
- -j=]]...]
-
- Try 'streamx publish --help' for more information.""");
- }
-
- @Test
- public void shouldRejectKeylessIngestion(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish", "channel");
-
- // then
- expectError(result, """
- Error: Missing required argument(s):
- Usage: streamx unpublish [-hV] [[--ingestion-url=]]
- ( )
-
- Try 'streamx unpublish --help' for more information.""");
- }
-
- @Test
- public void shouldRejectInvalidHostInIngestionUrl(QuarkusMainLauncher launcher) {
- // given
- String invalidIngestionUrl = "hattetepe:///invalid";
-
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + invalidIngestionUrl,
- CHANNEL, KEY);
-
- // then
- expectError(result,
- "Endpoint URI: hattetepe:///invalid/ingestion/v1 is malformed. "
- + "URI without host is not supported.");
- }
-
- @Override
- protected void initializeWiremock() {
- // no mock responses to configure for this test
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchPublishCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchPublishCommandTest.java
index 7b5c878d..a6ae6f7a 100644
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchPublishCommandTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchPublishCommandTest.java
@@ -1,93 +1,36 @@
package dev.streamx.cli.command.ingestion.batch;
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static dev.streamx.cli.OsUtils.ESCAPED_LINE_SEPARATOR;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST;
-
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.common.Json;
+
import com.github.tomakehurst.wiremock.matching.ContainsPattern;
import dev.streamx.cli.command.ingestion.AuthorizedProfile;
import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
import dev.streamx.cli.command.ingestion.UnauthorizedProfile;
-import dev.streamx.clients.ingestion.publisher.FailureResult;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
import io.quarkus.test.junit.TestProfile;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainLauncher;
import io.quarkus.test.junit.main.QuarkusMainTest;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.jose4j.base64url.Base64;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class BatchPublishCommandTest extends BaseIngestionCommandTest {
- private static final String CHANNEL = "pages";
- private static final String UNSUPPORTED_CHANNEL = "images";
- private static final String KEY = "index.html";
-
@Nested
@QuarkusMainTest
@TestProfile(UnauthorizedProfile.class)
class UnauthorizedTest {
- @Test
- public void shouldHandleInvalidPayloadFromRestIngestionApi(QuarkusMainLauncher launcher) {
- setupMockPublicationResponse(
- CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("INVALID_INGESTION_INPUT",
- "Data does not match the existing schema: Unknown union branch byte"
- )
- );
-
- // when
- LaunchResult result = launcher.launch(
- "batch", "--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/invalid-channel"
- );
-
- // then
- expectError(result, """
- Error performing batch publication while processing \
- 'target/test-classes/dev/streamx/cli/command/ingestion/batch/invalid-channel/index.html' \
- file.
-
- Details:
- Ingestion REST endpoint known error. Code: INVALID_INGESTION_INPUT. \
- Message: Data does not match the existing schema: Unknown union branch byte
-
- Full logs can be found in quarkus.log""");
- }
-
- @Test
- public void shouldRejectUnknownChannel(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch(
- "batch", "--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/unknown-channel"
- );
-
- // then
- expectError(result,
- "Channel 'images' not found. Available channels: [pages]");
- }
-
@Test
public void shouldRejectInvalidDataJson(QuarkusMainLauncher launcher) {
// when
LaunchResult result = launcher.launch(
- "batch", "--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/invalid-json"
+ BatchCommand.COMMAND_NAME, "--ingestion-url=" + getIngestionUrl(),
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/invalid-json"
);
// then
@@ -106,70 +49,102 @@ public void shouldRejectInvalidDataJson(QuarkusMainLauncher launcher) {
}
@Test
- public void shouldBatchPublishValidDirectory(QuarkusMainLauncher launcher) {
+ public void shouldBatchPublishValidDirectoryWithPage(QuarkusMainLauncher launcher) {
+ // when
+ LaunchResult result = launcher.launch(
+ BatchCommand.COMMAND_NAME, "--ingestion-url=" + getIngestionUrl(),
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/publish/page"
+ );
+
+ // then
+ expectSuccess(result);
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
+ .withRequestBody(new CloudEventJsonMatcher("""
+ {
+ "specversion" : "1.0",
+ "id" : "75a90fb7-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_publish",
+ "datacontenttype" : "application/json",
+ "subject" : "page/index.html",
+ "time" : "2025-12-23T10:28:23.435253Z",
+ "data" : {
+ "content" : "%s",
+ "type" : "page/sub-page"
+ }
+ }
+ """.formatted(Base64.encode("Hello World!
".getBytes()))))
+ .withoutHeader("Authorization"));
+ wm.verify(1, postRequestedFor(urlEqualTo(PUBLICATION_PATH)));
+ }
+
+ @Test
+ public void shouldBatchPublishValidDirectoryWithImage(QuarkusMainLauncher launcher)
+ throws IOException {
// when
LaunchResult result = launcher.launch(
- "batch", "--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid"
+ BatchCommand.COMMAND_NAME, "--ingestion-url=" + getIngestionUrl(),
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/publish/image"
);
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
+ .withRequestBody(new CloudEventJsonMatcher("""
{
- "key" : "valid/index.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : {
- "sx:type" : "page/sub-page"
- },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "Hello World!
%s"
- }
- }
+ "specversion" : "1.0",
+ "id" : "75a90fb7-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "image_publish",
+ "datacontenttype" : "application/json",
+ "subject" : "image/ds.png",
+ "time" : "2025-12-23T10:28:23.435253Z",
+ "data" : {
+ "content" : "%s",
+ "type" : "assets/image"
}
}
- """.formatted(ESCAPED_LINE_SEPARATOR)))
+ """.formatted(Base64.encode(Files.readAllBytes(Path.of(
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/"
+ + "publish/image/ds.png"))))))
.withoutHeader("Authorization"));
- wm.verify(1, postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL))));
+ wm.verify(1, postRequestedFor(urlEqualTo(PUBLICATION_PATH)));
}
@Test
public void shouldBatchPublishValidDirectoryWithJsons(QuarkusMainLauncher launcher) {
// when
LaunchResult result = launcher.launch(
- "batch", "--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid-json"
+ BatchCommand.COMMAND_NAME, "--ingestion-url=" + getIngestionUrl(),
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid-json"
);
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
+ .withRequestBody(new CloudEventJsonMatcher("""
{
- "key" : "content.json",
- "action" : "publish",
- "eventTime" : null,
- "properties" : { },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "object" : {
- "content" : "Hello world!
"
- },
- "fixed-property" : true,
- "list" : [ {
- "content" : "Hello world!
"
- } ]
- }
+ "specversion" : "1.0",
+ "id" : "b0db1b2f-4069-4234-a968-9474f96ede9e",
+ "source" : "source",
+ "type" : "page_publish",
+ "datacontenttype" : "application/json",
+ "subject" : "content.json",
+ "time" : "2025-12-23T11:00:17.710136Z",
+ "data" : {
+ "object" : {
+ "content" : "Hello world!
"
+ },
+ "fixed-property" : true,
+ "list" : [ {
+ "content" : "Hello world!
"
+ } ]
}
}
"""))
.withoutHeader("Authorization"));
- wm.verify(1, postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL))));
+ wm.verify(1, postRequestedFor(urlEqualTo(PUBLICATION_PATH)));
}
@Test
@@ -177,23 +152,19 @@ public void shouldRejectWrongIngestionUrl(QuarkusMainLauncher launcher) {
// when
String ingestionServiceUrl = "http://aaa.bbb.ccc";
LaunchResult result = launcher.launch(
- "batch",
+ BatchCommand.COMMAND_NAME,
"--ingestion-url=" + ingestionServiceUrl,
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid");
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/publish/page");
// then
expectError(result,
- """
- Unable to connect to the ingestion service.
-
- The ingestion service URL: http://aaa.bbb.ccc
-
- Verify:
- * if the mesh is up and running,
- * if the ingestion service URL is set correctly\
- (if it's not - set proper '--ingestion-url' option)
-
- Full logs can be found in"""
+ "Error performing batch publication while processing 'target/test-classes/"
+ + "dev/streamx/cli/command/ingestion/batch/valid/publish/page/index.html' file.\n"
+ + "\n"
+ + "Details:\n"
+ + "Ingestion REST error: unknown host\n"
+ + "\n"
+ + "Full logs can be found in quarkus.log"
);
}
}
@@ -206,45 +177,14 @@ class AuthorizedTest {
@Test
public void shouldPublishAuthorizedUsing(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("batch",
+ LaunchResult result = launcher.launch(BatchCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- "publish", "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid");
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/publish/page");
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
.withHeader("Authorization", new ContainsPattern(AuthorizedProfile.AUTH_TOKEN)));
}
}
-
- @Override
- protected void initializeWiremock() {
- setupMockPublicationResponse(
- CHANNEL,
- SC_ACCEPTED,
- IngestionResult.of(new SuccessResult(123456L, KEY))
- );
-
- setupMockPublicationResponse(
- UNSUPPORTED_CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("UNSUPPORTED_CHANNEL",
- "Channel " + UNSUPPORTED_CHANNEL + " is unsupported. Supported channels: " + CHANNEL
- )
- );
-
- setupMockChannelsSchemasResponse();
- }
-
- private static void setupMockPublicationResponse(String channel, int httpStatus,
- Object response) {
- ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(httpStatus)
- .withBody(response == null ? null : Json.write(response))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON);
-
- wm.stubFor(WireMock.post(getPublicationPath(channel))
- .willReturn(mockResponse));
- }
}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchUnpublishCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchUnpublishCommandTest.java
index 0b93045c..a43f65ed 100644
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchUnpublishCommandTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/BatchUnpublishCommandTest.java
@@ -1,27 +1,12 @@
package dev.streamx.cli.command.ingestion.batch;
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static dev.streamx.cli.OsUtils.ESCAPED_LINE_SEPARATOR;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST;
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.matching.ContainsPattern;
import dev.streamx.cli.command.ingestion.AuthorizedProfile;
import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
import dev.streamx.cli.command.ingestion.UnauthorizedProfile;
-import dev.streamx.clients.ingestion.publisher.FailureResult;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
import io.quarkus.test.junit.TestProfile;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainLauncher;
@@ -31,10 +16,6 @@
public class BatchUnpublishCommandTest extends BaseIngestionCommandTest {
- private static final String CHANNEL = "pages";
- private static final String UNSUPPORTED_CHANNEL = "images";
- private static final String KEY = "index.html";
-
@Nested
@QuarkusMainTest
@TestProfile(UnauthorizedProfile.class)
@@ -44,10 +25,9 @@ class UnauthorizedTest {
public void shouldUnpublishUsingIngestionClient(QuarkusMainLauncher launcher) {
// when
LaunchResult result = launcher.launch(
- "batch",
+ BatchCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- "unpublish",
- "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid");
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page");
// then
expectSuccess(result);
@@ -57,32 +37,16 @@ public void shouldUnpublishUsingIngestionClient(QuarkusMainLauncher launcher) {
public void shouldUnpublishUsingUnauthorizedIngestionClient(QuarkusMainLauncher launcher) {
// when
LaunchResult result = launcher.launch(
- "batch",
+ BatchCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- "unpublish",
- "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid");
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page");
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("unpublish")))
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
.withoutHeader("Authorization"));
}
-
- @Test
- public void shouldRejectUnknownChannel(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch(
- "batch",
- "--ingestion-url=" + getIngestionUrl(),
- "unpublish",
- "target/test-classes/dev/streamx/cli/command/ingestion/batch/unknown-channel");
-
- // then
- expectError(result,
- "Channel 'images' not found. Available channels: [pages]");
- }
}
@Nested
@@ -94,63 +58,30 @@ class AuthorizedTest {
public void shouldUnpublishUsingAuthorizedIngestionClient(QuarkusMainLauncher launcher) {
// when
LaunchResult result = launcher.launch(
- "batch",
+ BatchCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- "unpublish",
- "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid");
+ "target/test-classes/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page");
// then
expectSuccess(result);
wm.verify(
- postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
+ postRequestedFor(urlEqualTo(PUBLICATION_PATH))
+ .withRequestBody(new CloudEventJsonMatcher("""
{
- "key": "%s",
- "action" : "unpublish",
- "eventTime" : null,
- "properties" : {
- "sx:type" : "page/sub-page"
- },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "Hello World!
%s"
- }
- }
+ "specversion" : "1.0",
+ "id" : "81099e4d-a4ec-44e9-8d5c-8f177af8d22c",
+ "source" : "source",
+ "type" : "page_unpublish",
+ "datacontenttype":"application/json",
+ "subject" : "page/index.html",
+ "time" : "2025-12-23T11:59:29.946127Z",
+ "data" : {
+ "type" : "page/sub-page"
}
}
- """.formatted("valid/" + KEY, ESCAPED_LINE_SEPARATOR), true, true))
+ """))
.withHeader("Authorization", new ContainsPattern(AuthorizedProfile.AUTH_TOKEN)));
}
}
-
- @Override
- protected void initializeWiremock() {
- setupMockResponse(
- CHANNEL,
- SC_ACCEPTED,
- IngestionResult.of(new SuccessResult(123456L, KEY))
- );
-
- setupMockResponse(
- UNSUPPORTED_CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("UNSUPPORTED_CHANNEL",
- "Channel " + UNSUPPORTED_CHANNEL + " is unsupported. Supported channels: " + CHANNEL
- )
- );
- }
-
- private static void setupMockResponse(String channel, int httpStatus, Object response) {
- ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(httpStatus)
- .withBody(Json.write(response))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON);
-
- wm.stubFor(WireMock.post(getPublicationPath(channel))
- .willReturn(mockResponse));
-
- setupMockChannelsSchemasResponse();
- }
}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/batch/CloudEventJsonMatcher.java b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/CloudEventJsonMatcher.java
new file mode 100644
index 00000000..2cbdaa9c
--- /dev/null
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/batch/CloudEventJsonMatcher.java
@@ -0,0 +1,23 @@
+package dev.streamx.cli.command.ingestion.batch;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.github.tomakehurst.wiremock.matching.EqualToJsonPattern;
+import com.github.tomakehurst.wiremock.matching.MatchResult;
+
+class CloudEventJsonMatcher extends EqualToJsonPattern {
+
+ CloudEventJsonMatcher(@JsonProperty("equalToJson") String json) {
+ super(maskIdAndTime(json), null, null);
+ }
+
+ private static String maskIdAndTime(String cloudEventJson) {
+ return cloudEventJson
+ .replaceFirst("\"id\" *: *\"[^\"]+\"", "\"id\" : \"[MASKED]\"")
+ .replaceFirst("\"time\" *: *\"[^\"]+\"", "\"time\" : \"[MASKED]\"");
+ }
+
+ @Override
+ public MatchResult match(String value) {
+ return super.match(maskIdAndTime(value));
+ }
+}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishCommandTest.java
deleted file mode 100644
index 214fa176..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishCommandTest.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish;
-
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
-import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST;
-
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.common.Json;
-import com.github.tomakehurst.wiremock.matching.ContainsPattern;
-import dev.streamx.cli.command.ingestion.AuthorizedProfile;
-import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
-import dev.streamx.cli.command.ingestion.UnauthorizedProfile;
-import dev.streamx.clients.ingestion.publisher.FailureResult;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
-import io.quarkus.test.junit.TestProfile;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-public class PublishCommandTest extends BaseIngestionCommandTest {
-
- private static final String CHANNEL = "pages";
- private static final String INVALID_PAYLOAD_REQUEST_CHANNEL = "bad-request-channel";
- private static final String UNSUPPORTED_CHANNEL = "images";
- private static final String KEY = "index.html";
- private static final String DATA = """
- {"content": {"bytes": "Hello World!
"}}""";
- private static final String PAYLOAD_PATH = "target/test-classes/"
- + "dev/streamx/cli/command/ingestion/publish/payload/helloworld-payload.json";
-
- @Nested
- @QuarkusMainTest
- @TestProfile(UnauthorizedProfile.class)
- class UnauthorizedTest {
-
- @Test
- public void shouldHandleInvalidPayloadFromRestIngestionApi(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + DATA,
- INVALID_PAYLOAD_REQUEST_CHANNEL, KEY);
-
- // then
- expectError(result,
- "Channel 'bad-request-channel' not found. Available channels: [pages]");
- }
-
- @Test
- public void shouldRejectInvalidDataJson(QuarkusMainLauncher launcher) {
- // given
- String invalidJson = "asdf{][";
-
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + invalidJson,
- CHANNEL, KEY);
-
- // then
- expectError(result, """
- Payload could not be parsed.
-
- Supplied payload:
- asdf{][
-
- Make sure that:
- * it's valid JSON,
- * object property names are properly single-quoted (') or double-quoted ("),
- * strings are properly single-quoted (') or double-quoted (")
-
- Details: Unrecognized token 'asdf': was expecting (JSON String, Number, Array, Object\
- or token 'null', 'true' or 'false')
- at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled);\
- line: 1, column: 6]""");
- }
-
- @Test
- public void shouldPublishUsingIngestionClient(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + DATA,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
- .withoutHeader("Authorization"));
- }
-
- @Test
- public void shouldPublishUnauthorizedData(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + DATA,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
- {
- "key" : "index.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : { },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "Hello World!
"
- }
- }
- }
- }
- """))
- .withoutHeader("Authorization"));
- }
-
- @Test
- public void shouldPublishBinaryData(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-b=content.bytes=Hello!
",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
- {
- "key" : "index.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : { },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "Hello!
"
- }
- }
- }
- }
- """))
- .withoutHeader("Authorization"));
- }
-
- @Test
- public void shouldPublishUsingPayloadFromPayloadArg(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- CHANNEL, KEY, PAYLOAD_PATH);
-
- // then
- expectSuccess(result);
- }
-
- @Test
- public void shouldRejectUnknownChannel(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + DATA,
- UNSUPPORTED_CHANNEL, KEY);
-
- // then
- expectError(result,
- "Channel 'images' not found. Available channels: [pages]");
- }
-
- @Test
- public void shouldRejectWrongIngestionUrl(QuarkusMainLauncher launcher) {
- // when
- String ingestionServiceUrl = "http://aaa.bbb.ccc";
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + ingestionServiceUrl,
- "-j=" + DATA,
- CHANNEL, KEY);
-
- // then
- expectError(result,
- """
- Unable to connect to the ingestion service.
-
- The ingestion service URL: http://aaa.bbb.ccc
-
- Verify:
- * if the mesh is up and running,
- * if the ingestion service URL is set correctly\
- (if it's not - set proper '--ingestion-url' option)
-
- Full logs can be found in"""
- );
- }
- }
-
- @Nested
- @QuarkusMainTest
- @TestProfile(AuthorizedProfile.class)
- class AuthorizedTest {
-
- @Test
- public void shouldPublishAuthorizedUsing(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j=" + DATA,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
- .withHeader("Authorization", new ContainsPattern(AuthorizedProfile.AUTH_TOKEN)));
- }
- }
-
- @Override
- protected void initializeWiremock() {
- setupMockPublicationResponse(
- CHANNEL,
- SC_ACCEPTED,
- IngestionResult.of(new SuccessResult(123456L, KEY))
- );
-
- setupMockPublicationResponse(
- INVALID_PAYLOAD_REQUEST_CHANNEL,
- SC_BAD_REQUEST,
- IngestionResult.of(new FailureResult("INVALID_PUBLICATION_PAYLOAD", "Error message"))
- );
-
- setupMockPublicationResponse(
- UNSUPPORTED_CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("UNSUPPORTED_CHANNEL",
- "Channel " + UNSUPPORTED_CHANNEL + " is unsupported. Supported channels: " + CHANNEL
- )
- );
-
- setupMockChannelsSchemasResponse();
- }
-
- private static void setupMockPublicationResponse(String channel, int httpStatus,
- Object response) {
- ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(httpStatus)
- .withBody(response == null ? null : Json.write(response))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON);
-
- wm.stubFor(WireMock.post(getPublicationPath(channel))
- .willReturn(mockResponse));
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishPayloadCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishPayloadCommandTest.java
deleted file mode 100644
index 66e4b467..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/PublishPayloadCommandTest.java
+++ /dev/null
@@ -1,305 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish;
-
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
-import static com.github.tomakehurst.wiremock.client.WireMock.post;
-import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-
-import com.github.tomakehurst.wiremock.common.Json;
-import com.github.tomakehurst.wiremock.matching.ContainsPattern;
-import com.github.tomakehurst.wiremock.matching.StringValuePattern;
-import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import org.junit.jupiter.api.Test;
-
-@QuarkusMainTest
-public class PublishPayloadCommandTest extends BaseIngestionCommandTest {
-
- private static final String CHANNEL = "pages";
- private static final String KEY = "index.html";
- private static final String DATA = """
- {"content": {"bytes": "Hello World!
"}}""";
- private static final String TEST_RESOURCES = "file://target/test-classes/";
-
- @Test
- public void shouldRejectInvalidJsonPath(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j", DATA,
- "-s", "content.b[]ytes=Hello changed value!
",
- CHANNEL, KEY);
-
- // then
- expectError(result, """
- Could not find valid JSONPath expression in given option.
-
- Option: content.b[]ytes=Hello changed value!
-
- Verify:
- * if given JSONPath expression is valid \
- (according to https://github.com/json-path/JsonPath docs),
- * if '=' is present in option""");
- }
-
- @Test
- public void shouldRejectNonExistingFile(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=file://nana",
- CHANNEL, KEY);
-
- // then
- expectError(result, """
- File does not exist.
- Path: nana""");
- }
-
- @Test
- public void shouldRejectInvalidFile(QuarkusMainLauncher launcher) {
- // given
- String corruptedPathArg =
- TEST_RESOURCES + "dev/streamx/cli/command/ingestion/publish/payload/invalid-payload.json";
-
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j", "content.bytes=" + corruptedPathArg,
- CHANNEL, KEY);
-
- // then
- expectError(result, """
- Replacement is not recognised as valid JSON.
-
- Supplied JSONPath expression:
- $['content']['bytes']
- Supplied replacement:
- file://target/test-classes/dev/streamx/cli/command/ingestion/publish/payload/\
- invalid-payload.json
-
- Make sure that:
- * you need a JSON node as replacement
- (alternatively use '-s' to specify raw text replacement
- or use '-b' to specify is binary replacement),
- * it's valid JSON,
- * object property names are properly single-quoted (') or double-quoted ("),
- * strings are properly single-quoted (') or double-quoted (")
-
- Details: Unexpected end-of-input: expected close marker for Object (start marker\
- at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled);\
- line: 1, column: 1])
- at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled);\
- line: 3, column: 1]""");
- }
-
- @Test
- public void shouldPublishReplacedJsonPath(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=Hello changed value!
",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(
- equalToJson(
- buildResponseWith(
- "{\"content\": {\"bytes\": \"Hello changed value!
\"}}"))));
- }
-
- @Test
- public void shouldPublishWithProperties(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=Hello changed value!
",
- "-p", "sx:type=type/subtype",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(
- equalToJson(
- buildResponseWith(
- "{\"content\": {\"bytes\": \"Hello changed value!
\"}}",
- "{ \"sx:type\": \"type/subtype\" }"))));
- }
-
- @Test
- public void shouldPublishReplacedWithObjectJsonPath(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j", DATA,
- "-j", "content={'bytes':'Hello changed value!
'}",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(PublishPayloadCommandTest.CHANNEL)))
- .withRequestBody(
- equalToJson(
- buildResponseWith(
- "{\"content\": {\"bytes\": \"Hello changed value!
\"}}"))));
- }
-
- @Test
- public void shouldPublishReplacedFromFile(QuarkusMainLauncher launcher) {
- // given
- String arg = TEST_RESOURCES + "dev/streamx/cli/command/ingestion/publish/payload/payload.json";
-
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j", "content.bytes=" + arg,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson(buildResponseWith("""
- {"content": {"bytes": {"nana": "lele"}}}"""))));
- }
-
- @Test
- public void shouldPublishReplacedWithNull(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-j", DATA,
- "-j", "content.bytes=",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson(buildResponseWith("""
- {"content": {"bytes": null}}"""))));
- }
-
- @Test
- public void shouldPublishTwiceReplacedJsonPath(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=Hello changed value!
",
- "-s", "$..bytes=bytes",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson(buildResponseWith("{\"content\": {\"bytes\": \"bytes\"}}"))));
- }
-
- @Test
- public void shouldPublishReplacedJsonPathWithStringValue(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=Hello changed value!
",
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(
- equalToJson(buildResponseWith(
- "{\"content\": {\"bytes\": \"Hello changed value!
\"}}"))));
- }
-
- @Test
- public void shouldPublishReplacedJsonPathWithStringValueFromFile(QuarkusMainLauncher launcher) {
- // given
- String arg = TEST_RESOURCES + "dev/streamx/cli/command/ingestion/publish/payload/raw-text.txt";
-
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=" + arg,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(
- equalToJson(buildResponseWith(
- "{\"content\": {\"bytes\": \"This works ąćpretty well...
\"}}"))));
- }
-
- @Test
- public void shouldPublishReplacedJsonPathWithBinaryValue(QuarkusMainLauncher launcher) {
- // given
- String arg =
- TEST_RESOURCES + "dev/streamx/cli/command/ingestion/publish/payload/example-image.png";
-
- // when
- LaunchResult result = launcher.launch("publish",
- "--ingestion-url=" + getIngestionUrl(),
- "-s", "content.bytes=" + arg,
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- StringValuePattern matchingPngFileContent = matchingJsonPath(
- "payload[\"dev.streamx.blueprints.data.Page\"].content.bytes",
- new ContainsPattern("PNG")
- );
-
- wm.verify(postRequestedFor(urlEqualTo(
- getPublicationPath(CHANNEL)))
- .withRequestBody(matchingPngFileContent));
- }
-
- private String buildResponseWith(String content) {
- return buildResponseWith(content, "{ }");
- }
-
- private String buildResponseWith(String content, String properties) {
- return
- """
- {
- "key" : "index.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : %s,
- "payload" : {
- "dev.streamx.blueprints.data.Page" : %s
- }
- }
- """.formatted(properties, content);
- }
-
-
- @Override
- protected void initializeWiremock() {
- var result = IngestionResult.of(new SuccessResult(123456L, KEY));
- wm.stubFor(
- post(getPublicationPath(CHANNEL))
- .willReturn(responseDefinition().withStatus(SC_ACCEPTED).withBody(Json.write(result))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON)));
-
- setupMockChannelsSchemasResponse();
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/JsonPathExtractorTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/JsonPathExtractorTest.java
deleted file mode 100644
index 6fa615f5..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/JsonPathExtractorTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.params.provider.Arguments.arguments;
-
-import com.jayway.jsonpath.JsonPath;
-import java.util.stream.Stream;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.junit.jupiter.params.provider.ValueSource;
-
-class JsonPathExtractorTest {
-
- JsonPathExtractor cut = new JsonPathExtractor();
-
- @ParameterizedTest
- @ValueSource(strings = {
- "nanaLele",
- "=",
- "$..book[?(@.price <= $['expensive'])]"
- })
- void shouldNotExtractPair(String arg) {
- // when
- var result = cut.extract(arg);
-
- // then
- assertThat(result).isNotNull();
- assertThat(result.isPresent()).isFalse();
- }
-
- @ParameterizedTest
- @MethodSource("extractPair")
- void shouldExtractPair(String arg, JsonPath key, String newValue) {
- // when
- var result = cut.extract(arg);
-
- // then
- assertThat(result).isNotNull();
- assertThat(result.isPresent()).isTrue();
- assertThat(result.get().getKey().getPath()).isEqualTo(key.getPath());
- assertThat(result.get().getValue()).isEqualTo(newValue);
- }
-
- static Stream extractPair() {
- return Stream.of(
- arguments("nana.lele=newValue", JsonPath.compile("nana.lele"), "newValue"),
- arguments("$..book[?(@.author =~ /.*REES/i)]=newValue",
- JsonPath.compile("$..book[?(@.author =~ /.*REES/i)]"), "newValue"),
- arguments("jsonPath=", JsonPath.compile("jsonPath"), ""),
- arguments("$..*[?(@.*=='=')]===", JsonPath.compile("$..*[?(@.*=='=')]"), "=="),
- arguments("===", JsonPath.compile("="), "=")
- );
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/PayloadResolverTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/PayloadResolverTest.java
deleted file mode 100644
index f43271b5..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/publish/payload/PayloadResolverTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package dev.streamx.cli.command.ingestion.publish.payload;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchException;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import dev.streamx.cli.command.ingestion.publish.PayloadArgument;
-import dev.streamx.cli.exception.JsonPathReplacementException;
-import dev.streamx.cli.exception.PayloadException;
-import io.quarkus.test.junit.QuarkusTest;
-import jakarta.inject.Inject;
-import java.util.List;
-import org.junit.jupiter.api.Test;
-
-@QuarkusTest
-class PayloadResolverTest {
-
- private static final JsonNode EXAMPLE_JSON_NODE;
- private static final String TEST_RESOURCES = "file://target/test-classes";
-
- static {
- try {
- EXAMPLE_JSON_NODE = new ObjectMapper().readTree("{\"nana\": \"lele\"}");
- } catch (JsonProcessingException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Inject
- PayloadResolver cut;
-
- @Test
- void shouldValidateMissingPayload() {
- // when
- Exception exception = catchException(() -> cut.createPayload(List.of()));
-
- // then
- assertThat(exception).isInstanceOf(PayloadException.class);
- assertThat(exception).hasMessageContaining("Payload definition not found.");
- }
-
- @Test
- void shouldValidateData() {
- // given
- String corruptedArg = """
- {"nana": " """;
-
- // when
- Exception exception = catchException(() -> createPayload(corruptedArg));
-
- // then
- assertThat(exception).isInstanceOf(PayloadException.class);
- assertThat(exception).hasMessageContaining("Payload could not be parsed.");
- }
-
- @Test
- void shouldValidatePath() {
- // given
- String corruptedArg = "file://nonexisting";
-
- // when
- Exception exception = catchException(() -> createPayload(corruptedArg));
-
- // then
- assertThat(exception).isInstanceOf(PayloadException.class);
- assertThat(exception).hasMessageContaining("File does not exist.");
- }
-
- @Test
- void shouldValidateFileContent() {
- // given
- String corruptedPathArg =
- TEST_RESOURCES + "/dev/streamx/cli/command/ingestion/publish/payload/invalid-payload.json";
-
- // when
- Exception exception = catchException(() -> createPayload(corruptedPathArg));
-
- // then
- assertThat(exception).isInstanceOf(PayloadException.class);
- assertThat(exception).hasMessageContaining("Payload could not be parsed.");
- }
-
- @Test
- void shouldConvertDirectArgToJsonNode() {
- // given
- String arg = """
- {"nana": "lele"}""";
-
- // when
- JsonNode payload = createPayload(arg);
-
- // then
- assertThat(payload).isEqualTo(EXAMPLE_JSON_NODE);
- }
-
- @Test
- void shouldExtractDataFromFileAndConvertToJsonNode() {
- // given
- String arg = TEST_RESOURCES + "/dev/streamx/cli/command/ingestion/publish/payload/payload.json";
-
- // when
- JsonNode payload = createPayload(arg);
-
- // then
- assertThat(payload).isEqualTo(EXAMPLE_JSON_NODE);
- }
-
- @Test
- void shouldValidateMissingJsonPathOfNonJsonNodePayload() {
- // given
- String arg = TEST_RESOURCES + "/dev/streamx/cli/command/ingestion/publish/payload/payload.json";
-
- // when
- Exception exception = catchException(() ->
- cut.createPayload(List.of(
- PayloadArgument.ofJsonNode(arg),
- PayloadArgument.ofBinary("$..ana"))
- )
- );
-
- // then
- assertThat(exception).isInstanceOf(JsonPathReplacementException.class);
- }
-
- @Test
- void shouldValidateNonexistingJsonPathOfNonJsonNodePayload() {
- // given
- String arg = TEST_RESOURCES + "/dev/streamx/cli/command/ingestion/publish/payload/payload.json";
-
- // when
- Exception exception = catchException(() ->
- cut.createPayload(List.of(
- PayloadArgument.ofJsonNode(arg),
- PayloadArgument.ofBinary("$..ana=lele"))
- )
- );
-
- // then
- assertThat(exception).isInstanceOf(JsonPathReplacementException.class);
- }
-
- public JsonNode createPayload(String payload) {
- return cut.createPayload(List.of(PayloadArgument.ofJsonNode(payload)));
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/stream/StreamCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/stream/StreamCommandTest.java
index 45c2bec1..cc721bea 100644
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/stream/StreamCommandTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/stream/StreamCommandTest.java
@@ -1,25 +1,12 @@
package dev.streamx.cli.command.ingestion.stream;
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST;
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.matching.ContainsPattern;
import dev.streamx.cli.command.ingestion.AuthorizedProfile;
import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
import dev.streamx.cli.command.ingestion.UnauthorizedProfile;
-import dev.streamx.clients.ingestion.publisher.FailureResult;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
import io.quarkus.test.junit.TestProfile;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainLauncher;
@@ -30,11 +17,6 @@
@QuarkusMainTest
class StreamCommandTest extends BaseIngestionCommandTest {
- private static final String CHANNEL = "pages";
- private static final String INVALID_PAYLOAD_REQUEST_CHANNEL = "bad-request-channel";
- private static final String UNSUPPORTED_CHANNEL = "images";
- private static final String KEY = "index.html";
-
@Nested
@QuarkusMainTest
@TestProfile(UnauthorizedProfile.class)
@@ -43,41 +25,21 @@ class UnauthorizedTest {
@Test
public void shouldPublishUsingIngestionClient(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("stream",
+ LaunchResult result = launcher.launch(StreamCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- CHANNEL,
"target/test-classes/dev/streamx/cli/command/ingestion/stream/valid-json.stream");
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
- .withoutHeader("Authorization"));
- }
-
- @Test
- public void shouldPublishToUnsupportedChannel(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("stream",
- "--ingestion-url=" + getIngestionUrl(),
- UNSUPPORTED_CHANNEL,
- "target/test-classes/dev/streamx/cli/command/ingestion/stream/valid-json.stream");
-
- // then
- expectError(result, "Ingestion REST endpoint known error. "
- + "Code: UNSUPPORTED_CHANNEL. Message: Channel images is unsupported. "
- + "Supported channels: pages");
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(UNSUPPORTED_CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
.withoutHeader("Authorization"));
}
@Test
public void shouldRejectInvalidJson(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("stream",
+ LaunchResult result = launcher.launch(StreamCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- CHANNEL,
"target/test-classes/dev/streamx/cli/command/ingestion/stream/invalid-json.stream");
// then
@@ -103,9 +65,8 @@ public void shouldRejectInvalidJson(QuarkusMainLauncher launcher) {
@Test
public void shouldRejectIllegalJson(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("stream",
+ LaunchResult result = launcher.launch(StreamCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- CHANNEL,
"target/test-classes/dev/streamx/cli/command/ingestion/stream/illegal-json.stream");
// then
@@ -114,15 +75,16 @@ public void shouldRejectIllegalJson(QuarkusMainLauncher launcher) {
+ "stream/illegal-json.stream' file.\n"
+ "\n"
+ "Details:\n"
- + "Missing or invalid 'action' field\n");
+ + "Invalid data: Missing mandatory specversion attribute\n"
+ + "\n"
+ + "Full logs can be found in quarkus.log");
}
@Test
public void shouldRejectInvalidJsonSeparator(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("stream",
+ LaunchResult result = launcher.launch(StreamCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- CHANNEL,
"target/test-classes/dev/streamx/cli/command/ingestion/stream"
+ "/invalid-separated-json.stream"
);
@@ -142,7 +104,7 @@ public void shouldRejectInvalidJsonSeparator(QuarkusMainLauncher launcher) {
+ "Details: Unexpected character (',' (code 44)): expected a value\n"
+ " at [Source: REDACTED ("
+ "`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); "
- + "line: 15, column: 2]");
+ + "line: 8, column: 2]");
}
}
@@ -154,52 +116,14 @@ class AuthorizedTest {
@Test
public void shouldPublishAuthorizedUsing(QuarkusMainLauncher launcher) {
// when
- LaunchResult result = launcher.launch("stream",
+ LaunchResult result = launcher.launch(StreamCommand.COMMAND_NAME,
"--ingestion-url=" + getIngestionUrl(),
- CHANNEL,
"target/test-classes/dev/streamx/cli/command/ingestion/stream/valid-json.stream");
// then
expectSuccess(result);
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("publish")))
+ wm.verify(postRequestedFor(urlEqualTo(PUBLICATION_PATH))
.withHeader("Authorization", new ContainsPattern(AuthorizedProfile.AUTH_TOKEN)));
}
}
-
- @Override
- protected void initializeWiremock() {
- setupMockPublicationResponse(
- CHANNEL,
- SC_ACCEPTED,
- IngestionResult.of(new SuccessResult(123456L, KEY))
- );
-
- setupMockPublicationResponse(
- INVALID_PAYLOAD_REQUEST_CHANNEL,
- SC_BAD_REQUEST,
- IngestionResult.of(new FailureResult("INVALID_PUBLICATION_PAYLOAD", "Error message"))
- );
-
- setupMockPublicationResponse(
- UNSUPPORTED_CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("UNSUPPORTED_CHANNEL",
- "Channel " + UNSUPPORTED_CHANNEL + " is unsupported. Supported channels: " + CHANNEL
- )
- );
-
- setupMockChannelsSchemasResponse();
- }
-
- private static void setupMockPublicationResponse(String channel, int httpStatus,
- Object response) {
- ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(httpStatus)
- .withBody(response == null ? null : Json.write(response))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON);
-
- wm.stubFor(WireMock.post(getPublicationPath(channel))
- .willReturn(mockResponse));
- }
}
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64EncoderTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64EncoderTest.java
new file mode 100644
index 00000000..0f3e0a07
--- /dev/null
+++ b/core/src/test/java/dev/streamx/cli/command/ingestion/stream/parser/JsonBase64EncoderTest.java
@@ -0,0 +1,79 @@
+package dev.streamx.cli.command.ingestion.stream.parser;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class JsonBase64EncoderTest {
+
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+ public static final String INITIAL_JSON = """
+ {
+ "foo": {
+ "bar": "foobar"
+ },
+ "foo2": "bar2"
+ }""";
+
+ static Stream testArguments() {
+ return Stream.of(
+ // happy path
+ arguments(
+ INITIAL_JSON,
+ "/foo/bar",
+ INITIAL_JSON.replace("foobar", "Zm9vYmFy")
+ ),
+
+ // missing leading slash in the jsonFieldsAsBase64 should be automatically added
+ arguments(
+ INITIAL_JSON,
+ "foo/bar",
+ INITIAL_JSON.replace("foobar", "Zm9vYmFy")
+ ),
+
+ // attempting to encode a parent node that is not a text node
+ arguments(
+ INITIAL_JSON,
+ "/foo",
+ INITIAL_JSON
+ ),
+
+ // json doesn't contain the requested field
+ arguments(
+ INITIAL_JSON,
+ "bar",
+ INITIAL_JSON
+ ),
+
+ // invalid path of field
+ arguments(
+ INITIAL_JSON,
+ "/a/)#Q(*%Y@W$Tbngow23p0t[';'\\325/b",
+ INITIAL_JSON
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("testArguments")
+ void shouldEncodeFields(String sourceJson, String jsonFieldsAsBase64, String expectedResultJson)
+ throws Exception {
+ // given
+ JsonNode jsonNode = objectMapper.readTree(sourceJson);
+
+ // when
+ JsonBase64Encoder.encodeFields(jsonNode, List.of(jsonFieldsAsBase64));
+
+ // then
+ JsonNode expectedNode = objectMapper.readTree(expectedResultJson);
+ assertThat(jsonNode.toPrettyString()).isEqualTo(expectedNode.toPrettyString());
+ }
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommandTest.java b/core/src/test/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommandTest.java
deleted file mode 100644
index e393170a..00000000
--- a/core/src/test/java/dev/streamx/cli/command/ingestion/unpublish/UnpublishCommandTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package dev.streamx.cli.command.ingestion.unpublish;
-
-import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.responseDefinition;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
-import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
-import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
-import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.APPLICATION_JSON;
-import static com.github.tomakehurst.wiremock.common.ContentTypes.CONTENT_TYPE;
-import static org.apache.hc.core5.http.HttpStatus.SC_ACCEPTED;
-import static org.apache.hc.core5.http.HttpStatus.SC_BAD_REQUEST;
-
-import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
-import com.github.tomakehurst.wiremock.client.WireMock;
-import com.github.tomakehurst.wiremock.common.Json;
-import com.github.tomakehurst.wiremock.matching.ContainsPattern;
-import dev.streamx.cli.command.ingestion.AuthorizedProfile;
-import dev.streamx.cli.command.ingestion.BaseIngestionCommandTest;
-import dev.streamx.cli.command.ingestion.UnauthorizedProfile;
-import dev.streamx.clients.ingestion.publisher.FailureResult;
-import dev.streamx.clients.ingestion.publisher.IngestionResult;
-import dev.streamx.clients.ingestion.publisher.SuccessResult;
-import io.quarkus.test.junit.TestProfile;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-public class UnpublishCommandTest extends BaseIngestionCommandTest {
-
- private static final String CHANNEL = "pages";
- private static final String UNSUPPORTED_CHANNEL = "images";
- private static final String KEY = "index.html";
-
- @Nested
- @QuarkusMainTest
- @TestProfile(UnauthorizedProfile.class)
- class UnauthorizedTest {
-
- @Test
- public void shouldUnpublishUsingIngestionClient(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + getIngestionUrl(),
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
- }
-
- @Test
- public void shouldUnpublishUsingUnauthorizedIngestionClient(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + getIngestionUrl(),
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
-
- wm.verify(postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(matchingJsonPath("action", equalTo("unpublish")))
- .withoutHeader("Authorization"));
- }
-
- @Test
- public void shouldRejectUnknownChannel(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + getIngestionUrl(),
- UNSUPPORTED_CHANNEL, KEY);
-
- // then
- expectError(result,
- "Ingestion REST endpoint known error. Code: UNSUPPORTED_CHANNEL. "
- + "Message: Channel images is unsupported. Supported channels: pages");
- }
- }
-
- @Nested
- @QuarkusMainTest
- @TestProfile(AuthorizedProfile.class)
- class AuthorizedTest {
-
- @Test
- public void shouldUnpublishUsingAuthorizedIngestionClient(QuarkusMainLauncher launcher) {
- // when
- LaunchResult result = launcher.launch("unpublish",
- "--ingestion-url=" + getIngestionUrl(),
- CHANNEL, KEY);
-
- // then
- expectSuccess(result);
-
- wm.verify(
- postRequestedFor(urlEqualTo(getPublicationPath(CHANNEL)))
- .withRequestBody(equalToJson("""
- {
- "key": "%s",
- "payload": null,
- "action": "unpublish"
- }
- """.formatted(KEY), true, true))
- .withHeader("Authorization", new ContainsPattern(AuthorizedProfile.AUTH_TOKEN)));
- }
- }
-
- @Override
- protected void initializeWiremock() {
- setupMockResponse(
- CHANNEL,
- SC_ACCEPTED,
- IngestionResult.of(new SuccessResult(123456L, KEY))
- );
-
- setupMockResponse(
- UNSUPPORTED_CHANNEL,
- SC_BAD_REQUEST,
- new FailureResult("UNSUPPORTED_CHANNEL",
- "Channel " + UNSUPPORTED_CHANNEL + " is unsupported. Supported channels: " + CHANNEL
- )
- );
- }
-
- private static void setupMockResponse(String channel, int httpStatus, Object response) {
- ResponseDefinitionBuilder mockResponse = responseDefinition()
- .withStatus(httpStatus)
- .withBody(Json.write(response))
- .withHeader(CONTENT_TYPE, APPLICATION_JSON);
-
- wm.stubFor(WireMock.post(getPublicationPath(channel))
- .willReturn(mockResponse));
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/init/GitClientTest.java b/core/src/test/java/dev/streamx/cli/command/init/GitClientTest.java
deleted file mode 100644
index 711f4626..00000000
--- a/core/src/test/java/dev/streamx/cli/command/init/GitClientTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.assertj.core.api.Assertions.catchThrowableOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import dev.streamx.cli.exception.GitException;
-import dev.streamx.cli.util.os.OsCommandStrategy;
-import dev.streamx.cli.util.os.ProcessBuilder;
-import io.quarkus.test.InjectMock;
-import io.quarkus.test.component.QuarkusComponentTest;
-import jakarta.inject.Inject;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.api.io.TempDir;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-@QuarkusComponentTest
-@ExtendWith(MockitoExtension.class)
-class GitClientTest {
-
- @Inject
- GitClient gitClient;
-
- @InjectMock
- OsCommandStrategy strategy;
-
- @Mock
- ProcessBuilder processBuilder;
-
- @Mock
- Process process;
-
- @TempDir
- Path temp;
-
- @Test
- void shouldValidateGitOutput() throws IOException {
- // given
- mockProcess(0);
- String processOutput = "gitOtherOutput";
- mockProcessOutput(processOutput);
-
- // when
- Throwable throwable = catchThrowable(() -> gitClient.validateGitInstalled());
-
- // then
- assertThat(throwable).isInstanceOf(GitException.class)
- .hasMessage("""
- Could not find a Git executable.
-
- Make sure that:
- * Git is installed,
- * Git is available on $PATH""");
- }
-
- @Test
- void shouldValidateGitInstalled() throws IOException {
- // given
- mockProcess(127);
- String processOutput = "git version";
- mockProcessOutput(processOutput);
-
- // when
- Throwable throwable = catchThrowable(() -> gitClient.validateGitInstalled());
-
- // then
- assertThat(throwable).isInstanceOf(GitException.class)
- .hasMessage("""
- Could not find a Git executable.
-
- Make sure that:
- * Git is installed,
- * Git is available on $PATH""");
- }
-
- @Test
- void shouldCloneRepository() throws IOException, InterruptedException {
- // given
- mockProcess(0);
-
- // when
- gitClient.clone("mockedUrl", "mockedOutputDir");
-
- // then
- verify(processBuilder).addEnv("GIT_TERMINAL_PROMPT", "0");
- verify(processBuilder).start();
- verify(process).waitFor();
- verify(process).exitValue();
- }
-
- @Test
- void shouldFailCloningRepository() throws IOException {
- // given
- mockProcess(1);
-
- // when
- GitException ex = catchThrowableOfType(() ->
- gitClient.clone("mockedUrl", "mockedOutputDir"),
- GitException.class);
-
- // then
- assertThat(ex).isNotNull();
- assertThat(ex.getProcess()).isEqualTo(process);
- }
-
- @Test
- void shouldRemoveDotGitDir() throws IOException {
- // given
- Path dotGitDirectory = temp.resolve(".git");
- Files.createDirectory(dotGitDirectory);
- Files.writeString(dotGitDirectory.resolve("config"),
- "someConfig", StandardCharsets.UTF_8);
-
- // when
- gitClient.removeGitMetadata(temp.toAbsolutePath().toString());
-
- // then
- assertThat(Files.exists(dotGitDirectory)).isFalse();
- }
-
- private void mockProcess(int exitValue) throws IOException {
- when(strategy.create(any())).thenReturn(processBuilder);
- when(processBuilder.start()).thenReturn(process);
- when(process.exitValue()).thenReturn(exitValue);
- }
-
- private void mockProcessOutput(String processOutput) {
- when(process.getInputStream()).thenReturn(new ByteArrayInputStream(processOutput.getBytes(
- StandardCharsets.UTF_8)));
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/init/GitClientUtils.java b/core/src/test/java/dev/streamx/cli/command/init/GitClientUtils.java
deleted file mode 100644
index 3bc98bb6..00000000
--- a/core/src/test/java/dev/streamx/cli/command/init/GitClientUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import dev.streamx.cli.util.os.OsCommandStrategy;
-import java.io.IOException;
-
-public class GitClientUtils {
-
- public static boolean isGitInstalled(OsCommandStrategy strategy) {
- try {
- Process process = strategy.create("git --version").start();
- process.waitFor();
- byte[] stdOutBytes = process.getInputStream().readAllBytes();
-
- if (process.exitValue() != 0) {
- return false;
- }
- return new String(stdOutBytes).startsWith("git version");
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/init/InitCommandMainTest.java b/core/src/test/java/dev/streamx/cli/command/init/InitCommandMainTest.java
deleted file mode 100644
index b3aeac63..00000000
--- a/core/src/test/java/dev/streamx/cli/command/init/InitCommandMainTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-
-import dev.streamx.cli.command.init.InitCommandMainTest.SampleLocalRepositoryResource;
-import dev.streamx.cli.util.os.CmdCommandStrategy;
-import dev.streamx.cli.util.os.OsCommandStrategy;
-import dev.streamx.cli.util.os.ProcessBuilder;
-import dev.streamx.cli.util.os.ShellCommandStrategy;
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-import io.quarkus.test.common.WithTestResource;
-import io.quarkus.test.junit.main.LaunchResult;
-import io.quarkus.test.junit.main.QuarkusMainLauncher;
-import io.quarkus.test.junit.main.QuarkusMainTest;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-
-@QuarkusMainTest
-@WithTestResource(SampleLocalRepositoryResource.class)
-class InitCommandMainTest {
-
- public static final String PN_SAMPLE_GIT_REPOSITORY = "sampleGitRepository";
- public static final String GIT_NOT_INSTALLED = "gitNotInstalled";
- private static Path localRepoDirectory;
-
- @TempDir
- Path outputDirectory;
-
- @Test
- void shouldCreateProject(QuarkusMainLauncher launcher) {
- // given
- assumeGitIsInstalled();
-
- // when
- String outputDir = resolveOutputDir();
- LaunchResult result = launcher.launch("init", outputDir);
-
- // then
- assertThat(result.exitCode()).isEqualTo(0);
- assertThat(result.getOutput()).contains("Initializing StreamX project...");
- assertThat(result.getOutput()).contains("Project is ready in");
- assertThat(outputDirectory.toFile().exists()).isTrue();
- assertThat(result.getErrorOutput()).isEmpty();
- }
-
- private String resolveOutputDir() {
- return outputDirectory
- .resolve("clonedRepo")
- .toAbsolutePath()
- .normalize()
- .toString();
- }
-
- private static void assumeGitIsInstalled() {
- assumeTrue(GitClientUtils.isGitInstalled(getOsCommandStrategy()),
- "Git not installed.");
- }
-
- private static OsCommandStrategy getOsCommandStrategy() {
- String osName = System.getProperty("os.name").toLowerCase();
- if (osName.contains("win")) {
- return new CmdCommandStrategy();
- }
- return new ShellCommandStrategy();
- }
-
- public static class SampleLocalRepositoryResource implements QuarkusTestResourceLifecycleManager {
-
- @Override
- public Map start() {
- OsCommandStrategy commandStrategy = getOsCommandStrategy();
-
- if (GitClientUtils.isGitInstalled(commandStrategy)) {
- String sampleGitRepository = initializeLocalGitRepository();
- prepareSampleLocalRepository();
-
- System.setProperty(PN_SAMPLE_GIT_REPOSITORY, sampleGitRepository);
- return Map.of("streamx.cli.init.project.template.repo-url", sampleGitRepository);
- } else {
- return Map.of("streamx.cli.init.project.template.repo-url", GIT_NOT_INSTALLED);
- }
- }
-
- private static String initializeLocalGitRepository() {
- try {
- localRepoDirectory = Files.createTempDirectory("test-repository");
- return localRepoDirectory.normalize().toAbsolutePath().toString();
-
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void prepareSampleLocalRepository() {
- try {
- File cloneDirFile = localRepoDirectory.toFile();
- String command = "git init " + localRepoDirectory.toAbsolutePath().normalize();
- exec(command, cloneDirFile);
- Files.writeString(localRepoDirectory.resolve("file.txt"), "test");
- exec("git config user.name \"test\"", cloneDirFile);
- exec("git config user.email \"test@test.dev\"", cloneDirFile);
- exec("git add -A && git commit -m 'testCommit'", cloneDirFile);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private void exec(String command, File file) throws IOException, InterruptedException {
- ProcessBuilder builder = getOsCommandStrategy().create(command);
- builder.directory(file);
- Process process = builder.start();
- int status = process.waitFor();
- if (status != 0) {
- fail("Command %s exited with status %d", command, status);
- }
- }
-
- @Override
- public void stop() {
-
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/init/InitCommandTest.java b/core/src/test/java/dev/streamx/cli/command/init/InitCommandTest.java
deleted file mode 100644
index 58ea543b..00000000
--- a/core/src/test/java/dev/streamx/cli/command/init/InitCommandTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package dev.streamx.cli.command.init;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import dev.streamx.cli.command.init.project.template.ProjectTemplateSource;
-import dev.streamx.cli.exception.GitException;
-import io.quarkus.test.InjectMock;
-import io.quarkus.test.component.QuarkusComponentTest;
-import io.quarkus.test.component.TestConfigProperty;
-import jakarta.inject.Inject;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-@QuarkusComponentTest(
- annotationsTransformers = dev.streamx.cli.command.util.CommandTransformer.class
-)
-@TestConfigProperty(
- key = InitProjectConfig.STREAMX_INIT_PROJECT_TEMPLATE_OUTPUT_DIR,
- value = InitCommandTest.OUTPUT_DIR
-)
-@TestConfigProperty(
- key = "quarkus.log.file.path",
- value = "/log/path"
-)
-@ExtendWith(MockitoExtension.class)
-class InitCommandTest {
-
- public static final String OUTPUT_DIR = "outputDir";
- public static final String REPO_URL = "repoUrl";
- public static final String NORMALIZED_OUTPUT_DIR = Path.of(OUTPUT_DIR)
- .normalize().toAbsolutePath().toString();
-
- @Inject
- InitCommand initCommand;
-
- @InjectMock
- GitClient gitClient;
-
- @InjectMock
- ProjectTemplateSource projectTemplateSource;
-
- @Mock
- Process process;
-
- @AfterEach
- void cleanup() throws IOException {
- FileUtils.deleteDirectory(Path.of(OUTPUT_DIR).toFile());
- }
-
- @Test
- void shouldValidateGitInstallation() {
- // given
- mockProcessOutput("output");
- mockProcessErrorOutput("error");
- doThrow(GitException.gitCloneException(process)).when(gitClient).validateGitInstalled();
-
- // when
- Throwable throwable = catchThrowable(() -> initCommand.run());
-
- // then
- assertThat(throwable).isInstanceOf(RuntimeException.class)
- .hasMessage("""
- Unable to initialize new project.
-
- Details:
- git clone failed.
-
- Full logs can be found in /log/path""");
- verify(gitClient).validateGitInstalled();
- verifyNoMoreInteractions(gitClient);
- }
-
- @Test
- void shouldValidateOutputDirExists() throws IOException {
- // given
- Files.createDirectories(Path.of(OUTPUT_DIR));
-
- // when
- Throwable throwable = catchThrowable(() -> initCommand.run());
-
- // then
- assertThat(throwable).isInstanceOf(RuntimeException.class)
- .hasMessage("""
- Unable to initialize new project.
-
- Details:
- %s already exists
-
- Full logs can be found in /log/path""".formatted(NORMALIZED_OUTPUT_DIR));
- verify(gitClient).validateGitInstalled();
- verifyNoMoreInteractions(gitClient);
- }
-
- @Test
- void shouldExecuteCommandSuccessfully() throws IOException {
- // given
- when(projectTemplateSource.getRepoUrl()).thenReturn(REPO_URL);
-
- // when
- initCommand.run();
-
- // then
- verify(gitClient).validateGitInstalled();
- verify(gitClient).clone(REPO_URL, NORMALIZED_OUTPUT_DIR);
- verify(gitClient).removeGitMetadata(NORMALIZED_OUTPUT_DIR);
- }
-
- private void mockProcessOutput(String processOutput) {
- when(process.getInputStream()).thenReturn(new ByteArrayInputStream(processOutput.getBytes(
- StandardCharsets.UTF_8)));
- }
-
- private void mockProcessErrorOutput(String processOutput) {
- when(process.getErrorStream()).thenReturn(new ByteArrayInputStream(processOutput.getBytes(
- StandardCharsets.UTF_8)));
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolverInterpolationTest.java b/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolverInterpolationTest.java
index 7c73106e..4ec28753 100644
--- a/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolverInterpolationTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshDefinitionResolverInterpolationTest.java
@@ -1,14 +1,16 @@
package dev.streamx.cli.command.meshprocessing;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.fasterxml.jackson.databind.JsonMappingException;
+import com.streamx.mesh.model.ServiceMesh;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.NoSuchElementException;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@QuarkusTest
@@ -20,21 +22,57 @@ class MeshDefinitionResolverInterpolationTest {
@Inject
MeshDefinitionResolver uut;
- @Test
- void shouldFailWithPropertyUndefined() {
+ @BeforeEach
+ void clearSystemProperties() {
System.clearProperty("config.image.interpolated");
+ System.clearProperty("config.source.interpolated");
+ }
+
+ @Test
+ void shouldFailWithMandatoryPropertyUndefined() {
+ assertThatThrownBy(() -> uut.resolve(TEST_MESH_PATH))
+ .isInstanceOf(JsonMappingException.class)
+ .hasRootCauseInstanceOf(NoSuchElementException.class)
+ .hasRootCauseMessage("Could not expand value config.image.interpolated"
+ + " in expression ${config.image.interpolated}");
+ }
- JsonMappingException ex = assertThrowsExactly(JsonMappingException.class,
- () -> uut.resolve(TEST_MESH_PATH));
- assertThat(ex).hasRootCauseExactlyInstanceOf(NoSuchElementException.class);
+ @Test
+ void shouldResolveWithMandatoryPropertyDefinedAndOptionalPropertyUndefined() throws IOException {
+ System.setProperty("config.image.interpolated", "image-1");
+
+ ServiceMesh result = uut.resolve(TEST_MESH_PATH);
+ assertSinkImage(result, "image-1");
+ assertSourceRef(result, "inbox.pages");
}
@Test
- void shouldResolveWithPropertyDefined() throws IOException {
- System.setProperty("config.image.interpolated", "value");
+ void shouldResolveWithMandatoryAndOptionalPropertiesDefined() throws IOException {
+ System.setProperty("config.image.interpolated", "image-1");
+ System.setProperty("config.source.interpolated", "source-1");
- var result = uut.resolve(TEST_MESH_PATH);
+ ServiceMesh result = uut.resolve(TEST_MESH_PATH);
+ assertSinkImage(result, "image-1");
+ assertSourceRef(result, "source-1");
+ }
+
+ private static void assertSinkImage(ServiceMesh result, String expected) {
+ String actual = result
+ .getDescriptors()
+ .get("web-server-sink")
+ .getContainers()
+ .get("sink")
+ .getImage();
+ assertThat(actual).isEqualTo(expected);
+ }
- assertThat(result).isNotNull();
+ private static void assertSourceRef(ServiceMesh result, String expected) {
+ String actual = result
+ .getSources()
+ .get("cli")
+ .getOutgoing()
+ .getFirst()
+ .getRef();
+ assertThat(actual).isEqualTo(expected);
}
}
diff --git a/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshResolverTest.java b/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshResolverTest.java
index 9ce354f1..9976fcd5 100644
--- a/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshResolverTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/meshprocessing/MeshResolverTest.java
@@ -3,7 +3,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchException;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import dev.streamx.cli.path.CurrentDirectoryProvider;
import dev.streamx.cli.path.FixedCurrentDirectoryProvider;
@@ -16,7 +17,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import org.mockito.Mockito;
+import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.ParseResult;
@@ -96,13 +97,12 @@ TEST_MESH_PATH, currentDirectoryMeshYml(),
}
private static ParseResult getParseResult() {
+ CommandSpec commandSpec = mock(CommandSpec.class);
+ doReturn(mock(CommandLine.class)).when(commandSpec).commandLine();
- CommandSpec commandSpec = Mockito.mock();
- when(commandSpec.commandLine()).thenReturn(Mockito.mock());
-
- ParseResult parseResult = Mockito.mock();
- when(parseResult.commandSpec()).thenReturn(commandSpec);
- when(parseResult.subcommand()).thenReturn(parseResult);
+ ParseResult parseResult = mock(ParseResult.class);
+ doReturn(commandSpec).when(parseResult).commandSpec();
+ doReturn(parseResult).when(parseResult).subcommand();
return parseResult;
}
diff --git a/core/src/test/java/dev/streamx/cli/command/run/RunCommandTest.java b/core/src/test/java/dev/streamx/cli/command/run/RunCommandTest.java
index bca3d092..11d07a6b 100644
--- a/core/src/test/java/dev/streamx/cli/command/run/RunCommandTest.java
+++ b/core/src/test/java/dev/streamx/cli/command/run/RunCommandTest.java
@@ -3,9 +3,9 @@
import static dev.streamx.cli.command.util.MeshTestsUtils.cleanUpMesh;
import static org.assertj.core.api.Assertions.assertThat;
+import com.streamx.runner.event.MeshStarted;
import dev.streamx.cli.command.MeshStopper;
import dev.streamx.cli.command.run.RunCommandTest.RunCommandProfile;
-import dev.streamx.runner.event.MeshStarted;
import io.quarkus.arc.properties.IfBuildProperty;
import io.quarkus.test.junit.QuarkusTestProfile;
import io.quarkus.test.junit.TestProfile;
@@ -17,7 +17,6 @@
import jakarta.inject.Inject;
import java.nio.file.Paths;
import java.util.Map;
-import java.util.Set;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -33,11 +32,10 @@ void awaitDockerResourcesAreRemoved() {
Awaitility.await()
.until(() -> {
try {
- Set cleanedUpContainers =
- Set.of("pulsar", "pulsar-init",
- "rest-ingestion", "relay", "web-delivery-service");
- cleanUpMesh(cleanedUpContainers);
-
+ cleanUpMesh(
+ "pulsar", "pulsar-init",
+ "local-service-mesh-proxy", "rest-ingestion.proxy",
+ "pages-relay.service", "web-server-sink.sink");
return true;
} catch (Exception e) {
return false;
@@ -51,7 +49,7 @@ void shouldRunStreamxExampleMesh(QuarkusMainLauncher launcher) {
.toAbsolutePath()
.normalize()
.toString();
- LaunchResult result = launcher.launch("run", "-f=" + s);
+ LaunchResult result = launcher.launch(RunCommand.COMMAND_NAME, "-f=" + s);
assertThat(result.getOutput()).contains("STREAMX IS READY!");
}
diff --git a/core/src/test/java/dev/streamx/cli/command/util/CommandTransformer.java b/core/src/test/java/dev/streamx/cli/command/util/CommandTransformer.java
deleted file mode 100644
index d69279ca..00000000
--- a/core/src/test/java/dev/streamx/cli/command/util/CommandTransformer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package dev.streamx.cli.command.util;
-
-import io.quarkus.arc.processor.Annotations;
-import io.quarkus.arc.processor.AnnotationsTransformer;
-import io.quarkus.arc.processor.BuiltinScope;
-import jakarta.inject.Singleton;
-import java.util.List;
-import org.jboss.jandex.AnnotationTarget;
-import org.jboss.jandex.AnnotationTarget.Kind;
-import org.jboss.jandex.AnnotationValue;
-import org.jboss.jandex.DotName;
-
-public class CommandTransformer implements AnnotationsTransformer {
-
- private static final List ANNOTATIONS = List.of(
- DotName.createSimple("picocli.CommandLine$Command")
- );
-
- public CommandTransformer() {
- }
-
- public boolean appliesTo(AnnotationTarget.Kind kind) {
- return Kind.CLASS == kind;
- }
-
- public void transform(AnnotationsTransformer.TransformationContext context) {
- if (!BuiltinScope.isIn(context.getAnnotations())) {
- if (Annotations.containsAny(context.getAnnotations(), ANNOTATIONS)) {
- context.transform().add(Singleton.class, new AnnotationValue[0]).done();
- }
- }
- }
-}
diff --git a/core/src/test/java/dev/streamx/cli/command/util/MeshTestsUtils.java b/core/src/test/java/dev/streamx/cli/command/util/MeshTestsUtils.java
index 31f844e7..3d868b16 100644
--- a/core/src/test/java/dev/streamx/cli/command/util/MeshTestsUtils.java
+++ b/core/src/test/java/dev/streamx/cli/command/util/MeshTestsUtils.java
@@ -1,14 +1,14 @@
package dev.streamx.cli.command.util;
import com.github.dockerjava.api.DockerClient;
-import dev.streamx.runner.validation.DockerContainerValidator;
-import dev.streamx.runner.validation.DockerEnvironmentValidator;
+import com.streamx.runner.validation.DockerContainerValidator;
+import com.streamx.runner.validation.DockerEnvironmentValidator;
import java.util.Set;
public class MeshTestsUtils {
- public static void cleanUpMesh(Set cleanedUpContainers) {
+ public static void cleanUpMesh(String... containersToRemove) {
DockerClient client = new DockerEnvironmentValidator().validateDockerClient();
- for (String container : cleanedUpContainers) {
+ for (String container : containersToRemove) {
try {
client.removeContainerCmd(container)
.withForce(true)
@@ -17,6 +17,6 @@ public static void cleanUpMesh(Set cleanedUpContainers) {
// Ignore
}
}
- new DockerContainerValidator().verifyExistingContainers(client, cleanedUpContainers);
+ new DockerContainerValidator().verifyExistingContainers(client, Set.of(containersToRemove));
}
}
diff --git a/core/src/test/java/dev/streamx/cli/interpolation/InterpolatingMapperTest.java b/core/src/test/java/dev/streamx/cli/interpolation/InterpolatingMapperTest.java
index ac3156f6..47f93279 100644
--- a/core/src/test/java/dev/streamx/cli/interpolation/InterpolatingMapperTest.java
+++ b/core/src/test/java/dev/streamx/cli/interpolation/InterpolatingMapperTest.java
@@ -10,7 +10,6 @@
import java.util.Set;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
-import org.testcontainers.shaded.org.bouncycastle.oer.its.etsi102941.Url;
@QuarkusTest
public class InterpolatingMapperTest {
@@ -114,7 +113,7 @@ void testMixedTypesInterpolation() throws Exception {
assertEquals("interpolatedValue", result.getString());
assertEquals(-1, result.getLongField());
assertEquals(-1, result.getInteger());
- assertEquals("http://interpolatedValue", result.getUrl().getUrl());
+ assertEquals("http://interpolatedValue", result.getUrl());
}
@@ -124,7 +123,7 @@ static class MixedTypesTestClass {
private String string;
private Integer integer;
private Long longField;
- private Url url;
+ private String url;
public boolean isBool() {
return bool;
@@ -158,11 +157,11 @@ public void setLongField(Long longField) {
this.longField = longField;
}
- public Url getUrl() {
+ public String getUrl() {
return url;
}
- public void setUrl(Url url) {
+ public void setUrl(String url) {
this.url = url;
}
}
diff --git a/core/src/test/java/dev/streamx/cli/license/LicenseAcceptingTest.java b/core/src/test/java/dev/streamx/cli/license/LicenseAcceptingTest.java
index 22c2cdd5..1a7e703e 100644
--- a/core/src/test/java/dev/streamx/cli/license/LicenseAcceptingTest.java
+++ b/core/src/test/java/dev/streamx/cli/license/LicenseAcceptingTest.java
@@ -5,6 +5,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
import dev.streamx.cli.exception.LicenseException;
import dev.streamx.cli.license.LicenseTestProfiles.AcceptProceedingTestProfile;
@@ -16,18 +17,17 @@
import dev.streamx.cli.settings.SettingsStore;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
+import io.quarkus.test.junit.mockito.InjectSpy;
import jakarta.inject.Inject;
import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.time.LocalDateTime;
-import java.util.Comparator;
import java.util.List;
import java.util.Optional;
+import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -38,16 +38,19 @@ class LicenseAcceptingTest {
public static final String OLD_URL = "http://old.streamx.dev/license.html";
public static final String OLD_NAME = "oldLicense";
- LicenseArguments licenseArguments = new LicenseArguments();
+ private final LicenseArguments licenseArguments = new LicenseArguments();
+ private final AcceptingStrategy acceptingStrategy = mock(AcceptingStrategy.class);
@Inject
SettingsStore settingsStore;
- @Inject
+ @InjectSpy
LicenseProcessorEntrypoint entrypoint;
- @Inject
- AcceptingStrategy acceptingStrategy;
+ @BeforeEach
+ void setup() {
+ doReturn(acceptingStrategy).when(entrypoint).getAcceptingStrategy();
+ }
@AfterEach
void shutdown() {
@@ -231,15 +234,7 @@ private void userShouldNotBeAskedForAcceptation() {
}
private static void clearSettings() {
- try {
- Path pathToBeDeleted = Path.of(ProceedingTestProfile.TEST_SETTINGS_PATH_ROOT);
-
- Files.walk(pathToBeDeleted)
- .sorted(Comparator.reverseOrder())
- .map(Path::toFile)
- .forEach(File::delete);
- } catch (IOException e) {
- // skip
- }
+ File directoryToBeDeleted = new File(ProceedingTestProfile.TEST_SETTINGS_PATH_ROOT);
+ FileUtils.deleteQuietly(directoryToBeDeleted);
}
}
diff --git a/core/src/test/java/dev/streamx/cli/license/input/LicenseInputConfig.java b/core/src/test/java/dev/streamx/cli/license/input/LicenseInputConfig.java
deleted file mode 100644
index c162a58e..00000000
--- a/core/src/test/java/dev/streamx/cli/license/input/LicenseInputConfig.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package dev.streamx.cli.license.input;
-
-import io.quarkus.arc.profile.IfBuildProfile;
-import jakarta.enterprise.context.Dependent;
-import jakarta.inject.Singleton;
-import org.mockito.Mockito;
-
-@Dependent
-public class LicenseInputConfig {
-
- @Singleton
- @IfBuildProfile("test")
- AcceptingStrategy mockedAcceptingStrategy() {
- return Mockito.mock(AcceptingStrategy.class);
- }
-
-}
diff --git a/core/src/test/java/dev/streamx/cli/license/input/StdInLineReadStrategyTest.java b/core/src/test/java/dev/streamx/cli/license/input/StdInLineReadStrategyTest.java
index 95442b1e..2b3cbf54 100644
--- a/core/src/test/java/dev/streamx/cli/license/input/StdInLineReadStrategyTest.java
+++ b/core/src/test/java/dev/streamx/cli/license/input/StdInLineReadStrategyTest.java
@@ -1,7 +1,6 @@
package dev.streamx.cli.license.input;
import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -50,6 +49,6 @@ void shouldReject(String source) {
}
private static void givenStdIn(String source) {
- System.setIn(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)));
+ System.setIn(new ByteArrayInputStream(source.getBytes()));
}
}
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/deploy/servicemeshes.streamx.dev-v1.yml b/core/src/test/resources/dev/streamx/cli/command/cloud/deploy/servicemeshes.streamx.dev-v1.yml
deleted file mode 100644
index c67f3a24..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/deploy/servicemeshes.streamx.dev-v1.yml
+++ /dev/null
@@ -1,5155 +0,0 @@
-# Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
-apiVersion: "apiextensions.k8s.io/v1"
-kind: "CustomResourceDefinition"
-metadata:
- name: "servicemeshes.streamx.dev"
-spec:
- group: "streamx.dev"
- names:
- kind: "ServiceMesh"
- plural: "servicemeshes"
- shortNames:
- - "mesh"
- singular: "servicemesh"
- scope: "Namespaced"
- versions:
- - name: "v1alpha1"
- schema:
- openAPIV3Schema:
- properties:
- spec:
- properties:
- defaultImageTag:
- type: "string"
- defaultRegistry:
- type: "string"
- delivery:
- additionalProperties:
- properties:
- components:
- additionalProperties:
- properties:
- environment:
- additionalProperties:
- type: "string"
- type: "object"
- environmentFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- image:
- type: "string"
- ports:
- items:
- type: "string"
- type: "array"
- repositoryVolume:
- type: "string"
- volumesFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "object"
- type: "object"
- environment:
- additionalProperties:
- type: "string"
- type: "object"
- environmentFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- image:
- type: "string"
- incoming:
- additionalProperties:
- properties:
- topic:
- type: "string"
- type: "object"
- type: "object"
- port:
- type: "integer"
- repositoryVolume:
- type: "string"
- volumesFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "object"
- type: "object"
- deploymentConfig:
- properties:
- defaults:
- properties:
- delivery:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- type: "object"
- global:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- type: "object"
- ingestion:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- type: "object"
- processing:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- type: "object"
- type: "object"
- delivery:
- additionalProperties:
- properties:
- components:
- additionalProperties:
- properties:
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- sidecar:
- type: "boolean"
- volumes:
- additionalProperties:
- properties:
- mountPath:
- type: "string"
- size:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- storageClassName:
- type: "string"
- type: "object"
- type: "object"
- type: "object"
- type: "object"
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- ingress:
- properties:
- annotations:
- additionalProperties:
- type: "string"
- type: "object"
- enabled:
- type: "boolean"
- hosts:
- items:
- properties:
- host:
- type: "string"
- paths:
- items:
- properties:
- path:
- type: "string"
- pathType:
- type: "string"
- servicePort:
- type: "integer"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- ingressClassName:
- type: "string"
- tls:
- items:
- properties:
- hosts:
- items:
- type: "string"
- type: "array"
- secretName:
- type: "string"
- type: "object"
- type: "array"
- waitForLoadBalancer:
- type: "boolean"
- type: "object"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- volumes:
- additionalProperties:
- properties:
- mountPath:
- type: "string"
- size:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- storageClassName:
- type: "string"
- type: "object"
- type: "object"
- type: "object"
- type: "object"
- ingestion:
- additionalProperties:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- ingress:
- properties:
- annotations:
- additionalProperties:
- type: "string"
- type: "object"
- enabled:
- type: "boolean"
- hosts:
- items:
- properties:
- host:
- type: "string"
- paths:
- items:
- properties:
- path:
- type: "string"
- pathType:
- type: "string"
- servicePort:
- type: "integer"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- ingressClassName:
- type: "string"
- tls:
- items:
- properties:
- hosts:
- items:
- type: "string"
- type: "array"
- secretName:
- type: "string"
- type: "object"
- type: "array"
- waitForLoadBalancer:
- type: "boolean"
- type: "object"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- volumes:
- additionalProperties:
- properties:
- mountPath:
- type: "string"
- size:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- storageClassName:
- type: "string"
- type: "object"
- type: "object"
- type: "object"
- type: "object"
- processing:
- additionalProperties:
- properties:
- imagePullPolicy:
- type: "string"
- imagePullSecrets:
- items:
- properties:
- name:
- type: "string"
- type: "object"
- type: "array"
- podDisruptionBudget:
- properties:
- enabled:
- type: "boolean"
- maxUnavailable:
- type: "integer"
- minAvailable:
- type: "integer"
- type: "object"
- probes:
- properties:
- liveness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- readiness:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- startup:
- properties:
- exec:
- properties:
- command:
- items:
- type: "string"
- type: "array"
- type: "object"
- failureThreshold:
- type: "integer"
- grpc:
- properties:
- port:
- type: "integer"
- service:
- type: "string"
- type: "object"
- httpGet:
- properties:
- host:
- type: "string"
- httpHeaders:
- items:
- properties:
- name:
- type: "string"
- value:
- type: "string"
- type: "object"
- type: "array"
- path:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- scheme:
- type: "string"
- type: "object"
- initialDelaySeconds:
- type: "integer"
- periodSeconds:
- type: "integer"
- successThreshold:
- type: "integer"
- tcpSocket:
- properties:
- host:
- type: "string"
- port:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- terminationGracePeriodSeconds:
- type: "integer"
- timeoutSeconds:
- type: "integer"
- type: "object"
- type: "object"
- replicas:
- type: "integer"
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: "string"
- request:
- type: "string"
- type: "object"
- type: "array"
- limits:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- requests:
- additionalProperties:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type: "object"
- scheduling:
- properties:
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchFields:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- weight:
- type: "integer"
- type: "object"
- type: "array"
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- mismatchLabelKeys:
- items:
- type: "string"
- type: "array"
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- namespaces:
- items:
- type: "string"
- type: "array"
- topologyKey:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- type: "object"
- priorityClassName:
- type: "string"
- tolerations:
- items:
- properties:
- effect:
- type: "string"
- key:
- type: "string"
- operator:
- type: "string"
- tolerationSeconds:
- type: "integer"
- value:
- type: "string"
- type: "object"
- type: "array"
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: "string"
- operator:
- type: "string"
- values:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "array"
- matchLabels:
- additionalProperties:
- type: "string"
- type: "object"
- type: "object"
- matchLabelKeys:
- items:
- type: "string"
- type: "array"
- maxSkew:
- type: "integer"
- minDomains:
- type: "integer"
- nodeAffinityPolicy:
- type: "string"
- nodeTaintsPolicy:
- type: "string"
- topologyKey:
- type: "string"
- whenUnsatisfiable:
- type: "string"
- type: "object"
- type: "array"
- type: "object"
- stateful:
- type: "boolean"
- storageClassName:
- type: "string"
- strategy:
- properties:
- rollingUpdate:
- properties:
- maxSurge:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- maxUnavailable:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- type: "object"
- type:
- type: "string"
- type: "object"
- volumes:
- additionalProperties:
- properties:
- mountPath:
- type: "string"
- size:
- anyOf:
- - type: "integer"
- - type: "string"
- x-kubernetes-int-or-string: true
- storageClassName:
- type: "string"
- type: "object"
- type: "object"
- type: "object"
- type: "object"
- type: "object"
- environment:
- additionalProperties:
- type: "string"
- type: "object"
- environmentFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- ingestion:
- additionalProperties:
- properties:
- environment:
- additionalProperties:
- type: "string"
- type: "object"
- environmentFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- image:
- type: "string"
- volumesFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "object"
- type: "object"
- processing:
- additionalProperties:
- properties:
- environment:
- additionalProperties:
- type: "string"
- type: "object"
- environmentFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- image:
- type: "string"
- incoming:
- additionalProperties:
- properties:
- topic:
- type: "string"
- type: "object"
- type: "object"
- outgoing:
- additionalProperties:
- properties:
- topic:
- type: "string"
- type: "object"
- type: "object"
- volumesFrom:
- properties:
- configs:
- items:
- type: "string"
- type: "array"
- secrets:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "object"
- type: "object"
- sources:
- additionalProperties:
- properties:
- outgoing:
- items:
- type: "string"
- type: "array"
- type: "object"
- type: "object"
- type: "object"
- status:
- properties:
- conditions:
- items:
- properties:
- lastTransitionTime:
- type: "string"
- message:
- type: "string"
- observedGeneration:
- type: "integer"
- status:
- type: "string"
- type:
- type: "string"
- type: "object"
- type: "array"
- observedGeneration:
- type: "integer"
- type: "object"
- type: "object"
- served: true
- storage: true
- subresources:
- status: {}
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds.properties
deleted file mode 100644
index ca540fe4..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds.properties
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_DELIVERY_WDS_PROP=config-delivery-wds-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file.txt
deleted file mode 100644
index f873bd50..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/dir/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file1.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file1.txt
deleted file mode 100644
index 8e81b5f8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/dir/file1.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/dir/file1.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/file.txt
deleted file mode 100644
index 39fc185f..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx.properties
deleted file mode 100644
index dab0aba8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx.properties
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_DELIVERY_WDS_NGINX_PROP=config-delivery-wds-nginx-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx/file.txt
deleted file mode 100644
index bbf80c93..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/delivery/wds/nginx/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/nginx/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/global.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/global.properties
deleted file mode 100644
index 576b7355..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/global.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG_GLOBAL_PROP_NAME=config-global-prop-value
-CONFIG_GLOBAL_ANOTHER_PROP_NAME=config-global-another-prop-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest.properties
deleted file mode 100644
index b7467b90..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest.properties
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_INGESTION_REST_PROP=config-ingestion-rest-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest/file.txt
deleted file mode 100644
index 3670f92c..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/ingestion/rest/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-ingestion/rest/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid[]name.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid[]name.txt
deleted file mode 100644
index 4b9a8a29..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid[]name.txt
+++ /dev/null
@@ -1 +0,0 @@
-aaaaaaa
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid_prop_key.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid_prop_key.properties
deleted file mode 100644
index 0d73e118..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/invalid/invalid_prop_key.properties
+++ /dev/null
@@ -1 +0,0 @@
-invalid[]key=value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay.properties
deleted file mode 100644
index 972359d8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay.properties
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_PROCESSING_RELAY_PROP=config-processing-relay-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay/file.txt
deleted file mode 100644
index 6fba0559..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/processing/relay/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-processing/relay/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/relay.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/relay.properties
deleted file mode 100644
index 1028210d..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/relay.properties
+++ /dev/null
@@ -1 +0,0 @@
-conf-prop-name="conf-prop-value"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared.properties
deleted file mode 100644
index 391fa7dc..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared.properties
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_SHARED_PROP_NAME=config-shared-prop-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/do_not_delete/DO_NOT_DELETE.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/do_not_delete/DO_NOT_DELETE.txt
deleted file mode 100644
index ed8679d1..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/do_not_delete/DO_NOT_DELETE.txt
+++ /dev/null
@@ -1 +0,0 @@
-This file tests if directory volume config reads only one level of files tree.
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file.txt
deleted file mode 100644
index 60dfd6dc..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-shared/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file1.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file1.txt
deleted file mode 100644
index f20d7ba4..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configs/shared/file1.txt
+++ /dev/null
@@ -1 +0,0 @@
-shared/file1.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configuration-interpolation.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/configuration-interpolation.yaml
deleted file mode 100644
index 36a121db..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/configuration-interpolation.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - ${string.array.property}
-
-processing:
- relay:
- image: ${string.property}
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/custom-name.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/custom-name.yaml
deleted file mode 100644
index 9023e198..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/custom-name.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.configuration-interpolation.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.configuration-interpolation.yaml
deleted file mode 100644
index 8902ee48..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.configuration-interpolation.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-tenantConfig:
- inboxesPartitions: 2
- relaysPartitions: 2
- outboxesPartitions: 2
- inboxesCompactionThresholdBytes: 10240
- outboxesCompactionThresholdBytes: 10240
- storesCompactionThresholdBytes: 10240
- subscriptionExpirationTimeMinutes: 240
-ingestion:
- rest:
- replicas: 1
-processing:
- relay:
- replicas: 2
-delivery:
- web-delivery-service:
- replicas: ${integer.property}
- stateful: ${boolean.property}
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.custom-name.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.custom-name.yaml
deleted file mode 100644
index 0f8d4610..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.custom-name.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-ingestion:
- rest:
- replicas: 2
-processing:
- relay:
- replicas: 2
-delivery:
- web-delivery-service:
- stateful: false
- replicas: 2
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.empty-deployment.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.empty-deployment.yaml
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.with-configs.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.with-configs.yaml
deleted file mode 100644
index da8e102a..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.with-configs.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-tenantConfig:
- inboxesPartitions: 2
- relaysPartitions: 2
- outboxesPartitions: 2
- inboxesCompactionThresholdBytes: 10240
- outboxesCompactionThresholdBytes: 10240
- storesCompactionThresholdBytes: 10240
- subscriptionExpirationTimeMinutes: 240
-ingestion:
- rest:
- replicas: 1
-processing:
- relay:
- replicas: 2
-delivery:
- web-delivery-service:
- replicas: 1
- stateful: true
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.yaml
deleted file mode 100644
index 2ea76b54..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/deployment.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-ingestion:
- rest:
- replicas: 1
-processing:
- relay:
- replicas: 2
-delivery:
- web-delivery-service:
- stateful: true
- replicas: 1
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/empty-deployment.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/empty-deployment.yaml
deleted file mode 100644
index 9023e198..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/empty-deployment.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/empty-mesh.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/empty-mesh.yaml
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/mesh.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/mesh.yaml
deleted file mode 100644
index c6bd93fd..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/mesh.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
- environment:
- STREAMX_DELIVERY-SERVICE_READINESS-CHECK_CHANNELS-QUIET-TIME: "3000"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/nodeployment.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/nodeployment.yaml
deleted file mode 100644
index 9023e198..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/nodeployment.yaml
+++ /dev/null
@@ -1,31 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds.properties
deleted file mode 100644
index 3dde8ef9..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_DELIVERY_WDS_PROP=secret-delivery-wds-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file.txt
deleted file mode 100644
index f873bd50..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/dir/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file1.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file1.txt
deleted file mode 100644
index 8e81b5f8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/dir/file1.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/dir/file1.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/file.txt
deleted file mode 100644
index 39fc185f..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx.properties
deleted file mode 100644
index 2b1260b8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_DELIVERY_WDS_NGINX_PROP=secret-delivery-wds-nginx-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx/file.txt
deleted file mode 100644
index bbf80c93..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/delivery/wds/nginx/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-delivery/wds/nginx/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/global.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/global.properties
deleted file mode 100644
index 01a60fa8..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/global.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_GLOBAL_PROP_NAME=secret-global-prop-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest.properties
deleted file mode 100644
index 0325a707..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_INGESTION_REST_PROP=secret-ingestion-rest-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest/file.txt
deleted file mode 100644
index 3670f92c..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/ingestion/rest/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-ingestion/rest/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay.properties
deleted file mode 100644
index e42625eb..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_PROCESSING_RELAY_PROP=secret-processing-relay-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay/file.txt
deleted file mode 100644
index 6fba0559..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/processing/relay/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-processing/relay/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/relay.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/relay.properties
deleted file mode 100644
index e94c1f1d..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/relay.properties
+++ /dev/null
@@ -1 +0,0 @@
-secret-prop-name="secret-prop-value"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared.properties b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared.properties
deleted file mode 100644
index 68fb06bf..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared.properties
+++ /dev/null
@@ -1 +0,0 @@
-SECRET_SHARED_PROP_NAME=secret-shared-prop-value
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file.txt
deleted file mode 100644
index 60dfd6dc..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-shared/file.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file1.txt b/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file1.txt
deleted file mode 100644
index f20d7ba4..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/secrets/shared/file1.txt
+++ /dev/null
@@ -1 +0,0 @@
-shared/file1.txt
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/cloud/project/with-configs.yaml b/core/src/test/resources/dev/streamx/cli/command/cloud/project/with-configs.yaml
deleted file mode 100644
index efa8e014..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/cloud/project/with-configs.yaml
+++ /dev/null
@@ -1,91 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-environmentFrom:
- configs:
- - "global.properties"
- secrets:
- - "global.properties"
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-ingestion:
- rest:
- environmentFrom:
- configs:
- - "ingestion/rest.properties"
- secrets:
- - "ingestion/rest.properties"
- volumesFrom:
- configs:
- - "ingestion/rest/file.txt"
- - "shared"
- secrets:
- - "ingestion/rest/file.txt"
- - "shared"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
- environmentFrom:
- configs:
- - "processing/relay.properties"
- - "shared.properties"
- secrets:
- - "processing/relay.properties"
- - "shared.properties"
- volumesFrom:
- configs:
- - "processing/relay/file.txt"
- - "shared"
- secrets:
- - "processing/relay/file.txt"
- - "shared"
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- environmentFrom:
- configs:
- - "delivery/wds.properties"
- - "shared.properties"
- secrets:
- - "delivery/wds.properties"
- - "shared.properties"
- volumesFrom:
- configs:
- - "delivery/wds/file.txt"
- - "delivery/wds/dir"
- secrets:
- - "delivery/wds/file.txt"
- - "delivery/wds/dir"
- components:
- nginx:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - 8082:80
- repositoryVolume: "/usr/share/nginx/html"
- environmentFrom:
- configs:
- - "delivery/wds/nginx.properties"
- secrets:
- - "delivery/wds/nginx.properties"
- volumesFrom:
- configs:
- - "delivery/wds/nginx/file.txt"
- - "shared"
- secrets:
- - "delivery/wds/nginx/file.txt"
- - "shared"
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/dev/failing-mesh.yaml b/core/src/test/resources/dev/streamx/cli/command/dev/failing-mesh.yaml
deleted file mode 100644
index 06d2c4cc..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/dev/failing-mesh.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-ingestion:
- rest-ingestion:
- environment:
- QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: "per"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- environment:
- STREAMX_DELIVERY-SERVICE_READINESS-CHECK_CHANNELS-QUIET-TIME: "3000"
diff --git a/core/src/test/resources/dev/streamx/cli/command/dev/incremental-reloaded-mesh.yaml b/core/src/test/resources/dev/streamx/cli/command/dev/incremental-reloaded-mesh.yaml
deleted file mode 100644
index 0b18a59c..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/dev/incremental-reloaded-mesh.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-ingestion:
- rest-ingestion:
- environment:
- QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: "permit"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/page
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/page
- port: 8081
- environment:
- STREAMX_DELIVERY-SERVICE_READINESS-CHECK_CHANNELS-QUIET-TIME: "3000"
diff --git a/core/src/test/resources/dev/streamx/cli/command/dev/initial-mesh.yaml b/core/src/test/resources/dev/streamx/cli/command/dev/initial-mesh.yaml
deleted file mode 100644
index da297fa3..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/dev/initial-mesh.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: latest-jvm
-
-sources:
- cli:
- outgoing:
- - "pages"
-
-ingestion:
- rest-ingestion:
- environment:
- QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: "permit"
-
-processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
-
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
- environment:
- STREAMX_DELIVERY-SERVICE_READINESS-CHECK_CHANNELS-QUIET-TIME: "3000"
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/.eventsource.yaml
deleted file mode 100644
index 6aff22d0..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/.eventsource.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-channel: pages
-relativePathLevel: 1
-key: ${relativePath}
-
-payload:
- content:
- byte: file://${payloadPath}
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/index.html b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/index.html
deleted file mode 100644
index de8b69b6..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-channel/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Hello World!
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-json/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-json/.eventsource.yaml
index d2d0c1c7..e1354b53 100644
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-json/.eventsource.yaml
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/invalid-json/.eventsource.yaml
@@ -1,4 +1,6 @@
-channel: pages
+eventType: page_publish
+eventSource: source
+
relativePathLevel: 0
key: ${relativePath}
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/.eventsource.yaml
deleted file mode 100644
index 7c039eff..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/.eventsource.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-channel: images
-relativePathLevel: 1
-key: ${relativePath}
-
-payload:
- content:
- bytes: file://${payloadPath}
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/index.html b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/index.html
deleted file mode 100644
index de8b69b6..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/unknown-channel/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Hello World!
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid-json/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid-json/.eventsource.yaml
index abcc192e..f15f5700 100644
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid-json/.eventsource.yaml
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid-json/.eventsource.yaml
@@ -1,4 +1,5 @@
-channel: pages
+eventType: page_publish
+eventSource: source
key: ${relativePath}
payload:
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/.eventsource.yaml
deleted file mode 100644
index dbeb627c..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/.eventsource.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-channel: pages
-relativePathLevel: 1
-key: ${relativePath}
-ignorePatterns:
- - ".*/ignore\\.me"
-properties:
- "sx:type": page/sub-page
-
-payload:
- content:
- bytes: file://${payloadPath}
-
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/index.html b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/index.html
deleted file mode 100644
index de8b69b6..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Hello World!
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/.eventsource.yaml
new file mode 100644
index 00000000..d1047825
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/.eventsource.yaml
@@ -0,0 +1,12 @@
+eventType: image_publish
+eventSource: source
+
+relativePathLevel: 1
+key: ${relativePath}
+ignorePatterns:
+ - ".*/ignore\\.me"
+
+payload:
+ content: file://${payloadPath}
+ type: assets/image
+
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/ds.png b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/ds.png
new file mode 100644
index 00000000..4b85fd55
Binary files /dev/null and b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/ds.png differ
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/ignore.me b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/ignore.me
similarity index 100%
rename from core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/ignore.me
rename to core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/image/ignore.me
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/.eventsource.yaml
new file mode 100644
index 00000000..ee93d29e
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/.eventsource.yaml
@@ -0,0 +1,12 @@
+eventType: page_publish
+eventSource: source
+
+relativePathLevel: 1
+key: ${relativePath}
+ignorePatterns:
+ - ".*/ignore\\.me"
+
+payload:
+ content: file://${payloadPath}
+ type: page/sub-page
+
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/ignore.me b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/ignore.me
new file mode 100644
index 00000000..8195dbc0
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/ignore.me
@@ -0,0 +1 @@
+nevermind - ignore me!
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/index.html b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/index.html
new file mode 100644
index 00000000..ba7c290e
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/publish/page/index.html
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/.eventsource.yaml b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/.eventsource.yaml
new file mode 100644
index 00000000..68828725
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/.eventsource.yaml
@@ -0,0 +1,10 @@
+eventType: page_unpublish
+eventSource: source
+
+relativePathLevel: 1
+key: ${relativePath}
+ignorePatterns:
+ - ".*/ignore\\.me"
+
+payload:
+ type: page/sub-page
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/ignore.me b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/ignore.me
new file mode 100644
index 00000000..8195dbc0
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/ignore.me
@@ -0,0 +1 @@
+nevermind - ignore me!
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/index.html b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/index.html
new file mode 100644
index 00000000..ba7c290e
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/batch/valid/unpublish/page/index.html
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/example-image.png b/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/example-image.png
deleted file mode 100644
index 062c4163..00000000
Binary files a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/example-image.png and /dev/null differ
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/helloworld-payload.json b/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/helloworld-payload.json
deleted file mode 100644
index 864b90ce..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/helloworld-payload.json
+++ /dev/null
@@ -1 +0,0 @@
-{"content": {"bytes": "Hello World!
"}}
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/invalid-payload.json b/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/invalid-payload.json
deleted file mode 100644
index 93b12300..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/invalid-payload.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{
- "nana": "lele"
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/payload.json b/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/payload.json
deleted file mode 100644
index 2a35f674..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/payload.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "nana": "lele"
-}
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/raw-text.txt b/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/raw-text.txt
deleted file mode 100644
index fce7a2a9..00000000
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/publish/payload/raw-text.txt
+++ /dev/null
@@ -1 +0,0 @@
-This works ąćpretty well...
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/.stream.properties b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/.stream.properties
new file mode 100644
index 00000000..15b64ec4
--- /dev/null
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/.stream.properties
@@ -0,0 +1 @@
+json.fields.as-base64=/data/content
\ No newline at end of file
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/invalid-separated-json.stream b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/invalid-separated-json.stream
index 215d561b..35ff66d1 100644
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/invalid-separated-json.stream
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/invalid-separated-json.stream
@@ -1,30 +1,16 @@
{
- "key" : "homepage.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : {
- "sx:type": "page/content"
- },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "This is Home Page!
"
- }
- }
- }
+ "specversion" : "1.0",
+ "id" : "11111111-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_unpublish",
+ "subject" : "blogs.html",
+ "time" : "2025-12-25T10:28:23.435253Z"
},
{
- "key" : "homepage.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : {
- "sx:type": "page/content"
- },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "This is Home Page!
"
- }
- }
- }
+ "specversion" : "1.0",
+ "id" : "99999999-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_unpublish",
+ "subject" : "products.html",
+ "time" : "2025-12-25T10:28:23.435253Z"
}
diff --git a/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/valid-json.stream b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/valid-json.stream
index 322f191d..d5785ffe 100644
--- a/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/valid-json.stream
+++ b/core/src/test/resources/dev/streamx/cli/command/ingestion/stream/valid-json.stream
@@ -1,15 +1,32 @@
{
- "key" : "homepage.html",
- "action" : "publish",
- "eventTime" : null,
- "properties" : {
- "sx:type": "page/content"
- },
- "payload" : {
- "dev.streamx.blueprints.data.Page" : {
- "content" : {
- "bytes" : "This is Home Page!
"
- }
- }
+ "specversion" : "1.0",
+ "id" : "11111111-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_publish",
+ "datacontenttype" : "application/json",
+ "subject" : "homepage.html",
+ "time" : "2025-12-23T10:28:23.435253Z",
+ "data" : {
+ "content" : "This is Home Page!
",
+ "type" : "page/content"
}
}
+{
+ "specversion" : "1.0",
+ "id" : "55555555-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_unpublish",
+ "subject" : "blogs.html",
+ "time" : "2025-12-24T10:28:23.435253Z",
+ "data" : {
+ "type" : "page/blog"
+ }
+}
+{
+ "specversion" : "1.0",
+ "id" : "99999999-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "page_unpublish",
+ "subject" : "products.html",
+ "time" : "2025-12-25T10:28:23.435253Z"
+}
\ No newline at end of file
diff --git a/core/src/test/resources/filtered/mesh-interpolated.yaml b/core/src/test/resources/filtered/mesh-interpolated.yaml
index a21432e7..7f8ea1f6 100644
--- a/core/src/test/resources/filtered/mesh-interpolated.yaml
+++ b/core/src/test/resources/filtered/mesh-interpolated.yaml
@@ -1,25 +1,55 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: ${streamx.version}-jvm
+descriptors:
+ relay:
+ type: "processing"
+ containers:
+ service:
+ incoming:
+ events: {}
+ outgoing:
+ relayed-events: {}
+
+ web-server-sink:
+ type: "edge"
+ containers:
+ sink:
+ image: "${config.image.interpolated}"
+ incoming:
+ resources: {}
+ servicePorts:
+ - "8087:8080"
sources:
cli:
outgoing:
- - "pages"
+ - ref: "${config.source.interpolated:inbox.pages}"
+ produces:
+ - "com.streamx.blueprints.page.published.v1"
+ - "com.streamx.blueprints.page.unpublished.v1"
+
+ingestion:
+ rest-ingestion:
+ containers:
+ proxy:
+ environment:
+ QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: permit
processing:
- relay:
- image: ${config.image.interpolated}
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
+ pages-relay:
+ descriptor: relay
+ containers:
+ service:
+ incoming:
+ events:
+ ref: inbox.pages
+ outgoing:
+ relayed-events:
+ ref: outbox.pages
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
+edge:
+ web-server-sink:
+ descriptor: web-server-sink
+ containers:
+ sink:
+ incoming:
+ resources:
+ ref: outbox.pages
diff --git a/core/src/test/resources/filtered/mesh.yaml b/core/src/test/resources/filtered/mesh.yaml
index 03feb9b8..0e07ab37 100644
--- a/core/src/test/resources/filtered/mesh.yaml
+++ b/core/src/test/resources/filtered/mesh.yaml
@@ -1,25 +1,55 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: ${streamx.version}-jvm
+descriptors:
+ relay:
+ type: "processing"
+ containers:
+ service:
+ incoming:
+ events: {}
+ outgoing:
+ relayed-events: {}
+
+ web-server-sink:
+ type: "edge"
+ containers:
+ sink:
+ image: "ghcr.io/streamx-com/streamx-blueprints/web-server-sink:3.0.7-jvm"
+ incoming:
+ resources: {}
+ servicePorts:
+ - "8087:8080"
sources:
cli:
outgoing:
- - "pages"
+ - ref: "inbox.pages"
+ produces:
+ - "com.streamx.blueprints.page.published.v1"
+ - "com.streamx.blueprints.page.unpublished.v1"
+
+ingestion:
+ rest-ingestion:
+ containers:
+ proxy:
+ environment:
+ QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: permit
processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
+ pages-relay:
+ descriptor: relay
+ containers:
+ service:
+ incoming:
+ events:
+ ref: inbox.pages
+ outgoing:
+ relayed-events:
+ ref: outbox.pages
-delivery:
- web-delivery-service:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8081
+edge:
+ web-server-sink:
+ descriptor: web-server-sink
+ containers:
+ sink:
+ incoming:
+ resources:
+ ref: outbox.pages
diff --git a/distribution/pom.xml b/distribution/pom.xml
index f88258bb..b86d5770 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -12,8 +12,8 @@
StreamX Cli : Distribution
- 17
- 17
+ 21
+ 21
UTF-8
1.17.0
diff --git a/distribution/src/main/resources/jreleaser-preview.yml b/distribution/src/main/resources/jreleaser-preview.yml
index e2becadb..b815a80c 100644
--- a/distribution/src/main/resources/jreleaser-preview.yml
+++ b/distribution/src/main/resources/jreleaser-preview.yml
@@ -15,7 +15,7 @@ project:
java:
groupId: dev.streamx.cli
artifactId: streamx-cli
- version: 17
+ version: 21
inceptionYear: 2024
tags:
diff --git a/distribution/src/main/resources/jreleaser.yml b/distribution/src/main/resources/jreleaser.yml
index 6fd51cba..7e6192bd 100644
--- a/distribution/src/main/resources/jreleaser.yml
+++ b/distribution/src/main/resources/jreleaser.yml
@@ -13,7 +13,7 @@ project:
java:
groupId: dev.streamx.cli
artifactId: streamx-cli
- version: 17
+ version: 21
inceptionYear: 2024
tags:
diff --git a/e2e-tests/pom.xml b/e2e-tests/pom.xml
index dac74e2e..fe6b6163 100644
--- a/e2e-tests/pom.xml
+++ b/e2e-tests/pom.xml
@@ -13,8 +13,8 @@
StreamX Cli : E2e Tests
- 17
- 17
+ 21
+ 21
UTF-8
@@ -30,6 +30,11 @@
org.awaitility
awaitility
+
+ org.assertj
+ assertj-core
+ compile
+
org.jboss.logging
commons-logging-jboss-logging
@@ -44,7 +49,7 @@
test
- dev.streamx
+ com.streamx
streamx-runner
test
@@ -64,7 +69,6 @@
src/test/resources/filtered
mesh.yaml
- overridden-nginx-conf
diff --git a/e2e-tests/src/main/java/dev/streamx/cli/StreamxTerminalCommandProducer.java b/e2e-tests/src/main/java/dev/streamx/cli/StreamxTerminalCommandProducer.java
index 082e099c..c24370ce 100644
--- a/e2e-tests/src/main/java/dev/streamx/cli/StreamxTerminalCommandProducer.java
+++ b/e2e-tests/src/main/java/dev/streamx/cli/StreamxTerminalCommandProducer.java
@@ -1,6 +1,7 @@
package dev.streamx.cli;
import java.io.File;
+import java.nio.file.Path;
import java.util.regex.Pattern;
import java.util.stream.Stream;
@@ -39,7 +40,10 @@ private String findStreamxJar() {
.filter(File::exists)
.map(File::listFiles)
.flatMap(Stream::of)
- .map(File::getAbsolutePath)
+ .map(File::toPath)
+ .map(Path::toAbsolutePath)
+ .map(Path::normalize)
+ .map(Path::toString)
.filter(p -> pattern.matcher(p.replace("\\", "/")).matches())
.findFirst()
.orElseThrow(() -> new RuntimeException("Could not find streamx Jar"));
diff --git a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/terminal/OsTerminalCommandRunner.java b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/terminal/OsTerminalCommandRunner.java
index 30a2a335..390434e1 100644
--- a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/terminal/OsTerminalCommandRunner.java
+++ b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/terminal/OsTerminalCommandRunner.java
@@ -25,7 +25,6 @@ public OsTerminalCommandRunner() {
}
public ShellProcess run(String command) {
- logger.info("Running terminal command: " + command);
ProcessBuilder processBuilder = osCommand.create(command);
try {
ShellProcess shellProcess = ShellProcess.run(processBuilder);
@@ -33,6 +32,7 @@ public ShellProcess run(String command) {
processes.add(shellProcess);
return shellProcess;
} catch (IOException e) {
+ logger.info("Error running terminal command: " + command);
throw new RuntimeException(e);
}
}
diff --git a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/HttpValidator.java b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/HttpValidator.java
index 8829f8c4..385e8e14 100644
--- a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/HttpValidator.java
+++ b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/HttpValidator.java
@@ -1,17 +1,21 @@
package dev.streamx.cli.test.tools.validators;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
import static org.awaitility.Awaitility.await;
import jakarta.annotation.PreDestroy;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.io.IOException;
+import java.time.Duration;
+import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
+import org.assertj.core.api.ThrowingConsumer;
import org.jboss.logging.Logger;
@ApplicationScoped
@@ -22,32 +26,36 @@ public class HttpValidator {
@Inject
CloseableHttpClient httpClient;
- public void validate(String url, int expectedStatusCode, String expectedBody, int timeout) {
- await()
- .atMost(timeout, SECONDS)
- .alias("Assertion of response from url: " + url
- + " with expecting status:" + expectedStatusCode
- + " body:" + expectedBody
- + " timeout:" + timeout)
- .pollInterval(100, MILLISECONDS)
- .until(() ->
- validate(url, expectedStatusCode, expectedBody)
- );
+ public void validate(String url, int expectedStatusCode, String expectedBody, Duration timeout) {
+ validate(url, expectedStatusCode, timeout, httpEntity -> {
+ String responseBody = EntityUtils.toString(httpEntity);
+ assertThat(responseBody).describedAs(url).contains(expectedBody);
+ });
}
- private boolean validate(String url, int expectedStatusCode, String expectedBody) {
- HttpGet request = new HttpGet(url);
- try (CloseableHttpResponse response = httpClient.execute(request)) {
- int actualStatusCode = response.getStatusLine().getStatusCode();
- String responseBody = EntityUtils.toString(response.getEntity());
- logger.info("Request to " + url
- + " return statusCode " + actualStatusCode
- + " and body " + responseBody);
- return actualStatusCode == expectedStatusCode && responseBody.contains(expectedBody);
- } catch (IOException e) {
- logger.error("Request to " + url + "failed: " + e.getMessage(), e);
- throw new RuntimeException("Can not make request:" + url, e);
- }
+ public void validate(String url, int expectedStatusCode, byte[] expectedBody, Duration timeout) {
+ validate(url, expectedStatusCode, timeout, httpEntity -> {
+ byte[] responseBody = EntityUtils.toByteArray(httpEntity);
+ assertThat(responseBody).describedAs(url).containsExactly(expectedBody);
+ });
+ }
+
+ public void validate(String url, int expectedStatusCode, Duration timeout,
+ ThrowingConsumer responseEntityAssertion) {
+ await()
+ .atMost(timeout)
+ .pollInterval(100, MILLISECONDS)
+ .untilAsserted(() -> {
+ HttpGet request = new HttpGet(url);
+ try (CloseableHttpResponse response = httpClient.execute(request)) {
+ int statusCode = response.getStatusLine().getStatusCode();
+ assertThat(statusCode).describedAs(url).isEqualTo(expectedStatusCode);
+ HttpEntity responseEntity = response.getEntity();
+ responseEntityAssertion.accept(responseEntity);
+ } catch (IOException e) {
+ fail("Request to " + url + "failed", e);
+ }
+ });
}
@PreDestroy
diff --git a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/ProcessOutputValidator.java b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/ProcessOutputValidator.java
index dd39218b..d1c58a69 100644
--- a/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/ProcessOutputValidator.java
+++ b/e2e-tests/src/main/java/dev/streamx/cli/test/tools/validators/ProcessOutputValidator.java
@@ -1,10 +1,12 @@
package dev.streamx.cli.test.tools.validators;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+import dev.streamx.cli.test.tools.terminal.process.ShellProcess;
import jakarta.enterprise.context.ApplicationScoped;
+import java.time.Duration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -21,15 +23,19 @@ public class ProcessOutputValidator {
+ "[\\p{Alnum}.,%_=?\\-+()\\[\\]\\*$~@!:/{};']*)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
- public void validate(List output, String expectedContent, long timeout) {
+ public void validate(ShellProcess process, List output, String expectedContent,
+ Duration timeout) {
try {
await()
- .atMost(timeout, SECONDS)
+ .atMost(timeout)
.pollInterval(100, MILLISECONDS)
- .alias("Finding expectedContent:" + expectedContent)
- .until(() ->
- output
- .stream()
+ .alias("Finding expectedContent: " + expectedContent)
+ .untilAsserted(() ->
+ assertThat(output)
+ .describedAs(() -> "Full output is:\n"
+ + String.join("\n", process.getCurrentOutputLines())
+ + "\n"
+ + String.join("\n", process.getCurrentErrorLines()))
.anyMatch(line -> line.contains(expectedContent))
);
} catch (ConditionTimeoutException e) {
@@ -38,15 +44,13 @@ public void validate(List output, String expectedContent, long timeout)
}
}
- public String validateContainsUrl(List output, long timeout) {
+ public String validateContainsUrl(List output, Duration timeout) {
await()
- .atMost(timeout, SECONDS)
+ .atMost(timeout)
.pollInterval(100, MILLISECONDS)
.alias("Finding any url")
- .until(() ->
- output
- .stream()
- .anyMatch(line -> urlPattern.matcher(line).find())
+ .untilAsserted(() ->
+ assertThat(output).anyMatch(line -> urlPattern.matcher(line).find())
);
return output.stream()
diff --git a/e2e-tests/src/test/java/dev/streamx/cli/OsUtils.java b/e2e-tests/src/test/java/dev/streamx/cli/OsUtils.java
index f6b7a575..0a531834 100644
--- a/e2e-tests/src/test/java/dev/streamx/cli/OsUtils.java
+++ b/e2e-tests/src/test/java/dev/streamx/cli/OsUtils.java
@@ -1,6 +1,6 @@
package dev.streamx.cli;
-import dev.streamx.runner.validation.DockerEnvironmentValidator;
+import com.streamx.runner.validation.DockerEnvironmentValidator;
public class OsUtils {
public static boolean isDockerAvailable() {
diff --git a/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliLicenseIT.java b/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliLicenseIT.java
index c2141d0f..e5055942 100644
--- a/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliLicenseIT.java
+++ b/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliLicenseIT.java
@@ -12,6 +12,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@@ -20,7 +21,7 @@
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class StreamxCliLicenseIT {
- private static final int CLI_SHORT_TIMEOUT_IN_SEC = 5;
+ private static final Duration CLI_TIMEOUT = Duration.ofSeconds(10);
@Inject
@Named("StreamxCommandRunner")
@@ -85,9 +86,9 @@ public void shouldAcceptingLicenseAllowUsingWithoutMoreQuestions() {
private void assertIfLicenseIsAccessible(ShellProcess process) {
String url = processOutputValidator.validateContainsUrl(
process.getCurrentOutputLines(),
- CLI_SHORT_TIMEOUT_IN_SEC);
+ CLI_TIMEOUT);
httpValidator.validate(url, 200, "License",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ CLI_TIMEOUT);
}
private static void declineLicense(ShellProcess p) {
@@ -99,15 +100,15 @@ private static void acceptLicense(ShellProcess p) {
}
private void assertIfAcceptanceLicenseErrorPresent(ShellProcess p) {
- processOutputValidator.validate(
+ processOutputValidator.validate(p,
p.getCurrentErrorLines(),
"License acceptance is required for using StreamX",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ CLI_TIMEOUT);
}
private void assertIfStreamxCommandWork(ShellProcess p) {
- processOutputValidator.validate(p.getCurrentOutputLines(), "streamx-cli version",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ processOutputValidator.validate(p, p.getCurrentOutputLines(), "streamx-cli version",
+ CLI_TIMEOUT);
}
private ShellProcess runStreamxCommand() {
@@ -115,10 +116,10 @@ private ShellProcess runStreamxCommand() {
}
private void assertIfAcceptLicenseQuestionPresent(ShellProcess p) {
- processOutputValidator.validate(
+ processOutputValidator.validate(p,
p.getCurrentOutputLines(),
"Do you accept the license agreement?",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ CLI_TIMEOUT);
}
private static void resetLicenseAcceptance() {
diff --git a/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliPublicationIT.java b/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliPublicationIT.java
index 9aa8b477..1d398963 100644
--- a/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliPublicationIT.java
+++ b/e2e-tests/src/test/java/dev/streamx/cli/StreamxCliPublicationIT.java
@@ -1,8 +1,6 @@
package dev.streamx.cli;
-
import static dev.streamx.cli.test.tools.ResourcePathResolver.absolutePath;
-import static org.junit.jupiter.params.provider.Arguments.arguments;
import dev.streamx.cli.test.tools.terminal.TerminalCommandRunner;
import dev.streamx.cli.test.tools.terminal.process.ShellProcess;
@@ -11,26 +9,24 @@
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import jakarta.inject.Named;
-import java.util.List;
-import java.util.stream.Stream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.condition.EnabledIf;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
@QuarkusTest
@EnabledIf("dev.streamx.cli.OsUtils#isDockerAvailable")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class StreamxCliPublicationIT {
- private static final int CLI_SHORT_TIMEOUT_IN_SEC = 5;
+ private static final Duration CLI_TIMEOUT = Duration.ofSeconds(10);
@ConfigProperty(name = "streamx.cli.e2e.web.delivery.url", defaultValue = "http://localhost:8087/")
- String webDeliveryPortUrl;
- @ConfigProperty(name = "streamx.cli.e2e.nginx.url", defaultValue = "http://localhost:8089/overridden/")
- String nginxPortUrl;
+ String webDeliveryUrl;
@ConfigProperty(name = "streamx.cli.e2e.setup.timeoutInSec", defaultValue = "60")
int setupTimeoutInSec;
@@ -48,85 +44,92 @@ public class StreamxCliPublicationIT {
@BeforeAll
public void setup() {
runStreamxCommand(
- "--accept-license run -f " + absolutePath("mesh.yaml"),
+ "--accept-license run_v2 -f " + absolutePath("mesh.yaml"),
"STREAMX IS READY!",
- setupTimeoutInSec);
+ Duration.ofSeconds(setupTimeoutInSec));
}
- private void runStreamxCommand(String command, String expectedOutput, long timeoutInS) {
+ private void runStreamxCommand(String command, String expectedOutput, Duration timeout) {
ShellProcess p = terminalCommandRunner.run(command);
- processOutputValidator.validate(p.getCurrentOutputLines(), expectedOutput, timeoutInS);
+ processOutputValidator.validate(p, p.getCurrentOutputLines(), expectedOutput, timeout);
}
+ private void runStreamxIngestionCommand(String commandName, String path, String expectedOutput) {
+ String command = "--accept-license %s %s".formatted(commandName, path);
+ runStreamxCommand(command, expectedOutput, CLI_TIMEOUT);
+ }
- @ParameterizedTest
- @MethodSource("testCases")
- public void shouldTestPublishAndUnpublishPageOnStreamx(
- String pageName,
- String commandContentPart,
- String expectedPageContent
- ) {
-
- runStreamxCommand(
- "--accept-license publish pages " + pageName + " " + commandContentPart,
- "Sent data publication message to",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ @Test
+ public void shouldPublishAndUnpublishPageUsingStreamOperation() {
+ runStreamxIngestionCommand(
+ "stream_v2",
+ "src/test/resources/stream/page-publish-event.json",
+ "Sent com.streamx.blueprints.page.published.v1 event using stream with key 'hello.html'"
+ );
- validateStreamxPage(pageName, 200, expectedPageContent);
+ validateStreamxPage("hello.html", "Hello World!");
- runStreamxCommand(
- "--accept-license unpublish pages " + pageName,
- "Sent data unpublication message to",
- CLI_SHORT_TIMEOUT_IN_SEC);
+ runStreamxIngestionCommand(
+ "stream_v2",
+ "src/test/resources/stream/page-unpublish-event.json",
+ "Sent com.streamx.blueprints.page.unpublished.v1 event using stream with key 'hello.html'"
+ );
- validateStreamxPage(pageName, 404, "");
+ validateStreamxPageNotAvailable("hello.html");
}
- static Stream testCases() {
- return Stream.of(
- arguments(
- "third_param_page.html",
- absolutePath("payload.json"),
- "third_param_page"
- ),
- arguments(
- "exact_param_page.html",
- "-j '{\"content\":{\"bytes\":\"exact_param_page\"}}'",
- "exact_param_page"
- ),
- arguments(
- "json_path_exact_param_page.html",
- "-s content.bytes='Json exact page'",
- "Json exact page"
- ),
- arguments(
- "json_path_exact_param_page.html",
- "-b content.bytes='Json exact page'",
- "Json exact page"
- ),
- arguments(
- "file_param_page.html",
- "-j file://" + absolutePath("file_param_page.json"),
- "file_param_page"
- ),
- arguments(
- "json_path_file_param_page.html",
- "-s content.bytes=file://" + absolutePath("json_path_file_param_page.txt"),
- "json_path_file_param_page"
- ),
- arguments(
- "json_path_file_param_page.html",
- "-b content.bytes=file://" + absolutePath("json_path_file_param_page.txt"),
- "json_path_file_param_page"
- )
+ @Test
+ public void shouldPublishAndUnpublishPageUsingBatchOperation() {
+ runStreamxIngestionCommand(
+ "batch_v2",
+ "src/test/resources/batch/publish/page",
+ "Sent com.streamx.blueprints.page.published.v1 event using batch with key 'index.html'"
+ );
+
+ validateStreamxPage("index.html", "Hello World!
");
+
+ runStreamxIngestionCommand(
+ "batch_v2",
+ "src/test/resources/batch/unpublish/page",
+ "Sent com.streamx.blueprints.page.unpublished.v1 event using batch with key 'index.html'"
);
+
+ validateStreamxPageNotAvailable("index.html");
}
- private void validateStreamxPage(String resourcePath, int expectedStatusCode,
- String expectedBody) {
- List.of(webDeliveryPortUrl, nginxPortUrl).forEach(
- url -> httpValidator.validate(url + resourcePath, expectedStatusCode, expectedBody,
- CLI_SHORT_TIMEOUT_IN_SEC)
+ @Test
+ public void shouldPublishAndUnpublishAssetUsingBatchOperation() throws IOException {
+ runStreamxIngestionCommand(
+ "batch_v2",
+ "src/test/resources/batch/publish/asset",
+ "Sent com.streamx.blueprints.asset.published.v1 event using batch with key 'ds.png'"
);
+
+ validateStreamxPage("ds.png",
+ Files.readAllBytes(Path.of("src/test/resources/batch/publish/asset/ds.png")));
+
+ runStreamxIngestionCommand(
+ "batch_v2",
+ "src/test/resources/batch/unpublish/asset",
+ "Sent com.streamx.blueprints.asset.unpublished.v1 event using batch with key 'ds.png'"
+ );
+
+ validateStreamxPageNotAvailable("ds.png");
+ }
+
+ private void validateStreamxPage(String resourcePath, String expectedBody) {
+ httpValidator.validate(url(resourcePath), 200, expectedBody, CLI_TIMEOUT);
+ }
+
+ private void validateStreamxPage(String resourcePath, byte[] expectedBody) {
+ httpValidator.validate(url(resourcePath), 200, expectedBody, CLI_TIMEOUT);
+ }
+
+ private void validateStreamxPageNotAvailable(String resourcePath) {
+ httpValidator.validate(url(resourcePath), 404, "", CLI_TIMEOUT);
+ }
+
+ private String url(String resourcePath) {
+ return webDeliveryUrl + resourcePath;
}
}
diff --git a/e2e-tests/src/test/resources/batch/publish/asset/.eventsource.yaml b/e2e-tests/src/test/resources/batch/publish/asset/.eventsource.yaml
new file mode 100644
index 00000000..0d4ee277
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/publish/asset/.eventsource.yaml
@@ -0,0 +1,9 @@
+eventType: com.streamx.blueprints.asset.published.v1
+eventSource: source
+
+relativePathLevel: 0
+key: ${relativePath}
+
+payload:
+ content: file://${payloadPath}
+ type: assets/image
diff --git a/e2e-tests/src/test/resources/batch/publish/asset/ds.png b/e2e-tests/src/test/resources/batch/publish/asset/ds.png
new file mode 100644
index 00000000..4b85fd55
Binary files /dev/null and b/e2e-tests/src/test/resources/batch/publish/asset/ds.png differ
diff --git a/e2e-tests/src/test/resources/batch/publish/page/.eventsource.yaml b/e2e-tests/src/test/resources/batch/publish/page/.eventsource.yaml
new file mode 100644
index 00000000..eca8625a
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/publish/page/.eventsource.yaml
@@ -0,0 +1,9 @@
+eventType: com.streamx.blueprints.page.published.v1
+eventSource: source
+
+relativePathLevel: 0
+key: ${relativePath}
+
+payload:
+ content: file://${payloadPath}
+ type: page/index-page
diff --git a/e2e-tests/src/test/resources/batch/publish/page/index.html b/e2e-tests/src/test/resources/batch/publish/page/index.html
new file mode 100644
index 00000000..ba7c290e
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/publish/page/index.html
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/batch/unpublish/asset/.eventsource.yaml b/e2e-tests/src/test/resources/batch/unpublish/asset/.eventsource.yaml
new file mode 100644
index 00000000..e7f18c2f
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/unpublish/asset/.eventsource.yaml
@@ -0,0 +1,9 @@
+eventType: com.streamx.blueprints.asset.unpublished.v1
+eventSource: source
+
+relativePathLevel: 0
+key: ${relativePath}
+
+payload:
+ content: file://${payloadPath}
+ type: assets/image
diff --git a/e2e-tests/src/test/resources/batch/unpublish/asset/ds.png b/e2e-tests/src/test/resources/batch/unpublish/asset/ds.png
new file mode 100644
index 00000000..4b85fd55
Binary files /dev/null and b/e2e-tests/src/test/resources/batch/unpublish/asset/ds.png differ
diff --git a/e2e-tests/src/test/resources/batch/unpublish/page/.eventsource.yaml b/e2e-tests/src/test/resources/batch/unpublish/page/.eventsource.yaml
new file mode 100644
index 00000000..b6db9ffc
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/unpublish/page/.eventsource.yaml
@@ -0,0 +1,8 @@
+eventType: com.streamx.blueprints.page.unpublished.v1
+eventSource: source
+
+relativePathLevel: 0
+key: ${relativePath}
+
+payload:
+ type: page/index-page
diff --git a/e2e-tests/src/test/resources/batch/unpublish/page/index.html b/e2e-tests/src/test/resources/batch/unpublish/page/index.html
new file mode 100644
index 00000000..ba7c290e
--- /dev/null
+++ b/e2e-tests/src/test/resources/batch/unpublish/page/index.html
@@ -0,0 +1 @@
+Hello World!
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/configs/overridden-nginx-conf b/e2e-tests/src/test/resources/configs/overridden-nginx-conf
deleted file mode 100644
index 329f89b7..00000000
--- a/e2e-tests/src/test/resources/configs/overridden-nginx-conf
+++ /dev/null
@@ -1,10 +0,0 @@
-server {
- listen 80;
- listen [::]:80;
- server_name localhost;
-
- location /overridden {
- alias /usr/share/nginx/html;
- }
-}
-
diff --git a/e2e-tests/src/test/resources/file_param_page.json b/e2e-tests/src/test/resources/file_param_page.json
deleted file mode 100644
index 6cb37e37..00000000
--- a/e2e-tests/src/test/resources/file_param_page.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "content": {
- "bytes": "file_param_page"
- }
-}
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/filtered/mesh.yaml b/e2e-tests/src/test/resources/filtered/mesh.yaml
index 71e1ac93..b163ea17 100644
--- a/e2e-tests/src/test/resources/filtered/mesh.yaml
+++ b/e2e-tests/src/test/resources/filtered/mesh.yaml
@@ -1,44 +1,70 @@
-defaultRegistry: ghcr.io/streamx-dev/streamx
-defaultImageTag: ${streamx.version}-jvm
+descriptors:
+ relay:
+ type: "processing"
+ containers:
+ service:
+ incoming:
+ events: {}
+ outgoing:
+ relayed-events: {}
+
+ web-server-sink:
+ type: "edge"
+ containers:
+ sink:
+ image: "ghcr.io/streamx-com/streamx-blueprints/web-server-sink:3.0.7-jvm"
+ incoming:
+ resources: {}
+ servicePorts:
+ - "8087:8080"
sources:
cli:
outgoing:
- - "pages"
+ - ref: "inbox.pages"
+ produces:
+ - "com.streamx.blueprints.page.published.v1"
+ - "com.streamx.blueprints.page.unpublished.v1"
+ - ref: "inbox.assets"
+ produces:
+ - "com.streamx.blueprints.asset.published.v1"
+ - "com.streamx.blueprints.asset.unpublished.v1"
+
+ingestion:
+ rest-ingestion:
+ containers:
+ proxy:
+ environment:
+ QUARKUS_HTTP_AUTH_PERMISSION_BEARER_POLICY: permit
processing:
- relay:
- image: sample-relay-processing-service
- incoming:
- incoming-pages:
- topic: inboxes/pages
- outgoing:
- outgoing-pages:
- topic: outboxes/pages
+ pages-relay:
+ descriptor: relay
+ containers:
+ service:
+ incoming:
+ events:
+ ref: inbox.pages
+ outgoing:
+ relayed-events:
+ ref: outbox.pages
-delivery:
- web-delivery:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8087
- composite-web-delivery:
- image: sample-web-delivery-service
- incoming:
- pages:
- topic: outboxes/pages
- port: 8088
- environment:
- REPOSITORY_RESOURCE_ROOT_DIRECTORY: "/home/runner/work/streamx-cli/streamx-cli/srv/www"
- repositoryVolume: "/home/runner/work/streamx-cli/streamx-cli/srv/www"
- components:
- webserver:
- image: "docker.io/library/nginx:1.26.0"
- ports:
- - ${streamx.cli.e2e.port}:80
- repositoryVolume: "/usr/share/nginx/html"
- volumesFrom:
- configs:
- - "overridden-nginx-conf:/etc/nginx/conf.d/default.conf"
+ assets-relay:
+ descriptor: relay
+ containers:
+ service:
+ incoming:
+ events:
+ ref: inbox.assets
+ outgoing:
+ relayed-events:
+ ref: outbox.assets
+edge:
+ web-server-sink:
+ descriptor: web-server-sink
+ containers:
+ sink:
+ incoming:
+ resources:
+ ref: outbox.pages,outbox.assets
diff --git a/e2e-tests/src/test/resources/json_path_file_param_page.txt b/e2e-tests/src/test/resources/json_path_file_param_page.txt
deleted file mode 100644
index bb24ea82..00000000
--- a/e2e-tests/src/test/resources/json_path_file_param_page.txt
+++ /dev/null
@@ -1 +0,0 @@
-json_path_file_param_page
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/payload.json b/e2e-tests/src/test/resources/payload.json
deleted file mode 100644
index d685f897..00000000
--- a/e2e-tests/src/test/resources/payload.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "content": {
- "bytes": "third_param_page"
- }
-}
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/stream/.stream.properties b/e2e-tests/src/test/resources/stream/.stream.properties
new file mode 100644
index 00000000..15b64ec4
--- /dev/null
+++ b/e2e-tests/src/test/resources/stream/.stream.properties
@@ -0,0 +1 @@
+json.fields.as-base64=/data/content
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/stream/page-publish-event.json b/e2e-tests/src/test/resources/stream/page-publish-event.json
new file mode 100644
index 00000000..c8b1f8f3
--- /dev/null
+++ b/e2e-tests/src/test/resources/stream/page-publish-event.json
@@ -0,0 +1,13 @@
+{
+ "specversion" : "1.0",
+ "id" : "11111111-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "com.streamx.blueprints.page.published.v1",
+ "datacontenttype" : "application/json",
+ "subject" : "hello.html",
+ "time" : "2025-12-23T10:28:23.435253Z",
+ "data" : {
+ "content" : "Hello World!",
+ "type" : "page/test"
+ }
+}
\ No newline at end of file
diff --git a/e2e-tests/src/test/resources/stream/page-unpublish-event.json b/e2e-tests/src/test/resources/stream/page-unpublish-event.json
new file mode 100644
index 00000000..ec767e45
--- /dev/null
+++ b/e2e-tests/src/test/resources/stream/page-unpublish-event.json
@@ -0,0 +1,8 @@
+{
+ "specversion" : "1.0",
+ "id" : "11111111-327e-4bee-96a1-3e4224a1e71d",
+ "source" : "source",
+ "type" : "com.streamx.blueprints.page.unpublished.v1",
+ "subject" : "hello.html",
+ "time" : "2025-12-23T10:28:23.435253Z"
+}
\ No newline at end of file
diff --git a/entrypoint/src/main/java/dev/streamx/cli/EntrypointMain.java b/entrypoint/src/main/java/dev/streamx/cli/EntrypointMain.java
index 81edfde6..cc3f86f1 100644
--- a/entrypoint/src/main/java/dev/streamx/cli/EntrypointMain.java
+++ b/entrypoint/src/main/java/dev/streamx/cli/EntrypointMain.java
@@ -14,8 +14,8 @@ public class EntrypointMain {
public static void main(String[] args) {
int javaVersion = getJavaVersion();
- if (javaVersion < 17) {
- System.out.println("Java 17 or higher is required!");
+ if (javaVersion < 21) {
+ System.out.println("Java 21 or higher is required!");
return;
}
diff --git a/entrypoint/src/test/java/dev/streamx/cli/EntrypointMainTest.java b/entrypoint/src/test/java/dev/streamx/cli/EntrypointMainTest.java
index a790c2e5..e6daad54 100644
--- a/entrypoint/src/test/java/dev/streamx/cli/EntrypointMainTest.java
+++ b/entrypoint/src/test/java/dev/streamx/cli/EntrypointMainTest.java
@@ -53,7 +53,7 @@ void shouldFailTooLowJavaVersions(String javaVersion) {
// then
Assertions.assertFalse(StreamxCommand.isLaunched());
Assertions.assertTrue(
- byteArrayOutputStream.toString().contains("Java 17 or higher is required!")
+ byteArrayOutputStream.toString().contains("Java 21 or higher is required!")
);
}
diff --git a/pom.xml b/pom.xml
index e0ec4b0a..060e1317 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,9 +41,7 @@
io.quarkus.platform
3.18.3
- 1.0.16
- 1.1.1
- 0.0.16
+ 2.0.8
2.9.0
3.27.3
3.12.1
@@ -76,20 +74,14 @@
- dev.streamx
+ com.streamx
streamx-runner
${streamx.version}
- dev.streamx
+ com.streamx
ingestion-client
- ${ingestion-client.version}
-
-
-
- dev.streamx
- streamx-operator-mesh-api
- ${streamx-operator.version}
+ ${streamx.version}
com.jayway.jsonpath