fix: 🐛 CLI fixes for independently running parts of it (#85)

This commit is contained in:
Facundo Farall 2025-05-21 14:01:12 -03:00 committed by GitHub
parent d79f727949
commit c29fc8f06d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 128 additions and 95 deletions

View file

@ -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
readOnly: true

View file

@ -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
- |

View file

@ -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<boolean> => {
// 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<void> =
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.

View file

@ -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;

View file

@ -15,27 +15,43 @@ export const launchKurtosis = async (
launchedNetwork: LaunchedNetwork,
options: LaunchOptions = {}
): Promise<void> => {
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}`);
}
};

View file

@ -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} \

View file

@ -32,6 +32,7 @@ const program = new Command()
.option("--nr, --no-relayer", "Skip Snowbridge Relayers")
.option("--b, --blockscout", "Enable Blockscout")
.option("--slot-time <number>", "Set slot time in seconds", parseIntValue)
.option("--cn, --clean-network", "Always clean Kurtosis enclave and Docker containers")
.option(
"--datahaven-build-extra-args <value>",
"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 <value>", "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 <value>",
"Tag of the datahaven image to use",

View file

@ -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",

View file

@ -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;