|
1 | 1 | import { GenericContainer, Network, Wait } from 'testcontainers'; |
2 | 2 |
|
3 | | -import { KAFKA_CONNECT_IMAGE, OWL_SHOP_IMAGE, REDPANDA_IMAGE } from './test-images.mjs'; |
| 3 | +import { KAFKA_CONNECT_IMAGE, KAFKA_IMAGE, OWL_SHOP_IMAGE, REDPANDA_IMAGE } from './test-images.mjs'; |
4 | 4 | import { exec } from 'node:child_process'; |
5 | 5 | import { existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'; |
6 | 6 | import { dirname, join, resolve } from 'node:path'; |
@@ -156,6 +156,39 @@ async function verifyRedpandaServices(state, ports) { |
156 | 156 | } |
157 | 157 | } |
158 | 158 |
|
| 159 | +async function startKafkaContainer(network, state, ports, variantName) { |
| 160 | + console.log('Starting Apache Kafka container (KRaft, SASL/PLAIN)...'); |
| 161 | + const jaasConfPath = resolve(__dirname, '..', `test-variant-${variantName}`, 'config', 'kafka_server_jaas.conf'); |
| 162 | + const kafka = await new GenericContainer(KAFKA_IMAGE) |
| 163 | + .withNetwork(network) |
| 164 | + .withNetworkAliases('kafka') |
| 165 | + .withExposedPorts({ container: 9092, host: ports.kafkaKafka }) |
| 166 | + .withBindMounts([{ source: jaasConfPath, target: '/etc/kafka/jaas.conf', mode: 'ro' }]) |
| 167 | + .withEnvironment({ |
| 168 | + KAFKA_NODE_ID: '1', |
| 169 | + KAFKA_PROCESS_ROLES: 'broker,controller', |
| 170 | + KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka:9093', |
| 171 | + KAFKA_LISTENERS: 'SASL_PLAINTEXT://:9092,CONTROLLER://:9093', |
| 172 | + KAFKA_ADVERTISED_LISTENERS: 'SASL_PLAINTEXT://kafka:9092', |
| 173 | + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'SASL_PLAINTEXT:SASL_PLAINTEXT,CONTROLLER:PLAINTEXT', |
| 174 | + KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER', |
| 175 | + KAFKA_INTER_BROKER_LISTENER_NAME: 'SASL_PLAINTEXT', |
| 176 | + KAFKA_SASL_ENABLED_MECHANISMS: 'PLAIN', |
| 177 | + KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: 'PLAIN', |
| 178 | + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: '1', |
| 179 | + KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true', |
| 180 | + CLUSTER_ID: 'MkU3OEVBNTcwNTJENDM2Qk', |
| 181 | + KAFKA_OPTS: '-Djava.security.auth.login.config=/etc/kafka/jaas.conf', |
| 182 | + }) |
| 183 | + .withWaitStrategy(Wait.forLogMessage(/Kafka Server started/i)) |
| 184 | + .withStartupTimeout(120_000) |
| 185 | + .start(); |
| 186 | + |
| 187 | + state.kafkaId = kafka.getId(); |
| 188 | + state.kafkaContainer = kafka; |
| 189 | + console.log(`✓ Apache Kafka container started: ${state.kafkaId}`); |
| 190 | +} |
| 191 | + |
159 | 192 | async function startOwlShop(network, state) { |
160 | 193 | console.log('Starting OwlShop container...'); |
161 | 194 | const owlshopConfigContent = ` |
@@ -942,6 +975,12 @@ async function cleanupOnFailure(state) { |
942 | 975 | console.log(`Failed to stop destination Redpanda container: ${error.message}`); |
943 | 976 | }); |
944 | 977 | } |
| 978 | + if (state.kafkaContainer) { |
| 979 | + console.log('Stopping Kafka container using testcontainers API...'); |
| 980 | + await state.kafkaContainer.stop().catch((error) => { |
| 981 | + console.log(`Failed to stop Kafka container: ${error.message}`); |
| 982 | + }); |
| 983 | + } |
945 | 984 | if (state.redpandaContainer) { |
946 | 985 | console.log('Stopping Redpanda container using testcontainers API...'); |
947 | 986 | await state.redpandaContainer.stop().catch((error) => { |
@@ -1002,6 +1041,24 @@ export default async function globalSetup(config = {}) { |
1002 | 1041 | // Setup Docker infrastructure |
1003 | 1042 | const network = await setupDockerNetwork(state); |
1004 | 1043 |
|
| 1044 | + // --- Kafka variant: simple KRaft broker, no Redpanda/owlshop/connect --- |
| 1045 | + if (variantConfig.isKafka) { |
| 1046 | + await startKafkaContainer(network, state, ports, variantName); |
| 1047 | + const backendConfigPath = resolve(__dirname, '..', `test-variant-${variantName}`, 'config', configFile); |
| 1048 | + await startBackendServerWithConfig( |
| 1049 | + network, |
| 1050 | + isEnterprise, |
| 1051 | + imageTag, |
| 1052 | + state, |
| 1053 | + backendConfigPath, |
| 1054 | + ports.backend, |
| 1055 | + 'console-backend' |
| 1056 | + ); |
| 1057 | + writeFileSync(getStateFile(variantName), JSON.stringify(state, null, 2)); |
| 1058 | + console.log('\n✅ All services ready! Starting tests...\n'); |
| 1059 | + return; |
| 1060 | + } |
| 1061 | + |
1005 | 1062 | // --- Group 1: Start clusters in parallel --- |
1006 | 1063 | const clusterPromises = [ |
1007 | 1064 | startRedpandaContainer(network, state, ports).then(() => verifyRedpandaServices(state, ports)), |
|
0 commit comments