diff --git a/README.md b/README.md index bd3f7c65..98253760 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ operator-suite/container/scripts/run-test.sh --help | COLLECT_TEST_DATA | Whether to gather test data on error or not | `true` | `true`, `false` | | TESTS | Which tests to execute (maven syntax) | not set | | +## More information +For more information about subprojects - refer to README.md files in `operator-suite` or `standalone-suite` folders, which contain more details about usage, more environment variables, etc. ## Hints - keep code clean diff --git a/common/src/main/java/io/brokerqe/claire/ArtemisConstants.java b/common/src/main/java/io/brokerqe/claire/ArtemisConstants.java index 7b3448e8..4b4d81fb 100644 --- a/common/src/main/java/io/brokerqe/claire/ArtemisConstants.java +++ b/common/src/main/java/io/brokerqe/claire/ArtemisConstants.java @@ -166,6 +166,20 @@ public interface ArtemisConstants { // Log Strings + static String getArtemisVersionString(String version) { + // Red Hat AMQ Broker 7.11.1.GA + return String.format("Red Hat AMQ Broker %s.GA", version); + } + + static String getArtemisVersionStringOld(String version) { + // Red Hat AMQ 7.10.1.GA + return String.format("Red Hat AMQ %s.GA", version); + } + + static String getArtemisStartingServerVersionString(String version) { + return String.format("Starting ActiveMQ Artemis Server version %s", version); + } + String IS_LIVE_LOG_MSG = " INFO [org.apache.activemq.artemis.core.server] AMQ221007: Server is now"; String USING_CUSTOM_LOG_MSG = "There is a custom logger configuration defined in JAVA_ARGS_APPEND: -Dlog4j2.configurationFile="; String USING_DEFAULT_LOG_MSG = "Using default logging configuration(console only)"; diff --git a/common/src/main/java/io/brokerqe/claire/Constants.java b/common/src/main/java/io/brokerqe/claire/Constants.java index 42e4a596..89c0cfd9 100644 --- a/common/src/main/java/io/brokerqe/claire/Constants.java +++ b/common/src/main/java/io/brokerqe/claire/Constants.java @@ -10,6 +10,7 @@ public interface Constants { // Platform related strings String LINE_SEPARATOR = System.getProperty("line.separator"); String FILE_SEPARATOR = System.getProperty("file.separator"); + String TMP_DIR_SYSTEM = System.getProperty("java.io.tmpdir"); String DATE_FORMAT = "yyyy-MM-dd_HH-mm-ss"; // Test tags @@ -70,7 +71,9 @@ public interface Constants { // Networking String AMQP = "amqp"; + String TCP = "tcp"; String AMQP_URL_PREFIX = AMQP + "://"; + String TCP_URL_PREFIX = TCP + "://"; String HTTP = "http"; String HTTPS = "https"; String GET = "GET"; @@ -146,8 +149,8 @@ public interface Constants { String ARTEMIS_DEFAULT_CFG_DIR = "artemis/artemis_default_cfg"; String ARTEMIS_TEST_CFG_DIR = "test-cfg"; - String ARTEMIS_DEFAULT_CFG_BIN_DIR = ARTEMIS_DEFAULT_CFG_DIR + FILE_SEPARATOR + ArtemisConstants.BIN_DIR; - String ARTEMIS_DEFAULT_CFG_LIB_DIR = ARTEMIS_DEFAULT_CFG_DIR + FILE_SEPARATOR + ArtemisConstants.LIB_DIR; + String ARTEMIS_DEFAULT_CFG_BIN_DIR = ARTEMIS_DEFAULT_CFG_DIR + ArtemisConstants.BIN_DIR; + String ARTEMIS_DEFAULT_CFG_LIB_DIR = ARTEMIS_DEFAULT_CFG_DIR + ArtemisConstants.LIB_DIR; String PREFIX_SYSTEMTESTS_CLIENTS = "systemtests-clients"; String PREFIX_SYSTEMTESTS_CLI_PROTON_DOTNET = "systemtests-cli-proton-dotnet"; diff --git a/common/src/main/java/io/brokerqe/claire/Environment.java b/common/src/main/java/io/brokerqe/claire/Environment.java index 81495523..929e93f9 100644 --- a/common/src/main/java/io/brokerqe/claire/Environment.java +++ b/common/src/main/java/io/brokerqe/claire/Environment.java @@ -37,6 +37,7 @@ public String getCertificatesLocation() { static final Logger LOGGER = LoggerFactory.getLogger(Environment.class); protected String databaseFile; + protected String testUpgradePlan; private Database database; private static Environment environment; private Properties appProperties; @@ -62,7 +63,15 @@ public String getJdbcDatabaseFile() { return databaseFile; } - protected ArtemisVersion convertArtemisVersion(String version) { + public String getTestUpgradePlanContent() { + if (testUpgradePlan != null) { + return TestUtils.readFileContent(new File(testUpgradePlan)); + } else { + throw new IllegalArgumentException(Constants.EV_UPGRADE_PLAN + " variable has not been set!"); + } + } + + public ArtemisVersion convertArtemisVersion(String version) { ArtemisVersion versionRet; if (isUpstreamArtemis()) { return ArtemisVersion.values()[ArtemisVersion.values().length - 1]; diff --git a/common/src/main/java/io/brokerqe/claire/LocalExecutor.java b/common/src/main/java/io/brokerqe/claire/LocalExecutor.java new file mode 100644 index 00000000..d57e8194 --- /dev/null +++ b/common/src/main/java/io/brokerqe/claire/LocalExecutor.java @@ -0,0 +1,85 @@ +/* + * Copyright Strimzi and Broker QE authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.brokerqe.claire; + +import io.brokerqe.claire.exception.ClaireNotImplementedException; +import io.brokerqe.claire.executor.Executor; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.time.Duration; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + + +public class LocalExecutor implements Executor { + + private String commandDataOutput; + private int exitCode; + @Override + public Object executeCommand(String... cmd) { + return executeCommand(Duration.ofSeconds(60).toSeconds(), cmd); + } + + @Override + public Object executeCommand(long maxExecMs, String... cmd) { + ProcessBuilder builder = new ProcessBuilder(cmd); + builder.directory(new File(System.getProperty("user.home"))); + try { + Process process = builder.start(); + StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println); + streamGobbler.run(); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.submit(streamGobbler); + exitCode = process.waitFor(); + executor.shutdown(); + commandDataOutput = streamGobbler.toString(); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + + return exitCode; + } + + @Override + public void execBackgroundCommand(String... cmd) { + throw new ClaireNotImplementedException("Not implemented yet"); + } + + @Override + public boolean isBackgroundCommandFinished() { + throw new ClaireNotImplementedException("Not implemented yet"); + } + + @Override + public String getBackgroundCommandData(int waitTime) { + throw new ClaireNotImplementedException("Not implemented yet"); + } + + @Override + public String getCommandData(long timeout) { + return commandDataOutput; + } +} + +class StreamGobbler implements Runnable { + private InputStream inputStream; + private Consumer consumer; + + public StreamGobbler(InputStream inputStream, Consumer consumer) { + this.inputStream = inputStream; + this.consumer = consumer; + } + + @Override + public void run() { + new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer); + } +} diff --git a/common/src/main/java/io/brokerqe/claire/TestUtils.java b/common/src/main/java/io/brokerqe/claire/TestUtils.java index 86d5b27e..f5b63e7c 100644 --- a/common/src/main/java/io/brokerqe/claire/TestUtils.java +++ b/common/src/main/java/io/brokerqe/claire/TestUtils.java @@ -51,6 +51,7 @@ import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -62,7 +63,9 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Arrays; import java.util.Base64; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; @@ -83,6 +86,21 @@ public static Path getProjectRelativeFilePath(String projectRelativeFile) { return Paths.get(Constants.PROJECT_USER_DIR, projectRelativeFile).toAbsolutePath(); } + // ========== Execute command Operations ========== + + public static String executeLocalCommand(String cmd) { + return executeLocalCommand(cmd.split(" ")); + } + + public static String executeLocalCommand(String... cmd) { + LocalExecutor executor = new LocalExecutor(); + LOGGER.debug("[CMD][local] {}", Arrays.stream(cmd).toArray()); + executor.executeCommand(cmd); + String output = executor.getCommandData(Duration.ofSeconds(10).toSeconds()); + LOGGER.debug("[CMD][local] Output\n{}", output); + return output; + } + // ========== Junit Test Operations ========== public static String getClassName(ExtensionContext extensionContext) { return extensionContext.getRequiredTestClass().getName(); @@ -312,9 +330,12 @@ public static String getElementByXpathFromXml(String elementXPathExpression, Fil // ========== Network Operations ========== public static void getFileFromUrl(String stringUrl, String outputFile) { if (!Files.exists(Paths.get(outputFile))) { - LOGGER.debug("Downloading {} to {}", stringUrl, outputFile); + LOGGER.debug("[Download] {} to {}", stringUrl, outputFile); try { URL url = new URL(stringUrl); + if (stringUrl.startsWith("https")) { + makeInsecureHttpsRequest(stringUrl); + } ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); FileOutputStream fileOutputStream = new FileOutputStream(outputFile); fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); @@ -470,6 +491,34 @@ public static void copyDirectoryFlat(String source, String target) { } } + public static void copyDirectories(String source, String target) { + try { + Path sourceDir = Paths.get(source); + Path targetDir = Paths.get(target); + LOGGER.debug("[Copy] Recursively {} -> {}", source, target); + Files.walk(sourceDir) + .forEach(sourcePath -> { + try { + Path targetPath = targetDir.resolve(sourceDir.relativize(sourcePath)); + Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static void moveDirectory(String srcDir, String newDir) { + try { + LOGGER.debug("[Move] {} -> {}", srcDir, newDir); + FileUtils.moveDirectory(new File(srcDir), new File(newDir)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public static void copyFile(String source, String target) { try { Files.copy(Path.of(source), Path.of(target), StandardCopyOption.REPLACE_EXISTING); @@ -488,8 +537,24 @@ public static Path findFile(String directory, String filename) { } } - public static String replaceFileContent(String filePath, String toReplace, String replaceWith) { - String newFilePath = filePath + "_tmpFile" + TestUtils.getRandomString(3); + public static List searchForGlobFile(String directory, String globPattern, int maxDepth) { + List paths; + try { + paths = Files.find(Paths.get(directory), maxDepth, (path, attr) -> { + LOGGER.debug(path.toString()); + return FileSystems.getDefault().getPathMatcher(globPattern).matches(path); + }).toList(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return paths; + } + + public static String replaceFileContent(String filePath, String toReplace, String replaceWith, boolean inPlace) { + String newFilePath = filePath; + if (!inPlace) { + newFilePath += "_tmpFile" + TestUtils.getRandomString(3); + } String data = readFileContent(new File(filePath)); data = data.replace(toReplace, replaceWith); TestUtils.createFile(newFilePath, data); @@ -560,6 +625,7 @@ public static void unTar(final String inputFile, final String outputDir) { public static void unzip(String archivePath, String unarchivePath) { try { + LOGGER.debug("[Unzip] {} -> {}", archivePath, unarchivePath); new ZipFile(Paths.get(archivePath).toFile()).extractAll(unarchivePath); } catch (IOException e) { throw new RuntimeException(e); diff --git a/common/src/main/java/io/brokerqe/claire/clients/Protocol.java b/common/src/main/java/io/brokerqe/claire/clients/Protocol.java new file mode 100644 index 00000000..8e0e47b6 --- /dev/null +++ b/common/src/main/java/io/brokerqe/claire/clients/Protocol.java @@ -0,0 +1,12 @@ +/* + * Copyright Broker QE authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.brokerqe.claire.clients; + +public enum Protocol { + AMQP, + AMQPS, + CORE, + CORES +} diff --git a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledAmqpMessagingClient.java b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledAmqpMessagingClient.java index 14945cfa..a5e57dcd 100644 --- a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledAmqpMessagingClient.java +++ b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledAmqpMessagingClient.java @@ -4,6 +4,10 @@ */ package io.brokerqe.claire.clients.bundled; +import io.brokerqe.claire.clients.Protocol; + +import java.util.Locale; + public class BundledAmqpMessagingClient extends BundledMessagingClient { public BundledAmqpMessagingClient(BundledClientOptions options) { @@ -12,6 +16,6 @@ public BundledAmqpMessagingClient(BundledClientOptions options) { @Override String getProtocol() { - return "amqp"; + return Protocol.AMQP.name().toLowerCase(Locale.ROOT); } } diff --git a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledClientOptions.java b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledClientOptions.java index 87418d72..376bccdf 100644 --- a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledClientOptions.java +++ b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledClientOptions.java @@ -6,6 +6,7 @@ package io.brokerqe.claire.clients.bundled; import io.brokerqe.claire.clients.DeployableClient; +import io.brokerqe.claire.clients.Protocol; public class BundledClientOptions { DeployableClient deployableClient; @@ -18,6 +19,7 @@ public class BundledClientOptions { String password; Boolean persistenceDisabled = false; Boolean multicast = false; + Protocol protocol; public BundledClientOptions withDeployableClient(DeployableClient deployableClient) { this.deployableClient = deployableClient; @@ -66,6 +68,54 @@ public BundledClientOptions withPersistenceDisabled(Boolean persistenceDisabled) public BundledClientOptions withMulticast(Boolean multicast) { this.multicast = multicast; return this; + } + + public BundledClientOptions withProtocol(Protocol protocol) { + this.protocol = protocol; + return this; + } + + public DeployableClient getDeployableClient() { + return deployableClient; + } + + public String getDestinationUrl() { + return destinationUrl; + } + + public String getDestinationPort() { + return destinationPort; + } + + public String getDestinationAddress() { + return destinationAddress; + } + + public String getDestinationQueue() { + return destinationQueue; + } + + public int getMessageCount() { + return messageCount; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public Boolean getPersistenceDisabled() { + return persistenceDisabled; + } + + public Boolean getMulticast() { + return multicast; + } + public Protocol getProtocol() { + return protocol; } } \ No newline at end of file diff --git a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledCoreMessagingClient.java b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledCoreMessagingClient.java index 24818593..65de73cb 100644 --- a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledCoreMessagingClient.java +++ b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledCoreMessagingClient.java @@ -4,6 +4,10 @@ */ package io.brokerqe.claire.clients.bundled; +import io.brokerqe.claire.clients.Protocol; + +import java.util.Locale; + public class BundledCoreMessagingClient extends BundledMessagingClient { public BundledCoreMessagingClient(BundledClientOptions options) { @@ -11,6 +15,6 @@ public BundledCoreMessagingClient(BundledClientOptions options) { } public String getProtocol() { - return "core"; + return Protocol.CORE.name().toLowerCase(Locale.ROOT); } } diff --git a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledMessagingClient.java b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledMessagingClient.java index 38d19e79..fb8d9f77 100644 --- a/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledMessagingClient.java +++ b/common/src/main/java/io/brokerqe/claire/clients/bundled/BundledMessagingClient.java @@ -20,7 +20,7 @@ public abstract class BundledMessagingClient implements MessagingClient { private static final Logger LOGGER = LoggerFactory.getLogger(BundledMessagingClient.class); private final String destinationAddress; - private final String destinationUrl; + private String destinationUrl; private final String destinationPort; private final String destinationQueue; private final String protocol; @@ -108,7 +108,10 @@ private String[] constructClientCommand(String clientType) { } } - String command = String.format("%s/artemis %s --url tcp://%s:%s --protocol %s --destination %s", + if (!destinationUrl.contains("://")) { + destinationUrl = "tcp://" + destinationUrl; + } + String command = String.format("%s/artemis %s --url %s:%s --protocol %s --destination %s", deployableClient.getExecutableHome(), clientType, destinationUrl, destinationPort, protocol, clientDestination); if (messageCount != -2) { diff --git a/operator-suite/src/main/java/io/brokerqe/claire/EnvironmentOperator.java b/operator-suite/src/main/java/io/brokerqe/claire/EnvironmentOperator.java index b10633fd..9cf2ad09 100644 --- a/operator-suite/src/main/java/io/brokerqe/claire/EnvironmentOperator.java +++ b/operator-suite/src/main/java/io/brokerqe/claire/EnvironmentOperator.java @@ -13,7 +13,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Path; @@ -40,7 +39,6 @@ public class EnvironmentOperator extends Environment { private final String brokerInitImage; private final String operatorImage; private final String bundleImage; - private final String testUpgradePlan; private final boolean projectManagedClusterOperator; private final String logsDirLocation; private final String tmpDirLocation; @@ -323,13 +321,6 @@ public String getOperatorImage() { public String getBundleImage() { return bundleImage; } - public String getTestUpgradePlanContent() { - if (testUpgradePlan != null) { - return TestUtils.readFileContent(new File(testUpgradePlan)); - } else { - throw new IllegalArgumentException(Constants.EV_UPGRADE_PLAN + " variable has not been set!"); - } - } private String getDefaultKeycloakOperatorName() { if (isUpstreamArtemis()) { diff --git a/operator-suite/src/test/java/io/brokerqe/claire/upgrade/UpgradeOlmTests.java b/operator-suite/src/test/java/io/brokerqe/claire/upgrade/UpgradeOlmTests.java index 12f361bc..24e58f08 100644 --- a/operator-suite/src/test/java/io/brokerqe/claire/upgrade/UpgradeOlmTests.java +++ b/operator-suite/src/test/java/io/brokerqe/claire/upgrade/UpgradeOlmTests.java @@ -7,6 +7,7 @@ import io.amq.broker.v1beta1.ActiveMQArtemis; import io.amq.broker.v1beta1.ActiveMQArtemisAddress; import io.brokerqe.claire.AbstractSystemTests; +import io.brokerqe.claire.ArtemisConstants; import io.brokerqe.claire.Constants; import io.brokerqe.claire.ResourceManager; import io.brokerqe.claire.clients.ClientType; @@ -124,8 +125,8 @@ void microIncrementalTest(ArgumentsAccessor argumentsAccessor) { assertThat(operatorLogs, containsString(operatorVersionString)); // Red Hat AMQ 7.10.1.GA - String brokerVersionOldString = "Red Hat AMQ " + version + ".GA"; - String brokerVersionNewString = "Red Hat AMQ Broker " + version + ".GA"; + String brokerVersionOldString = ArtemisConstants.getArtemisVersionString(version); + String brokerVersionNewString = ArtemisConstants.getArtemisVersionStringOld(version); for (Pod brokerUpgradePod : brokerUpgradePods) { LOGGER.info("[{}] Check expected version {} in {} pod logs", testNamespace, version, brokerUpgradePod.getMetadata().getName()); String brokerLogs = getClient().getLogsFromPod(brokerUpgradePod); diff --git a/standalone-suite/README.md b/standalone-suite/README.md index 6681a959..70065430 100644 --- a/standalone-suite/README.md +++ b/standalone-suite/README.md @@ -67,6 +67,19 @@ Standalone test suite provides support for databases in two ways: In deployed DB way, relevant _bitnami mariadb/mysql/postgresql_, _container-registry.oracle.com/database/free_ or _mcr.microsoft.com/mssql/server:2022_ container will be spawned and used for testing. +## YACFG Artemis configuration genration tool +- If needed to use custom yacfg, use following exported variables & example command + ```shell + export YACFG_TEMPLATES=/yacfg_artemis/templates + export YACFG_PROFILES=/yacfg_artemis/profiles + cd + yacfg --profile artemis/.yaml.jinja2 --tune /.yaml.jinja2 --output + + yacfg --profile artemis/claire-default-profile-2.34.0.yaml.jinja2 \ + --tune claire/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/primary-tune.yaml.jinja2 \ + --output primary-lala + ``` + ## Development Hints - Keep the code clean :-) - If you are going to implement a container verify if it already exists on testcontainer modules (go to the modules @@ -75,5 +88,4 @@ section on testcontainers main page) the tests. These classes have some important comments on it - The `helper` package contains useful classes which helps to create tests specially the `ArtemisJmxHelper` class - The `client.jms` package contains the client implementations (currently, in an early stage) -- Remember to add the initial header on new files/classes, otherwise the build will fail on checkstyle checks (you may -configure your IDE to automatically add the header on new files) +- Remember to add the initial header on new files/classes, otherwise the build will fail on checkstyle checks (you may configure your IDE to automatically add the header on new files) diff --git a/standalone-suite/dockerfiles/artemis/artemis-controller.sh b/standalone-suite/dockerfiles/artemis/artemis-controller.sh index bf5841e1..6cfe23e1 100755 --- a/standalone-suite/dockerfiles/artemis/artemis-controller.sh +++ b/standalone-suite/dockerfiles/artemis/artemis-controller.sh @@ -43,7 +43,6 @@ function umount_nfs() { function start() { echo "" echo "Going to start artemis" - echo "" nohup /var/lib/artemis-instance/bin/artemis run 2>&1 & sleep 2 pidof java > "${PID_FILE}" diff --git a/standalone-suite/dockerfiles/artemis/docker-entrypoint.sh b/standalone-suite/dockerfiles/artemis/docker-entrypoint.sh index 530d5c4d..f17aa685 100755 --- a/standalone-suite/dockerfiles/artemis/docker-entrypoint.sh +++ b/standalone-suite/dockerfiles/artemis/docker-entrypoint.sh @@ -18,7 +18,9 @@ function start { echo "About to start artemis" echo "" artemis-controller.sh mount_nfs + echo "nfs mounted" artemis-controller.sh start + echo "artemis-controller.sh started" } if [ $UID -eq 0 ]; then diff --git a/standalone-suite/src/main/java/io/brokerqe/claire/EnvironmentStandalone.java b/standalone-suite/src/main/java/io/brokerqe/claire/EnvironmentStandalone.java index 18e116a1..d39ad0af 100644 --- a/standalone-suite/src/main/java/io/brokerqe/claire/EnvironmentStandalone.java +++ b/standalone-suite/src/main/java/io/brokerqe/claire/EnvironmentStandalone.java @@ -53,6 +53,7 @@ private EnvironmentStandalone() { loadProjectProperties(Constants.STANDALONE_MODULE_PROPERTIES_FILE); this.set(this); databaseFile = getConfigurationValue(Constants.EV_JDBC_DATA, Constants.PROP_JDBC_DATA, null); + testUpgradePlan = System.getenv().getOrDefault(Constants.EV_UPGRADE_PLAN, null); osInfo = getOSInfo(); // Default value is in logback settings file logLevel = getConfigurationValue(Constants.EV_TEST_LOG_LEVEL, Constants.PROP_LOG_LEVEL, ArtemisConstants.DEFAULT_LOG_LEVEL); @@ -134,6 +135,7 @@ private void printAllUsedTestVariables() { Constants.PROP_YACFG_ARTEMIS_PROFILES_OVERRIDE_DIR + ": " + yacfgArtemisProfilesOverrideDir + Constants.LINE_SEPARATOR + Constants.PROP_YACFG_ARTEMIS_TEMPLATES_OVERRIDE_DIR + ": " + yacfgArtemisTemplatesOverrideDir + Constants.LINE_SEPARATOR + Constants.PROP_JDBC_DATA + ": " + databaseFile + Constants.LINE_SEPARATOR + + Constants.EV_UPGRADE_PLAN + ": " + testUpgradePlan + Constants.LINE_SEPARATOR + Constants.PROP_USE_EXISTING_CONFIG + ": " + providedArtemisConfig; LOGGER.info(envVars); } diff --git a/standalone-suite/src/main/java/io/brokerqe/claire/client/deployment/ArtemisDeployment.java b/standalone-suite/src/main/java/io/brokerqe/claire/client/deployment/ArtemisDeployment.java new file mode 100644 index 00000000..704f232e --- /dev/null +++ b/standalone-suite/src/main/java/io/brokerqe/claire/client/deployment/ArtemisDeployment.java @@ -0,0 +1,69 @@ +/* + * Copyright Broker QE authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.brokerqe.claire.client.deployment; + +import io.brokerqe.claire.ArtemisConstants; +import io.brokerqe.claire.Constants; +import io.brokerqe.claire.EnvironmentStandalone; +import io.brokerqe.claire.TestUtils; +import io.brokerqe.claire.container.ArtemisContainer; +import org.junit.jupiter.api.TestInfo; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ArtemisDeployment { + + public static String downloadPrepareArtemisInstallDir(TestInfo testInfo, String artemisZipUrl, String version, String testConfigDir) { + String testName = TestUtils.getClassName(testInfo) + "_" + TestUtils.getRandomString(2); + String filename = artemisZipUrl.substring(artemisZipUrl.lastIndexOf("/") + 1); + String tmpTestFile = EnvironmentStandalone.getInstance().getTmpDirLocation() + Constants.FILE_SEPARATOR + testName; + + + String tmpZipPath = Constants.TMP_DIR_SYSTEM + Constants.FILE_SEPARATOR + filename; + String artemisInstallDirTmp = tmpTestFile + Constants.FILE_SEPARATOR + testName; + String installDir = testConfigDir + Constants.FILE_SEPARATOR + version + "_install"; + + TestUtils.createDirectory(tmpTestFile); + TestUtils.deleteDirectoryRecursively(Paths.get(installDir)); + TestUtils.createDirectory(installDir); + TestUtils.getFileFromUrl(artemisZipUrl, tmpZipPath); + if (tmpZipPath.endsWith(".zip")) { + TestUtils.unzip(tmpZipPath, artemisInstallDirTmp); + List paths = TestUtils.searchForGlobFile(artemisInstallDirTmp, "glob:**/apache-artemis-*", 1); + TestUtils.copyDirectories(paths.get(0).toString(), installDir); + } + return installDir; + } + + public static Map createArtemisInstanceFromInstallDir(String installDir, String instanceName, String instanceDir) { + // create default instance for given version (for instance/bin directory) + String createCmd = installDir + "/bin/artemis create --force --name " + instanceName + + " --user " + ArtemisConstants.ADMIN_NAME + " --password " + ArtemisConstants.ADMIN_PASS + + " --require-login " + instanceDir; + TestUtils.executeLocalCommand(createCmd); + // update artemis.profile to point to exact 'etc' folder (in future container) + TestUtils.replaceFileContent(instanceDir + "/bin/artemis", + "ARTEMIS_INSTANCE_ETC='" + instanceDir + "/etc'", + "ARTEMIS_INSTANCE_ETC=" + ArtemisContainer.ARTEMIS_INSTANCE_ETC_DIR, + true); + + Map artemisData = new HashMap<>(); + artemisData.put(ArtemisContainer.INSTALL_DIR_KEY, installDir); + artemisData.put(ArtemisContainer.INSTANCE_DIR_KEY, instanceDir); + + return artemisData; + } + + public static Map createArtemisInstanceFromUrl(TestInfo testInfo, String artemisUrl, String version, + String testConfigDir, String instanceName, String instanceDir) { + String installDir = downloadPrepareArtemisInstallDir(testInfo, artemisUrl, version, testConfigDir); + return createArtemisInstanceFromInstallDir(installDir, instanceName, instanceDir); + } + +} diff --git a/standalone-suite/src/main/java/io/brokerqe/claire/container/AbstractGenericContainer.java b/standalone-suite/src/main/java/io/brokerqe/claire/container/AbstractGenericContainer.java index 7c415927..324a1fc4 100644 --- a/standalone-suite/src/main/java/io/brokerqe/claire/container/AbstractGenericContainer.java +++ b/standalone-suite/src/main/java/io/brokerqe/claire/container/AbstractGenericContainer.java @@ -12,6 +12,8 @@ import com.github.dockerjava.api.command.UnpauseContainerCmd; import com.github.dockerjava.api.exception.NotFoundException; import com.github.dockerjava.api.model.Bind; +import com.github.dockerjava.api.model.ContainerNetwork; +import com.github.dockerjava.api.model.Volume; import io.brokerqe.claire.ArtemisConstants; import io.brokerqe.claire.Constants; import io.brokerqe.claire.EnvironmentStandalone; @@ -36,6 +38,7 @@ import java.nio.file.Paths; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -67,6 +70,12 @@ public GenericContainer getGenericContainer() { return container; } + public String getContainerIpAddress() { + Map map = getGenericContainer().getContainerInfo().getNetworkSettings().getNetworks(); + Object mapId = map.keySet().toArray()[0]; + return map.get(mapId).getIpAddress(); + } + public void withCustomNetwork(Network network) { LOGGER.debug("[Container: {}] - With custom network: {}", name, network.getId()); container.withNetwork(network); @@ -92,6 +101,7 @@ public void start() { cmd.withUser(userId); } cmd.withHostName(name); + cmd.withName(name); }); LOGGER.trace("[Container {}] - With network alias: {}", name, name); container.withNetworkAliases(name); @@ -206,8 +216,22 @@ private void withStdOutLog() { } public void withFileSystemBind(String source, String destination, BindMode mode) { + withFileSystemBind(source, destination, mode, false); + } + + public void withFileSystemBind(String source, String destination, BindMode mode, boolean replaceBind) { LOGGER.trace("[Container {}] - Binding filesystem from {} to {} with mode {}", name, source, destination, mode); List currentBinds = container.getBinds(); + + if (replaceBind) { + List tmpBinds = new ArrayList<>(List.copyOf(currentBinds)); + LOGGER.debug("[Container {}] - Replacing bind filesystem from {} to {} with mode {}", name, source, destination, mode); + tmpBinds.removeIf(bind -> bind.getVolume().toString().equals(ArtemisContainer.ARTEMIS_INSTALL_DIR)); + tmpBinds.add(new Bind(source, new Volume(destination))); + container.setBinds(tmpBinds); + return; + } + boolean alreadyContainsBind = currentBinds.stream().anyMatch(p -> p.getVolume().getPath().equals(destination)); if (!alreadyContainsBind) { container.withFileSystemBind(source, destination, mode); diff --git a/standalone-suite/src/main/java/io/brokerqe/claire/container/ArtemisContainer.java b/standalone-suite/src/main/java/io/brokerqe/claire/container/ArtemisContainer.java index b454f183..3446fa25 100644 --- a/standalone-suite/src/main/java/io/brokerqe/claire/container/ArtemisContainer.java +++ b/standalone-suite/src/main/java/io/brokerqe/claire/container/ArtemisContainer.java @@ -9,6 +9,9 @@ import io.brokerqe.claire.ArtemisConstants; import io.brokerqe.claire.Constants; import io.brokerqe.claire.TestUtils; +import io.brokerqe.claire.client.deployment.BundledClientDeployment; +import io.brokerqe.claire.clients.DeployableClient; +import io.brokerqe.claire.clients.Protocol; import io.brokerqe.claire.exception.ClaireRuntimeException; import io.brokerqe.claire.helper.TimeHelper; import org.slf4j.Logger; @@ -33,29 +36,101 @@ public final class ArtemisContainer extends AbstractGenericContainer { public static final String BACKUP_ANNOUNCED_LOG_REGEX = ".*AMQ221031: backup announced\\n"; public static final List DEFAULT_PORTS = List.of(ArtemisConstants.DEFAULT_ALL_PROTOCOLS_PORT, ArtemisConstants.DEFAULT_AMQP_PORT, ArtemisConstants.DEFAULT_MQTT_PORT, ArtemisConstants.DEFAULT_STOMP_PORT, ArtemisConstants.DEFAULT_HORNETQ_PORT, ArtemisConstants.DEFAULT_WEB_CONSOLE_PORT, ArtemisConstants.DEFAULT_JMX_PORT); - public static final String ARTEMIS_INSTALL_DIR = ArtemisConstants.OPT_DIR + Constants.FILE_SEPARATOR + - ArtemisConstants.ARTEMIS_STRING; - public static final String ARTEMIS_INSTANCE_DIR = ArtemisConstants.VAR_DIR + ArtemisConstants.LIB_DIR + - Constants.FILE_SEPARATOR + ArtemisConstants.INSTANCE_STRING; + public static final String ARTEMIS_INSTALL_DIR = ArtemisConstants.OPT_DIR + Constants.FILE_SEPARATOR + ArtemisConstants.ARTEMIS_STRING; + public static final String ARTEMIS_INSTANCE_DIR = ArtemisConstants.VAR_DIR + ArtemisConstants.LIB_DIR + Constants.FILE_SEPARATOR + ArtemisConstants.INSTANCE_STRING; + public static final String ARTEMIS_INSTANCE_ETC_DIR = ARTEMIS_INSTANCE_DIR + ArtemisConstants.ETC_DIR; public static final String ARTEMIS_INSTANCE_DATA_DIR = ARTEMIS_INSTANCE_DIR + ArtemisConstants.DATA_DIR; private static final String ARTEMIS_INSTANCE_CONTROLLER_CMD = "/usr/local/bin/artemis-controller.sh"; + + public static final String INSTANCE_DIR_KEY = "instanceDir"; + public static final String INSTALL_DIR_KEY = "installDir"; private boolean secured = false; + private String installDir; + private String instanceDir; + private String configBinDir; + private String configDir; + private String libDir; + private DeployableClient deployableClient; public ArtemisContainer(String name) { super(name, ENVIRONMENT_STANDALONE.getArtemisContainerImage()); type = ContainerType.ARTEMIS; + deployableClient = new BundledClientDeployment(); + deployableClient.setContainer(this.getGenericContainer()); + } + + public String getDefaultBrokerUri() { + return getBrokerUri(Protocol.CORE, 61616); + } + + public String getBrokerUri(Protocol protocol) { + switch (protocol) { + case AMQP -> { + return getBrokerUri(Protocol.AMQP, 5672); + } + case AMQPS -> { + return getBrokerUri(Protocol.AMQP, 5673); + } + case CORE -> { + return getBrokerUri(Protocol.CORE, 61616); + } + case CORES -> { + return getBrokerUri(Protocol.CORE, 61617); + } + default -> { + return getBrokerUri(Protocol.CORE, 61616); + } + } + } + + public String getBrokerUri(Protocol protocol, int port) { + String brokerUri; + switch (protocol) { + case AMQP -> brokerUri = Constants.AMQP_URL_PREFIX.toLowerCase(Locale.ROOT) + "%s"; + case CORE -> brokerUri = Constants.TCP_URL_PREFIX.toLowerCase(Locale.ROOT) + "%s"; + default -> throw new IllegalArgumentException("Unknown port!"); + } + + brokerUri = String.format(brokerUri, getName()); + // TODO use port as well? +// brokerUri = String.format(brokerUri, getInstanceNameAndPort(port)); + return brokerUri; + } + + public String getInstallDir() { + return installDir != null ? installDir : TestUtils.getProjectRelativeFile(ArtemisConstants.INSTALL_DIR); } - public String getArtemisInstallDir() { - return TestUtils.getProjectRelativeFile(ArtemisConstants.INSTALL_DIR); + public void setInstallDir(String installDir) { + this.installDir = installDir; + setConfigLibDir(instanceDir + Constants.FILE_SEPARATOR + ArtemisConstants.LIB_DIR); } - public String getArtemisDefaultCfgBinDir() { - return TestUtils.getProjectRelativeFile(Constants.ARTEMIS_DEFAULT_CFG_BIN_DIR); + public void setInstanceDir(String instanceDir) { + this.instanceDir = instanceDir; } - public String getArtemisDefaultCfgLibDir() { - return TestUtils.getProjectRelativeFile(Constants.ARTEMIS_DEFAULT_CFG_LIB_DIR); + public String getInstanceDir() { + return instanceDir; + } + + public void setConfigDir(String configDir) { + this.configDir = configDir; + } + + public String getConfigBinDir() { + return configBinDir != null ? configBinDir : TestUtils.getProjectRelativeFile(Constants.ARTEMIS_DEFAULT_CFG_BIN_DIR); + } + public void setConfigBinDir(String configBinDir) { + this.configBinDir = configBinDir; + } + + public String getConfigLibDir() { + return libDir != null ? libDir : TestUtils.getProjectRelativeFile(Constants.ARTEMIS_DEFAULT_CFG_LIB_DIR); + } + + public void setConfigLibDir(String libDir) { + this.libDir = libDir; } public String getArtemisJavaHomeDir() { @@ -63,23 +138,26 @@ public String getArtemisJavaHomeDir() { } public void withInstallDir(String dirPath) { + withInstallDir(dirPath, false); + } + + public void withInstallDir(String dirPath, boolean replaceBind) { LOGGER.debug("[Container {}] - with install dir {} = {}", name, dirPath, ARTEMIS_INSTALL_DIR); - TestUtils.createDirectory(dirPath); - withFileSystemBind(dirPath, ARTEMIS_INSTALL_DIR, BindMode.READ_ONLY); + withFileSystemBind(dirPath, ARTEMIS_INSTALL_DIR, BindMode.READ_ONLY, replaceBind); } public void withConfigDir(String dirPath) { - String configDir = ARTEMIS_INSTANCE_DIR + ArtemisConstants.ETC_DIR; - LOGGER.debug("[Container {}] with config dir {} = {}", name, dirPath, configDir); - TestUtils.createDirectory(dirPath); - withFileSystemBind(dirPath, configDir, BindMode.READ_ONLY); + String containerConfigDir = ARTEMIS_INSTANCE_DIR + ArtemisConstants.ETC_DIR; + LOGGER.debug("[Container {}] with config dir {} = {}", name, dirPath, containerConfigDir); + setConfigDir(dirPath); + withFileSystemBind(dirPath, containerConfigDir, BindMode.READ_ONLY); } public void withInstanceDir(String dirPath) { - String instanceDir = ARTEMIS_INSTANCE_DIR; - LOGGER.debug("[Container {}] with instance dir {} = {}", name, dirPath, instanceDir); - TestUtils.createDirectory(dirPath); - withFileSystemBind(dirPath, instanceDir, BindMode.READ_WRITE); + String containerInstanceDir = ARTEMIS_INSTANCE_DIR; + setInstanceDir(dirPath); + LOGGER.debug("[Container {}] with instance dir {} = {}", name, dirPath, containerInstanceDir); + withFileSystemBind(dirPath, containerInstanceDir, BindMode.READ_WRITE); } public void withConfigFile(String srcFilePath, String dstFileName) { @@ -111,13 +189,14 @@ public void start() { public void start(Duration startupTimeout) { LOGGER.info("[Container {}] - About to start", name); LOGGER.debug("[Container {}] - Using exposed ports: {}", name, DEFAULT_PORTS); + container.addExposedPorts(Ints.toArray(DEFAULT_PORTS)); container.withPrivilegedMode(true); container.withStartupTimeout(startupTimeout); - withInstallDir(getArtemisInstallDir()); withJavaHome(getArtemisJavaHomeDir()); - withFileSystemBind(getArtemisDefaultCfgBinDir(), ARTEMIS_INSTANCE_DIR + ArtemisConstants.BIN_DIR, BindMode.READ_WRITE); - withFileSystemBind(getArtemisDefaultCfgLibDir(), ARTEMIS_INSTANCE_DIR + ArtemisConstants.LIB_DIR, BindMode.READ_WRITE); + withInstallDir(getInstallDir()); + withFileSystemBind(getConfigBinDir(), ARTEMIS_INSTANCE_DIR + ArtemisConstants.BIN_DIR, BindMode.READ_WRITE); + withFileSystemBind(getConfigLibDir(), ARTEMIS_INSTANCE_DIR + ArtemisConstants.LIB_DIR, BindMode.READ_WRITE); long uid = new UnixSystem().getUid(); long gid = new UnixSystem().getGid(); withEnvVar(Map.of("ARTEMIS_GROUP_GID", String.valueOf(gid), "ARTEMIS_USER_UID", String.valueOf(uid))); @@ -221,4 +300,8 @@ public void setSecured(boolean secured) { this.secured = secured; } + public DeployableClient getDeployableClient() { + return deployableClient; + } + } diff --git a/standalone-suite/src/test/java/io/brokerqe/claire/AbstractSystemTests.java b/standalone-suite/src/test/java/io/brokerqe/claire/AbstractSystemTests.java index ae2bc68d..b9f807ff 100644 --- a/standalone-suite/src/test/java/io/brokerqe/claire/AbstractSystemTests.java +++ b/standalone-suite/src/test/java/io/brokerqe/claire/AbstractSystemTests.java @@ -5,8 +5,13 @@ package io.brokerqe.claire; import io.brokerqe.claire.clients.DeployableClient; +import io.brokerqe.claire.clients.MessagingClient; +import io.brokerqe.claire.clients.Protocol; import io.brokerqe.claire.clients.bundled.ArtemisCommand; +import io.brokerqe.claire.clients.bundled.BundledAmqpMessagingClient; import io.brokerqe.claire.clients.bundled.BundledArtemisClient; +import io.brokerqe.claire.clients.bundled.BundledClientOptions; +import io.brokerqe.claire.clients.bundled.BundledCoreMessagingClient; import io.brokerqe.claire.container.ArtemisContainer; import io.brokerqe.claire.container.NfsServerContainer; import io.brokerqe.claire.container.YacfgArtemisContainer; @@ -22,7 +27,9 @@ import org.apache.activemq.artemis.api.core.RoutingType; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.TestInfo; @@ -43,6 +50,7 @@ import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(StandaloneTestDataCollector.class) @@ -110,32 +118,38 @@ public ArtemisContainer setupArtemisWithDB() { } protected ArtemisContainer getArtemisInstance(String instanceName) { - return getArtemisInstance(instanceName, null, new ArrayList<>(), new HashMap<>(), false, true); + return getArtemisInstance(instanceName, null, new ArrayList<>(), new HashMap<>(), null, false, true); } protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile) { - return getArtemisInstance(instanceName, tuneFile, new ArrayList<>(), new HashMap<>(), false, true); + return getArtemisInstance(instanceName, tuneFile, new ArrayList<>(), new HashMap<>(), null, false, true); + } + + protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, List yacfgOpts) { + return getArtemisInstance(instanceName, tuneFile, yacfgOpts, new HashMap<>(), null, false, true); + } + + protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, List yacfgOpts, Map artemisData) { + return getArtemisInstance(instanceName, tuneFile, yacfgOpts, new HashMap<>(), artemisData, false, true); } protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, boolean isBackupInstance) { - return getArtemisInstance(instanceName, tuneFile, new ArrayList<>(), new HashMap<>(), isBackupInstance, true); + return getArtemisInstance(instanceName, tuneFile, new ArrayList<>(), new HashMap<>(), null, isBackupInstance, true); } - protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, - List yacfgOpts, - Map envVars) { - return getArtemisInstance(instanceName, tuneFile, yacfgOpts, envVars, false, true); + protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, List yacfgOpts, Map envVars, Map artemisData) { + return getArtemisInstance(instanceName, tuneFile, yacfgOpts, envVars, null, false, true); } protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, List yacfgOpts, Map envVars, - boolean isBackupInstance) { - return getArtemisInstance(instanceName, tuneFile, yacfgOpts, envVars, isBackupInstance, true); + Map artemisData, boolean isBackupInstance) { + return getArtemisInstance(instanceName, tuneFile, yacfgOpts, envVars, artemisData, isBackupInstance, true); } protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFile, List yacfgOpts, Map envVars, - boolean isBackupInstance, boolean startInstance) { + Map artemisData, boolean isBackupInstance, boolean startInstance) { List mutableYacfgOpts = new ArrayList<>(yacfgOpts); if (useArtemisWithDB()) { return setupArtemisWithDB(); @@ -146,7 +160,7 @@ protected ArtemisContainer getArtemisInstance(String instanceName, String tuneFi mutableYacfgOpts.add("--tune"); mutableYacfgOpts.add(tuneFile); } - generateArtemisCfg(artemis, mutableYacfgOpts); + generateArtemisCfg(artemis, artemisData, mutableYacfgOpts); if (isBackupInstance) { artemis.withLogWait(ArtemisContainer.BACKUP_ANNOUNCED_LOG_REGEX); } @@ -187,6 +201,10 @@ protected String getTestConfigDir() { return TestUtils.getProjectRelativeFile(Constants.ARTEMIS_TEST_CFG_DIR + Constants.FILE_SEPARATOR + cfgDir); } + protected String getTestTempDir() { + return getEnvironment().getTmpDirLocation() + Constants.FILE_SEPARATOR + getPkgClassAsDir(); + } + protected void generateArtemisCfgInParallel(Map> configMap) { configMap.entrySet().stream().parallel().forEach(e -> { generateArtemisCfg(e.getKey(), e.getValue()); @@ -194,21 +212,35 @@ protected void generateArtemisCfgInParallel(Map> } protected void generateArtemisCfg(ArtemisContainer artemisInstance) { - generateArtemisCfg(artemisInstance, new ArrayList<>(), null); + generateArtemisCfg(artemisInstance, new ArrayList<>()); } protected void generateArtemisCfg(ArtemisContainer artemisInstance, List yacfgParams) { - generateArtemisCfg(artemisInstance, yacfgParams, null); + generateArtemisCfg(artemisInstance, null, yacfgParams); } - - protected void generateArtemisCfg(ArtemisContainer artemisInstance, List yacfgParams, String profileFileName) { + protected void generateArtemisCfg(ArtemisContainer artemisInstance, Map artemisData, List yacfgParams) { String instanceDir = getTestConfigDir() + Constants.FILE_SEPARATOR + artemisInstance.getName(); - TestUtils.createDirectory(instanceDir + ArtemisConstants.BIN_DIR); - TestUtils.createDirectory(instanceDir + ArtemisConstants.DATA_DIR); - TestUtils.createDirectory(instanceDir + ArtemisConstants.ETC_DIR); - TestUtils.createDirectory(instanceDir + ArtemisConstants.LIB_DIR); - TestUtils.createDirectory(instanceDir + ArtemisConstants.LOG_DIR); - TestUtils.createDirectory(instanceDir + ArtemisConstants.TMP_DIR); + String providedInstanceDir = null; + String providedInstallDir = null; + if (artemisData != null) { + providedInstanceDir = artemisData.get("instanceDir"); + providedInstallDir = artemisData.get("installDir"); + artemisInstance.setInstallDir(providedInstallDir); + } + + if (providedInstanceDir == null) { + LOGGER.debug("[Config] Using default installDir {}", instanceDir); + TestUtils.createDirectory(instanceDir + ArtemisConstants.BIN_DIR); + TestUtils.createDirectory(instanceDir + ArtemisConstants.DATA_DIR); + TestUtils.createDirectory(instanceDir + ArtemisConstants.ETC_DIR); + TestUtils.createDirectory(instanceDir + ArtemisConstants.LIB_DIR); + TestUtils.createDirectory(instanceDir + ArtemisConstants.LOG_DIR); + TestUtils.createDirectory(instanceDir + ArtemisConstants.TMP_DIR); + } else { + LOGGER.debug("[Config] Using provided instanceDir {}", providedInstanceDir); + TestUtils.copyDirectories(providedInstanceDir, instanceDir); + artemisInstance.setConfigBinDir(instanceDir + ArtemisConstants.BIN_DIR); + } artemisInstance.withInstanceDir(instanceDir); String artemisConfig = EnvironmentStandalone.getInstance().getProvidedArtemisConfig(); @@ -220,16 +252,14 @@ protected void generateArtemisCfg(ArtemisContainer artemisInstance, List final YacfgArtemisContainer yacfg; yacfg = ResourceManager.getYacfgArtemisContainerInstance(String.format("yacfg-%s", artemisInstance.getName())); - String instanceYacfgOutputDir = instanceDir + Constants.FILE_SEPARATOR + ArtemisConstants.ETC_DIR; + String instanceYacfgOutputDir = instanceDir + ArtemisConstants.ETC_DIR; yacfg.withHostOutputDir(instanceYacfgOutputDir); - if (profileFileName != null && !profileFileName.isBlank() && !profileFileName.isEmpty()) { - yacfg.withProfile(profileFileName); - } - - if (yacfgParams.stream().noneMatch(e -> e.contains("broker_home"))) { + Predicate homePredicate = e -> e.contains("broker_home="); + yacfgParams.stream().filter(homePredicate).forEach(e -> { yacfg.withParam(YacfgArtemisContainer.OPT_PARAM_KEY, String.format("broker_home=%s", ArtemisContainer.ARTEMIS_INSTALL_DIR)); - } + }); + yacfgParams.removeIf(homePredicate); if (yacfgParams.stream().noneMatch(e -> e.contains("broker_name="))) { yacfg.withParam(YacfgArtemisContainer.OPT_PARAM_KEY, String.format("broker_name=%s", artemisInstance.getName())); @@ -239,6 +269,13 @@ protected void generateArtemisCfg(ArtemisContainer artemisInstance, List yacfg.withParam(YacfgArtemisContainer.OPT_PARAM_KEY, String.format("broker_instance=%s", ArtemisContainer.ARTEMIS_INSTANCE_DIR)); } + Predicate profilePredicate = e -> e.contains("profile="); + yacfgParams.stream().filter(profilePredicate).forEach(e -> { + String profile = StringUtils.substringAfter(e, "="); + yacfg.withProfile(profile); + }); + yacfgParams.removeIf(profilePredicate); + Predicate tunePredicate = e -> e.contains("tune_file="); yacfgParams.stream().filter(tunePredicate).forEach(e -> { Path file = Paths.get(StringUtils.substringAfter(e, "=")); @@ -343,6 +380,7 @@ protected NfsServerContainer getNfsServerInstance(String exportDirName) { return nfsServer; } + // ==== Messaging methods protected void deleteAddress(DeployableClient artemisDeployableClient, String name) { BundledArtemisClient artemisClient = new BundledArtemisClient(artemisDeployableClient, ArtemisCommand.ADDRESS_DELETE, Map.of("name", name)); artemisClient.executeCommand(); @@ -352,4 +390,101 @@ protected void deleteQueue(DeployableClient artemisDeployableClient, String name BundledArtemisClient artemisClient = new BundledArtemisClient(artemisDeployableClient, ArtemisCommand.QUEUE_DELETE, Map.of("name", name)); artemisClient.executeCommand(); } + + public void createAddress(DeployableClient artemisDeployableClient, String name) { + BundledArtemisClient artemisClient = new BundledArtemisClient(artemisDeployableClient, ArtemisCommand.ADDRESS_CREATE, Map.of("name", name)); + artemisClient.executeCommand(); + } + + public void createQueue(ArtemisContainer artemis, Map artemisCreateQueueOptions) { + createQueue(artemis.getDeployableClient(), artemisCreateQueueOptions, ArtemisConstants.ADMIN_NAME, ArtemisConstants.ADMIN_PASS); + } + + public void createQueue(DeployableClient artemisDeployableClient, Map artemisCreateQueueOptions, String username, String password) { + BundledArtemisClient artemisClient = new BundledArtemisClient(artemisDeployableClient, ArtemisCommand.QUEUE_CREATE, username, password, artemisCreateQueueOptions); + artemisClient.executeCommand(); + } + + public MessagingClient createMessagingClient(BundledClientOptions options) { + MessagingClient messagingClient; + + if (options.getProtocol().toString().startsWith(Protocol.AMQP.name())) { + options.getDeployableClient().getContainer(); + messagingClient = new BundledAmqpMessagingClient(options); + } else { + messagingClient = new BundledCoreMessagingClient(options); + } + return messagingClient; + } + + public int sendMessages(BundledClientOptions options) { + return sendMessages(null, options); + } + + public int sendMessages(MessagingClient messagingClient, BundledClientOptions options) { + if (messagingClient == null) { + messagingClient = createMessagingClient(options); + } + LOGGER.info("[{}] Sending {} messages to {}.", options.getDeployableClient().getContainerName(), options.getMessageCount(), options.getDestinationQueue()); + return messagingClient.sendMessages(); + } + + public int receiveMessages(BundledClientOptions options) { + return receiveMessages(null, options); + } + + public int receiveMessages(MessagingClient messagingClient, BundledClientOptions options) { + if (messagingClient == null) { + messagingClient = createMessagingClient(options); + } + LOGGER.info("[{}] Sending {} messages to {}.", options.getDeployableClient().getContainerName(), options.getMessageCount(), options.getDestinationQueue()); + return messagingClient.receiveMessages(); + } + + public void sendReceiveDurableMsgQueue(ArtemisContainer artemis, BundledClientOptions senderOptions, BundledClientOptions receiverOptions) { + Map artemisCreateQueueOptions = new HashMap<>(Map.of( + "name", senderOptions.getDestinationQueue(), + "address", senderOptions.getDestinationAddress(), + ArtemisConstants.ROUTING_TYPE_ANYCAST, "", + "durable", "", + "auto-create-address", "", + "preserve-on-no-consumers", "" + )); + Map artemisDeleteQueueOptions = new HashMap<>(Map.of( + "name", senderOptions.getDestinationAddress() + )); + + BundledArtemisClient artemisClient = new BundledArtemisClient(artemis.getDeployableClient(), ArtemisCommand.QUEUE_CREATE, ArtemisConstants.ADMIN_NAME, ArtemisConstants.ADMIN_PASS, artemisCreateQueueOptions); + artemisClient.executeCommand(); + + MessagingClient sender = createMessagingClient(senderOptions); + int sent = sendMessages(sender, senderOptions); + + MessagingClient receiver = createMessagingClient(receiverOptions); + int received = receiveMessages(receiver, senderOptions); + MatcherAssert.assertThat(received, equalTo(sent)); + + artemisClient = new BundledArtemisClient(artemis.getDeployableClient(), ArtemisCommand.QUEUE_DELETE, artemisDeleteQueueOptions); + artemisClient.executeCommand(); + } + + public Duration calculateArtemisStartupTimeout(int size, String unit, int messageCount) { + int seconds = messageCount; + if (size != 0) { + seconds *= size; + } + if (unit != null) { + switch (unit) { + case "KiB" -> seconds *= 0.5; + case "MiB" -> seconds *= 15; + case "GiB" -> seconds *= 100; + } + } + return Duration.ofSeconds(seconds); + } + + // common assertion methods + public void assertContains(String log, String text) { + Assertions.assertTrue(log.contains(text)); + } } diff --git a/standalone-suite/src/test/java/io/brokerqe/claire/ha/sharedstore/FailoverSharedStoreTests.java b/standalone-suite/src/test/java/io/brokerqe/claire/ha/sharedstore/FailoverSharedStoreTests.java index ef0b63c5..5d61e6a7 100644 --- a/standalone-suite/src/test/java/io/brokerqe/claire/ha/sharedstore/FailoverSharedStoreTests.java +++ b/standalone-suite/src/test/java/io/brokerqe/claire/ha/sharedstore/FailoverSharedStoreTests.java @@ -74,7 +74,7 @@ void setupEnv() { String artemisBackupName = "artemisBackup"; LOGGER.info("Creating artemis instance: " + artemisBackupName); String backupTuneFile = generateYacfgProfilesContainerTestDir("backup-tune.yaml.jinja2"); - artemisBackup = getArtemisInstance(artemisBackupName, backupTuneFile, yacfgOpts, artemisBackupEnvVars, true); + artemisBackup = getArtemisInstance(artemisBackupName, backupTuneFile, yacfgOpts, artemisBackupEnvVars, null, true); LOGGER.info("Setting client configurations"); DeployableClient stDeployableClient = new StJavaClientDeployment(); diff --git a/standalone-suite/src/test/java/io/brokerqe/claire/messaging/MessagingTests.java b/standalone-suite/src/test/java/io/brokerqe/claire/messaging/MessagingTests.java index c235ed88..82d8fb47 100644 --- a/standalone-suite/src/test/java/io/brokerqe/claire/messaging/MessagingTests.java +++ b/standalone-suite/src/test/java/io/brokerqe/claire/messaging/MessagingTests.java @@ -206,7 +206,7 @@ private void doSendReceiveDurableMsgQueue(String address, int messageCount, Stri "conn-heartbeat", "180" )); - Duration timeout = calculateStartupTimeout(size, unit, messageCount); + Duration timeout = calculateArtemisStartupTimeout(size, unit, messageCount); if (messageContent != null) { senderOptions.put("msg-content", messageContent); receiverOptions.put("timeout", String.valueOf(timeout.toSeconds())); @@ -243,21 +243,6 @@ private void doSendReceiveDurableMsgQueue(String address, int messageCount, Stri artemisClient.executeCommand(); } - private Duration calculateStartupTimeout(int size, String unit, int messageCount) { - int seconds = messageCount; - if (size != 0) { - seconds *= size; - } - if (unit != null) { - switch (unit) { - case "KiB" -> seconds *= 0.5; - case "MiB" -> seconds *= 15; - case "GiB" -> seconds *= 100; - } - } - return Duration.ofSeconds(seconds); - } - private int getMessageCount(int defaultCount) { Database db = Environment.get().getDatabase(); if (db instanceof ProvidedDatabase) { diff --git a/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/HAReplicationUpgradeTests.java b/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/HAReplicationUpgradeTests.java new file mode 100644 index 00000000..027c6a00 --- /dev/null +++ b/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/HAReplicationUpgradeTests.java @@ -0,0 +1,122 @@ +/* + * Copyright Broker QE authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.brokerqe.claire.upgrade; + +import io.brokerqe.claire.AbstractSystemTests; +import io.brokerqe.claire.ArtemisConstants; +import io.brokerqe.claire.ResourceManager; +import io.brokerqe.claire.client.AmqpUtil; +import io.brokerqe.claire.client.JmsClient; +import io.brokerqe.claire.container.ArtemisContainer; +import jakarta.jms.Message; +import jakarta.jms.Queue; +import org.apache.activemq.artemis.api.core.RoutingType; +import org.apache.qpid.jms.JmsConnectionFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +@Disabled +public class HAReplicationUpgradeTests extends AbstractSystemTests { + private static final Logger LOGGER = LoggerFactory.getLogger(HAReplicationUpgradeTests.class); + private ArtemisContainer artemisPrimary0; + private ArtemisContainer artemisPrimary1; + private ArtemisContainer artemisPrimary2; + private ArtemisContainer artemisBackup0; + private ArtemisContainer artemisBackup1; + private ArtemisContainer artemisBackup2; + + + Stream getUpgradePlanArguments() { + ArrayList> mapped = new Yaml().load(getEnvironment().getTestUpgradePlanContent()); + return mapped.stream().map(line -> + Arguments.of(line.get("version"), line.get("channel"), line.get("indexImageBundle")) + ); + } + + @BeforeAll + void setupEnvironment() { + LOGGER.info("[UpgradeTestPlan] {}", getEnvironment().getTestUpgradePlanContent()); +// for (int i : new int[]{0, 1, 2}) { + String artemisPrimaryName = "artemisPrimary"; + LOGGER.info("Creating artemis instance: " + artemisPrimaryName); + String primaryTuneFile = generateYacfgProfilesContainerTestDir("primary-tune.yaml.jinja2"); + artemisPrimary0 = getArtemisInstance(artemisPrimaryName + 0, primaryTuneFile); + artemisPrimary1 = getArtemisInstance(artemisPrimaryName + 1, primaryTuneFile); +// artemisPrimary2 = getArtemisInstance(artemisPrimaryName + 2, primaryTuneFile); + + String artemisBackupName = "artemisBackup"; + LOGGER.info("Creating artemis instance: " + artemisBackupName); + String backupTuneFile = generateYacfgProfilesContainerTestDir("backup-tune.yaml.jinja2"); + artemisBackup0 = getArtemisInstance(artemisBackupName + 0, backupTuneFile, true); + artemisBackup1 = getArtemisInstance(artemisBackupName + 1, backupTuneFile, true); +// artemisBackup2 = getArtemisInstance(artemisBackupName + 2, backupTuneFile, true); +// } + } + + @ParameterizedTest + @MethodSource("getUpgradePlanArguments") + void microUpgradeHA(ArgumentsAccessor argumentsAccessor) { + String version = argumentsAccessor.getString(0); + String channel = argumentsAccessor.getString(1); + String iib = argumentsAccessor.getString(2); + + int numOfMessages = 100; + String addressName = "TestQueue1"; + String queueName = "TestQueue1"; + + // create a qpid jms client + String primaryAmqpHostAndPort = artemisPrimary0.getHostAndPort(ArtemisConstants.DEFAULT_ALL_PROTOCOLS_PORT); + String backupAmqpHostAndPort = artemisBackup0.getHostAndPort(ArtemisConstants.DEFAULT_ALL_PROTOCOLS_PORT); + String amqpOpts = "failover.amqpOpenServerListAction=IGNORE"; + String url = AmqpUtil.buildAmqFailoverUrl(amqpOpts, primaryAmqpHostAndPort, backupAmqpHostAndPort); + + LOGGER.info("Creating client"); + JmsClient client = ResourceManager.getJmsClient("client-1", new JmsConnectionFactory(url)) + .withCredentials(ArtemisConstants.ADMIN_NAME, ArtemisConstants.ADMIN_PASS) + .withDestination(Queue.class, queueName); + + LOGGER.info("Producing {} messages to queue {}", numOfMessages, queueName); + client.produce(numOfMessages); + Map producedMsgs = client.getProducedMsgs(); + + LOGGER.info("Ensure queue contains {} messages on primary", numOfMessages); + ensureQueueCount(artemisPrimary0, addressName, queueName, RoutingType.ANYCAST, numOfMessages); + + // ensure replica is in sync + ensureBrokerReplicaIsInSync(artemisBackup0); + + // stop the primary instance + artemisPrimary0.stop(); + + // ensure the backup instance became the current live + ensureBrokerIsLive(artemisBackup0); + + LOGGER.info("Ensure queue contains {} messages on backup", numOfMessages); + ensureQueueCount(artemisBackup0, addressName, queueName, RoutingType.ANYCAST, numOfMessages); + + LOGGER.info("Consuming {} messages from queue {} on backup", numOfMessages, queueName); + client.consume(numOfMessages); + Map consumedMsgs = client.getConsumedMsgs(); + + LOGGER.info("Ensure queue is empty"); + ensureQueueCount(artemisBackup0, addressName, queueName, RoutingType.ANYCAST, 0); + + LOGGER.info("Ensuring produced and consumed messages are the same"); + ensureSameMessages(numOfMessages, producedMsgs, consumedMsgs); + } + +} diff --git a/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/SingleUpgradeTests.java b/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/SingleUpgradeTests.java new file mode 100644 index 00000000..cd24c365 --- /dev/null +++ b/standalone-suite/src/test/java/io/brokerqe/claire/upgrade/SingleUpgradeTests.java @@ -0,0 +1,169 @@ +/* + * Copyright Broker QE authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.brokerqe.claire.upgrade; + +import io.brokerqe.claire.AbstractSystemTests; +import io.brokerqe.claire.ArtemisConstants; +import io.brokerqe.claire.Constants; +import io.brokerqe.claire.TestUtils; +import io.brokerqe.claire.client.deployment.ArtemisDeployment; +import io.brokerqe.claire.clients.Protocol; +import io.brokerqe.claire.clients.bundled.BundledClientOptions; +import io.brokerqe.claire.container.ArtemisContainer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +public class SingleUpgradeTests extends AbstractSystemTests { + + private static final Logger LOGGER = LoggerFactory.getLogger(SingleUpgradeTests.class); + private static int messagesReceivedTotal = 0; + private static int messagesSentInitials; + private static int messagesReceivePartial; + private static int upgradeCount; + + private ArtemisContainer artemisUpgraded; + + Stream getUpgradePlanArguments() { + ArrayList> mapped = new Yaml().load(getEnvironment().getTestUpgradePlanContent()); + messagesSentInitials = 2000 * (mapped.size() - 1); + messagesReceivePartial = messagesSentInitials / (mapped.size() - 1); + upgradeCount = mapped.size(); + return mapped.stream().map(line -> + Arguments.of(line.get("version"), line.get("artemis_version"), line.get("artemis_zip_url")) + ); + } + + @BeforeAll + void setupEnvironment() { + LOGGER.info("[UpgradeTestPlan] {}", getEnvironment().getTestUpgradePlanContent()); + } + + ArtemisContainer createArtemis(String name, String artemisVersion, Map artemisData) { + String yacfgArtemisProfile = "claire-default-profile-" + artemisVersion + ".yaml.jinja2"; + LOGGER.info("[UPGRADE] Creating artemis instance: {} with profile {}", name, yacfgArtemisProfile); + return getArtemisInstance(name, null, new ArrayList<>(List.of("profile=" + yacfgArtemisProfile)), artemisData); + } + + ArtemisContainer performUpgradeProcedure(ArtemisContainer artemisUpgraded, String upgradeInstallDir) { + // apache-artemis-2.33.0.redhat-00013/bin/artemis upgrade /tmp/upgrade-lala/ + String createCmd = upgradeInstallDir + "/bin/artemis upgrade " + artemisUpgraded.getInstanceDir(); + TestUtils.executeLocalCommand(createCmd); + artemisUpgraded.withInstallDir(upgradeInstallDir, true); + artemisUpgraded.setInstallDir(upgradeInstallDir); + artemisUpgraded.restartWithStop(Duration.ofSeconds(10)); + return artemisUpgraded; + } + + void assertVersionLogs(ArtemisContainer artemis, String version, String artemisVersion) { + // Red Hat AMQ Broker 7.11.7.GA + // AMQ101000: Starting ActiveMQ Artemis Server version 2.28.0.redhat-00022 + String brokerVersionOldString = ArtemisConstants.getArtemisVersionString(version); + String brokerVersionNewString = ArtemisConstants.getArtemisVersionStringOld(version); + + LOGGER.info("[UPGRADE][{}] Checking for correct versions in logs {}, {}", artemis.getName(), version, artemisVersion); + assertThat(artemis.getLogs(), anyOf(containsString(brokerVersionOldString), containsString(brokerVersionNewString))); + assertThat(artemis.getLogs(), containsString(ArtemisConstants.getArtemisStartingServerVersionString(artemisVersion))); + } + + @ParameterizedTest + @MethodSource("getUpgradePlanArguments") + void microUpgrade(ArgumentsAccessor argumentsAccessor) { + String version = argumentsAccessor.getString(0); + String artemisVersion = argumentsAccessor.getString(1); + String artemisZipUrl = argumentsAccessor.getString(2); + + String artemisUpgradedName = "brk-static-upgrade"; + String artemisVersionedName = "brk-version-" + version.replaceAll("\\.", "-"); + String artemisUpgradedInstanceDir = getTestConfigDir() + Constants.FILE_SEPARATOR + artemisUpgradedName; + String upgradeQueueName = "upgrade-queue"; + + String installDir = ArtemisDeployment.downloadPrepareArtemisInstallDir(testInfo, artemisZipUrl, version, getTestConfigDir()); + + Map artemisUpgradedData = ArtemisDeployment.createArtemisInstanceFromInstallDir(installDir, artemisUpgradedName, artemisUpgradedInstanceDir); + + if (argumentsAccessor.getInvocationIndex() > 1) { + LOGGER.info("[UPGRADE] Receive partial durable messages {}", messagesReceivePartial); + artemisUpgraded = performUpgradeProcedure(artemisUpgraded, installDir); + BundledClientOptions durableReceiverOptions = new BundledClientOptions() + .withDeployableClient(artemisUpgraded.getDeployableClient()) + .withDestinationAddress(upgradeQueueName) + .withDestinationQueue(upgradeQueueName) + .withDestinationPort(DEFAULT_ALL_PORT) + .withMessageCount(messagesReceivePartial) + .withUsername(ArtemisConstants.ADMIN_NAME) + .withPassword(ArtemisConstants.ADMIN_PASS) + .withDestinationUrl(artemisUpgraded.getBrokerUri(Protocol.CORE)) + .withProtocol(Protocol.CORE); + messagesReceivedTotal += receiveMessages(durableReceiverOptions); + LOGGER.info("[UPGRADE] Received so far {}", messagesReceivedTotal); + + if (argumentsAccessor.getInvocationIndex() == upgradeCount) { + LOGGER.info("[UPGRADE] Check all received messages vs all sent"); + Assertions.assertEquals(messagesReceivedTotal, messagesSentInitials); + } + + } else { + LOGGER.info("[UPGRADE] Deploying initial broker {}", artemisUpgradedName); + artemisUpgraded = createArtemis(artemisUpgradedName, artemisVersion, artemisUpgradedData); + + LOGGER.info("[UPGRADE] Sending initial messages {}", messagesSentInitials); + BundledClientOptions initialSenderOptions = new BundledClientOptions() + .withDeployableClient(artemisUpgraded.getDeployableClient()) + .withDestinationAddress(upgradeQueueName) + .withDestinationQueue(upgradeQueueName) + .withDestinationPort(DEFAULT_ALL_PORT) + .withMessageCount(messagesSentInitials) + .withUsername(ArtemisConstants.ADMIN_NAME) + .withPassword(ArtemisConstants.ADMIN_PASS) + .withDestinationUrl(artemisUpgraded.getBrokerUri(Protocol.CORE)) + .withProtocol(Protocol.CORE); + int sentInitial = sendMessages(initialSenderOptions); + Assertions.assertEquals(sentInitial, messagesSentInitials); + } + + LOGGER.info("[UPGRADE] Deploying versioned broker {}", artemisUpgradedName); + ArtemisContainer artemisVersioned = createArtemis(artemisVersionedName, artemisVersion, artemisUpgradedData); + + assertVersionLogs(artemisUpgraded, version, artemisVersion); + assertVersionLogs(artemisVersioned, version, artemisVersion); + + LOGGER.info("[UPGRADE] Test send-receive versioned broker {}", artemisVersionedName); + int msgsExpected = 100; + String addressName = "versioned-queue"; + BundledClientOptions senderOptions = new BundledClientOptions() + .withDeployableClient(artemisVersioned.getDeployableClient()) + .withDestinationPort(DEFAULT_ALL_PORT) + .withDestinationAddress(addressName) + .withDestinationQueue(addressName) + .withMessageCount(msgsExpected) + .withUsername(ArtemisConstants.ADMIN_NAME) + .withPassword(ArtemisConstants.ADMIN_PASS) + .withDestinationUrl(artemisVersioned.getName()) + .withProtocol(Protocol.CORE); + sendReceiveDurableMsgQueue(artemisVersioned, senderOptions, senderOptions); + + LOGGER.info("[UPGRADE] Stopping versioned broker {}", artemisVersionedName); + artemisVersioned.stop(); + } + +} diff --git a/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/backup-tune.yaml.jinja2 b/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/backup-tune.yaml.jinja2 new file mode 100644 index 00000000..55477fa0 --- /dev/null +++ b/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/backup-tune.yaml.jinja2 @@ -0,0 +1,28 @@ +--- +user_connectors: + - name: 'cluster-connector' + +user_broadcast_groups: + - name: 'cluster-broadcast-group' + connectors_ref: + - 'cluster-connector' + +user_discovery_groups: + - name: 'cluster-discovery-group' + +user_cluster: + user: 'clusterUser' + password: 'clusterPassword' + +user_cluster_connections: + - name: 'artemis-cluster' + connector_ref: 'cluster-connector' + discovery_group_ref: 'cluster-discovery-group' + +user_ha: + policy: replication + role: backup + properties: + initial_replication_sync_timeout: 9876 + retry_replication_wait: 12345 + allow_failback: true \ No newline at end of file diff --git a/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/primary-tune.yaml.jinja2 b/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/primary-tune.yaml.jinja2 new file mode 100644 index 00000000..c99b1a41 --- /dev/null +++ b/standalone-suite/yacfg-profiles/tests/upgrade/HAReplicationUpgradeTests/primary-tune.yaml.jinja2 @@ -0,0 +1,27 @@ +--- +user_connectors: + - name: 'cluster-connector' + +user_broadcast_groups: + - name: 'cluster-broadcast-group' + connectors_ref: + - 'cluster-connector' + +user_discovery_groups: + - name: 'cluster-discovery-group' + +user_cluster: + user: 'clusterUser' + password: 'clusterPassword' + +user_cluster_connections: + - name: 'artemis-cluster' + connector_ref: 'cluster-connector' + discovery_group_ref: 'cluster-discovery-group' + +user_ha: + policy: replication + role: primary + properties: + initial_replication_sync_timeout: 9876 + retry_replication_wait: 12345 \ No newline at end of file