diff --git a/deployment/charts/node/datahaven/dh-bootnode.yaml b/deployment/charts/node/datahaven/dh-bootnode.yaml index ed8a6fbe..3674b53d 100644 --- a/deployment/charts/node/datahaven/dh-bootnode.yaml +++ b/deployment/charts/node/datahaven/dh-bootnode.yaml @@ -4,7 +4,7 @@ fullnameOverride: dh-bootnode image: repository: moonsonglabs/datahaven - tag: pr-78 + tag: main pullPolicy: Always imagePullSecrets: @@ -38,7 +38,7 @@ extraInitContainers: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" securityContext: runAsUser: 0 - command: [ "/bin/bash" ] + command: ["/bin/bash"] args: - -c - | @@ -63,4 +63,4 @@ extraContainers: - name: chain-data subPath: chainspec.json mountPath: /usr/share/nginx/html/chainspec.json - readOnly: true \ No newline at end of file + readOnly: true diff --git a/deployment/charts/node/datahaven/dh-validator.yaml b/deployment/charts/node/datahaven/dh-validator.yaml index 2a5ced32..9c66bfdf 100644 --- a/deployment/charts/node/datahaven/dh-validator.yaml +++ b/deployment/charts/node/datahaven/dh-validator.yaml @@ -4,7 +4,7 @@ fullnameOverride: dh-validator image: repository: moonsonglabs/datahaven - tag: pr-78 + tag: main pullPolicy: Always imagePullSecrets: @@ -23,7 +23,7 @@ node: chainKeystore: storageClass: "gp2" keys: - # This is Alice seed. To generate new seed run: docker run --rm moonsonglabs/datahaven:latest key generate + # This is Alice seed. To generate new seed run: docker run --rm moonsonglabs/datahaven:latest key generate - seed: "bottom drive obey lake curtain smoke basket hold race lonely fit walk" type: gran scheme: ed25519 @@ -42,11 +42,11 @@ node: scheme: ecdsa extraDerivation: '$([ "${HOSTNAME##*-}" = "0" ] && echo "//Alice" || echo "//Bob")' customNodeKey: - # To generate new key run: docker run --rm -t moonsonglabs/datahaven:latest key generate-node-key - # 12D3KooWL5Av1ZZSKkaittmxXBmZpzP7zgiB1AAnWHEw7MxzqnFp - - bdf71a910354e231095366230621eaefb5f99465045f1501478fd3d9b5deef98 - # 12D3KooWAxFonTS177T81CTDeH6mfvJQWYEJeVQ1gPrnULjNY8Cn - - 2a775a9db9fb0ff40afacb4aa7ccbf2a5d04c6d980bb1437c196c8e38a6cd948 + # To generate new key run: docker run --rm -t moonsonglabs/datahaven:latest key generate-node-key + # 12D3KooWL5Av1ZZSKkaittmxXBmZpzP7zgiB1AAnWHEw7MxzqnFp + - bdf71a910354e231095366230621eaefb5f99465045f1501478fd3d9b5deef98 + # 12D3KooWAxFonTS177T81CTDeH6mfvJQWYEJeVQ1gPrnULjNY8Cn + - 2a775a9db9fb0ff40afacb4aa7ccbf2a5d04c6d980bb1437c196c8e38a6cd948 flags: - "--bootnodes /dns/dh-bootnode-0/tcp/30333/p2p/12D3KooWRpzRTivvJ5ySvgbFnPeEE6rDhitQKL1fFJvvBGhnenSk" enableOffchainIndexing: true @@ -61,7 +61,7 @@ extraInitContainers: imagePullPolicy: "{{ .Values.image.pullPolicy }}" securityContext: runAsUser: 0 - command: [ "/bin/bash" ] + command: ["/bin/bash"] args: - -c - | diff --git a/test/cli/handlers/launch/datahaven.ts b/test/cli/handlers/launch/datahaven.ts index 80dd5ebb..07449a60 100644 --- a/test/cli/handlers/launch/datahaven.ts +++ b/test/cli/handlers/launch/datahaven.ts @@ -66,38 +66,6 @@ export const launchDataHavenSolochain = async ( let shouldLaunchDataHaven = options.datahaven; - if ((await checkDataHavenRunning()) && !options.alwaysClean) { - logger.info("โ„น๏ธ DataHaven network (Docker containers) is already running."); - - logger.trace("Checking if datahaven option was set via flags"); - if (options.datahaven === false) { - logger.info("Keeping existing DataHaven containers."); - - await registerNodes(launchedNetwork); - printDivider(); - return; - } - - if (options.datahaven === true) { - await cleanDataHavenContainers(options); - } else { - const shouldRelaunch = await confirmWithTimeout( - "Do you want to clean and relaunch the DataHaven containers?", - true, - 10 - ); - - if (!shouldRelaunch) { - logger.info("Keeping existing DataHaven containers."); - - await registerNodes(launchedNetwork); - printDivider(); - return; - } - await cleanDataHavenContainers(options); - } - } - if (shouldLaunchDataHaven === undefined) { shouldLaunchDataHaven = await confirmWithTimeout( "Do you want to launch the DataHaven network?", @@ -111,11 +79,42 @@ export const launchDataHavenSolochain = async ( } if (!shouldLaunchDataHaven) { - logger.info("Skipping DataHaven network launch. Done!"); + logger.info("๐Ÿ‘ Skipping DataHaven network launch. Done!"); + + await registerNodes(launchedNetwork); printDivider(); return; } + if (await checkDataHavenRunning()) { + // If the user wants to launch the DataHaven network, we ask them if they want + // to clean the existing containers/network or just continue with the existing + // containers/network. + if (shouldLaunchDataHaven) { + let shouldRelaunch = options.cleanNetwork; + + if (shouldRelaunch === undefined) { + shouldRelaunch = await confirmWithTimeout( + "Do you want to clean and relaunch the DataHaven containers?", + true, + 10 + ); + } + + // Case: User wants to keep existing containers/network + if (!shouldRelaunch) { + logger.info("๐Ÿ‘ Keeping existing DataHaven containers/network."); + + await registerNodes(launchedNetwork); + printDivider(); + return; + } + + // Case: User wants to clean and relaunch the DataHaven containers + await cleanDataHavenContainers(options); + } + } + logger.info(`โ›“๏ธโ€๐Ÿ’ฅ Creating Docker network: ${DOCKER_NETWORK_NAME}`); logger.debug(await $`docker network rm ${DOCKER_NETWORK_NAME} -f`.text()); logger.debug(await $`docker network create ${DOCKER_NETWORK_NAME}`.text()); @@ -125,7 +124,6 @@ export const launchDataHavenSolochain = async ( await buildLocalImage(options); await checkTagExists(options.datahavenImageTag); - launchedNetwork.networkName = DOCKER_NETWORK_NAME; logger.success(`DataHaven nodes will use Docker network: ${DOCKER_NETWORK_NAME}`); for (const id of CLI_AUTHORITY_IDS) { @@ -191,18 +189,25 @@ export const launchDataHavenSolochain = async ( */ const checkDataHavenRunning = async (): Promise => { // Check for any container whose name starts with "datahaven-" - const containerIds = await $`docker ps -q --filter "name=^datahaven-"`.text(); + const containerIds = await $`docker ps --format "{{.Names}}" --filter "name=^datahaven-"`.text(); const networkOutput = await $`docker network ls --filter "name=^${DOCKER_NETWORK_NAME}$" --format "{{.Name}}"`.text(); // Check if containerIds has any actual IDs (not just whitespace) const containersExist = containerIds.trim().length > 0; + if (containersExist) { + logger.info(`โ„น๏ธ DataHaven containers already running: \n${containerIds}`); + } + // Check if networkOutput has any network names (not just whitespace or empty lines) const networksExist = networkOutput .trim() .split("\n") .filter((line) => line.trim().length > 0).length > 0; + if (networksExist) { + logger.info(`โ„น๏ธ DataHaven network already running: ${networkOutput}`); + } return containersExist || networksExist; }; @@ -227,6 +232,11 @@ const cleanDataHavenContainers = async (options: LaunchOptions): Promise = logger.debug(await $`docker network rm -f ${DOCKER_NETWORK_NAME}`.text()); logger.info("โœ… DataHaven Docker network removed."); + + invariant( + (await checkDataHavenRunning()) === false, + "โŒ DataHaven containers were not stopped and removed" + ); }; /** @@ -309,6 +319,9 @@ const checkTagExists = async (tag: string) => { }; const registerNodes = async (launchedNetwork: LaunchedNetwork) => { + // Registering DataHaven nodes Docker network. + launchedNetwork.networkName = DOCKER_NETWORK_NAME; + const targetContainerName = "datahaven-alice"; const aliceHostWsPort = 9944; // Standard host port for Alice's WS, as set during launch. @@ -319,9 +332,8 @@ const registerNodes = async (launchedNetwork: LaunchedNetwork) => { if (!isContainerRunning) { // If the target Docker container is not running, we cannot register it. - throw new Error( - `โŒ Docker container ${targetContainerName} is not running. Cannot register node.` - ); + logger.warn(`โš ๏ธ Docker container ${targetContainerName} is not running. Cannot register node.`); + return; } // If the Docker container is running, proceed to register it in launchedNetwork. diff --git a/test/cli/handlers/launch/index.ts b/test/cli/handlers/launch/index.ts index 87b88891..2f723ded 100644 --- a/test/cli/handlers/launch/index.ts +++ b/test/cli/handlers/launch/index.ts @@ -19,8 +19,7 @@ export interface LaunchOptions { blockscout?: boolean; relayer?: boolean; relayerImageTag?: string; - skipCleaning?: boolean; - alwaysClean?: boolean; + cleanNetwork?: boolean; datahaven?: boolean; buildDatahaven?: boolean; datahavenImageTag?: string; diff --git a/test/cli/handlers/launch/kurtosis.ts b/test/cli/handlers/launch/kurtosis.ts index 3c3c39b4..3f89ee1b 100644 --- a/test/cli/handlers/launch/kurtosis.ts +++ b/test/cli/handlers/launch/kurtosis.ts @@ -15,27 +15,43 @@ export const launchKurtosis = async ( launchedNetwork: LaunchedNetwork, options: LaunchOptions = {} ): Promise => { - printHeader("Starting Kurtosis Network"); + printHeader("Starting Kurtosis EthereumNetwork"); - if ((await checkKurtosisRunning()) && !options.alwaysClean) { - logger.info("โ„น๏ธ Kurtosis network is already running."); + let shouldLaunchKurtosis = options.launchKurtosis; - logger.trace("Checking if launchKurtosis option was set via flags"); - if (options.launchKurtosis === false) { - logger.info("๐Ÿ‘ Keeping existing Kurtosis enclave."); + if (shouldLaunchKurtosis === undefined) { + shouldLaunchKurtosis = await confirmWithTimeout( + "Do you want to launch the Kurtosis network?", + true, + 10 + ); + } - await registerServices(launchedNetwork); - printDivider(); - return; - } + if (!shouldLaunchKurtosis) { + logger.info("๐Ÿ‘ Skipping Kurtosis Ethereum network launch. Done!"); - if (options.launchKurtosis !== true) { - const shouldRelaunch = await confirmWithTimeout( - "Do you want to clean and relaunch the Kurtosis enclave?", - true, - 10 - ); + await registerServices(launchedNetwork); + printDivider(); + return; + } + if (await checkKurtosisRunning()) { + logger.info("โ„น๏ธ Kurtosis Ethereum network is already running."); + + // If the user wants to launch the Kurtosis network, we ask them if they want + // to clean the existing enclave or just continue with the existing enclave. + if (shouldLaunchKurtosis) { + let shouldRelaunch = options.cleanNetwork; + + if (shouldRelaunch === undefined) { + shouldRelaunch = await confirmWithTimeout( + "Do you want to clean and relaunch the Kurtosis enclave?", + true, + 10 + ); + } + + // Case: User wants to keep existing enclave if (!shouldRelaunch) { logger.info("๐Ÿ‘ Keeping existing Kurtosis enclave."); @@ -43,15 +59,14 @@ export const launchKurtosis = async ( printDivider(); return; } - } - } - if (!options.skipCleaning) { - logger.info("๐Ÿงน Cleaning up Docker and Kurtosis environments..."); - logger.debug(await $`kurtosis enclave stop datahaven-ethereum`.nothrow().text()); - logger.debug(await $`kurtosis clean`.text()); - logger.debug(await $`kurtosis engine stop`.text()); - logger.debug(await $`docker system prune -f`.nothrow().text()); + // Case: User wants to clean and relaunch the enclave + logger.info("๐Ÿงน Cleaning up Docker and Kurtosis environments..."); + logger.debug(await $`kurtosis enclave stop datahaven-ethereum`.nothrow().text()); + logger.debug(await $`kurtosis clean`.text()); + logger.debug(await $`kurtosis engine stop`.nothrow().text()); + logger.debug(await $`docker system prune -f`.nothrow().text()); + } } if (process.platform === "darwin") { @@ -141,19 +156,23 @@ const registerServices = async (launchedNetwork: LaunchedNetwork) => { logger.info("๐Ÿ“ Registering Kurtosis service endpoints..."); // Configure EL RPC URL - const rethPublicPort = await getPortFromKurtosis("el-1-reth-lighthouse", "rpc"); - invariant(rethPublicPort && rethPublicPort > 0, "โŒ Could not find EL RPC port"); - const elRpcUrl = `http://127.0.0.1:${rethPublicPort}`; - launchedNetwork.elRpcUrl = elRpcUrl; - logger.info(`๐Ÿ“ Execution Layer RPC URL configured: ${elRpcUrl}`); + try { + const rethPublicPort = await getPortFromKurtosis("el-1-reth-lighthouse", "rpc"); + invariant(rethPublicPort && rethPublicPort > 0, "โŒ Could not find EL RPC port"); + const elRpcUrl = `http://127.0.0.1:${rethPublicPort}`; + launchedNetwork.elRpcUrl = elRpcUrl; + logger.info(`๐Ÿ“ Execution Layer RPC URL configured: ${elRpcUrl}`); - // Configure CL Endpoint - const lighthousePublicPort = await getPortFromKurtosis("cl-1-lighthouse-reth", "http"); - const clEndpoint = `http://127.0.0.1:${lighthousePublicPort}`; - invariant( - clEndpoint, - "โŒ CL Endpoint could not be determined from Kurtosis service cl-1-lighthouse-reth" - ); - launchedNetwork.clEndpoint = clEndpoint; - logger.info(`๐Ÿ“ Consensus Layer Endpoint configured: ${clEndpoint}`); + // Configure CL Endpoint + const lighthousePublicPort = await getPortFromKurtosis("cl-1-lighthouse-reth", "http"); + const clEndpoint = `http://127.0.0.1:${lighthousePublicPort}`; + invariant( + clEndpoint, + "โŒ CL Endpoint could not be determined from Kurtosis service cl-1-lighthouse-reth" + ); + launchedNetwork.clEndpoint = clEndpoint; + logger.info(`๐Ÿ“ Consensus Layer Endpoint configured: ${clEndpoint}`); + } catch (error) { + logger.warn(`โš ๏ธ Kurtosis service endpoints could not be determined: ${error}`); + } }; diff --git a/test/cli/handlers/launch/relayer.ts b/test/cli/handlers/launch/relayer.ts index c3bbbf43..669e7e93 100644 --- a/test/cli/handlers/launch/relayer.ts +++ b/test/cli/handlers/launch/relayer.ts @@ -67,7 +67,7 @@ export const launchRelayers = async (options: LaunchOptions, launchedNetwork: La } if (!shouldLaunchRelayers) { - logger.info("Skipping Snowbridge relayers launch. Done!"); + logger.info("๐Ÿ‘ Snowbridge relayers launch. Done!"); printDivider(); return; } @@ -339,6 +339,10 @@ export const initEthClientPallet = async ( logger.debug(await $`docker rm -f generate-beacon-checkpoint`.text()); logger.debug("Generating beacon checkpoint"); + invariant( + launchedNetwork.networkName, + "โŒ Docker network name not found in LaunchedNetwork instance" + ); const command = `docker run \ -v ${beaconConfigHostPath}:${beaconConfigContainerPath}:ro \ -v ${checkpointHostPath}:${checkpointContainerPath} \ diff --git a/test/cli/index.ts b/test/cli/index.ts index a85f95be..1bce277b 100644 --- a/test/cli/index.ts +++ b/test/cli/index.ts @@ -32,6 +32,7 @@ const program = new Command() .option("--nr, --no-relayer", "Skip Snowbridge Relayers") .option("--b, --blockscout", "Enable Blockscout") .option("--slot-time ", "Set slot time in seconds", parseIntValue) + .option("--cn, --clean-network", "Always clean Kurtosis enclave and Docker containers") .option( "--datahaven-build-extra-args ", "Extra args for DataHaven node Cargo build (the plain command is `cargo build --release` for linux, `cargo zigbuild --target x86_64-unknown-linux-gnu --release` for mac)", @@ -39,8 +40,6 @@ const program = new Command() ) .option("--kurtosis-network-args ", "CustomKurtosis network args") .option("--verified", "Verify smart contracts with Blockscout") - .option("--always-clean", "Always clean Kurtosis", false) - .option("--skip-cleaning", "Skip cleaning Kurtosis") .option( "-i, --datahaven-image-tag ", "Tag of the datahaven image to use", diff --git a/test/package.json b/test/package.json index 29f286d5..3e31c7d1 100644 --- a/test/package.json +++ b/test/package.json @@ -16,9 +16,9 @@ "start:e2e:verified": "bun cli --verified --blockscout --deploy-contracts --setup-validators --update-validator-set --fund-validators", "start:e2e:verified:relayers": "bun cli --verified --blockscout --deploy-contracts --setup-validators --update-validator-set --fund-validators --slot-time 1 --relayer --datahaven", "start:e2e:local": "LOG_LEVEL=debug bun start:e2e:ci --bd", - "start:e2e:ci": "bun cli --datahaven --no-build-datahaven --launch-kurtosis --deploy-contracts --fund-validators --setup-validators --update-validator-set --relayer --always-clean", + "start:e2e:ci": "bun cli --datahaven --no-build-datahaven --launch-kurtosis --deploy-contracts --fund-validators --setup-validators --update-validator-set --relayer --clean-network", "start:e2e:minrelayer": "bun cli --relayer --deploy-contracts --no-setup-validators --no-update-validator-set --no-fund-validators --datahaven", - "stop:docker:datahaven": "docker rm -f $(docker ps -aq --filter name='^datahaven-') 2>/dev/null || true", + "stop:docker:datahaven": "docker rm -f $(docker ps -aq --filter name='^datahaven-') 2>/dev/null || true; docker network rm datahaven-net || true", "stop:docker:relayer": "docker rm -f $(docker ps -aq --filter name='^snowbridge-relayer-') 2>/dev/null || true", "stop:e2e": "bun stop:docker:datahaven ; bun stop:docker:relayer ; (kurtosis enclave stop datahaven-ethereum || true) && kurtosis clean && kurtosis engine stop && docker container prune -f", "start:e2e:minimal:relayer": "bun cli --relayer --deploy-contracts --no-setup-validators --no-update-validator-set --no-fund-validators --datahaven", diff --git a/test/scripts/deploy-contracts.ts b/test/scripts/deploy-contracts.ts index 4d801bef..b7ac2e42 100644 --- a/test/scripts/deploy-contracts.ts +++ b/test/scripts/deploy-contracts.ts @@ -43,7 +43,7 @@ export const deployContracts = async (options: DeployContractsOptions): Promise< } if (!shouldDeployContracts) { - logger.info("Skipping contract deployment. Done!"); + logger.info("๐Ÿ‘ Skipping contract deployment. Done!"); printDivider(); return false;