diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 69ecf8d1b9ce46d7c8f4831d0b90395fcf85ea8a..bf5ddb37e7e4ca6adfbeaf6511cb7b87a0f22ecc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,14 @@ stages: - integration-test +cache: + - key: + files: + - Cargo.lock + - paths: + - target + - ${CARGO_HOME} + include: # ci image - project: parity/infrastructure/ci_cd/shared @@ -23,6 +31,7 @@ k8s-integration-test-smoke: tags: - zombienet-polkadot-integration-test script: - - cargo test --features ci-k8s --test smoke -- --nocapture + - RUST_LOG=zombienet_orchestrator=debug cargo test --features ci-k8s --test smoke -- --nocapture variables: CI_IMAGE: !reference [.ci-unified, variables, CI_IMAGE] + RUN_IN_CI: "1" diff --git a/crates/orchestrator/src/spawner.rs b/crates/orchestrator/src/spawner.rs index a084d60f50814e9ff495ebd5609ee7cfad7da5af..d5ab43ba7674ae6ba0481816b5c62a0dcac983e3 100644 --- a/crates/orchestrator/src/spawner.rs +++ b/crates/orchestrator/src/spawner.rs @@ -176,8 +176,10 @@ where ) })?; - let (mut rpc_port_external, mut prometheus_port_external) = - (node.ws_port.0, node.prometheus_port.0); + let mut ip_to_use = LOCALHOST; + + let (rpc_port_external, prometheus_port_external); + // Create port-forward iff we are not in CI if !running_in_ci() { let ports = futures::future::try_join_all(vec![ @@ -190,10 +192,14 @@ where ports[0].unwrap_or(node.ws_port.0), ports[1].unwrap_or(node.prometheus_port.0), ); + } else { + // running in ci requrire to use ip and default port + (rpc_port_external, prometheus_port_external) = (RPC_PORT, PROMETHEUS_PORT); + ip_to_use = running_node.ip().await?; } - let ws_uri = format!("ws://{}:{}", LOCALHOST, rpc_port_external); - let prometheus_uri = format!("http://{}:{}/metrics", LOCALHOST, prometheus_port_external); + let ws_uri = format!("ws://{}:{}", ip_to_use, rpc_port_external); + let prometheus_uri = format!("http://{}:{}/metrics", ip_to_use, prometheus_port_external); info!("🚀 {}, should be running now", node.name); info!( "🚀 {}: direct link https://polkadot.js.org/apps/?rpc={ws_uri}#/explorer", diff --git a/crates/provider/src/kubernetes/client.rs b/crates/provider/src/kubernetes/client.rs index b447e3cfb37fc7e841c84edc98c15e46956a7142..de6b5907d722ad809a778f7917edc6c46aad17d1 100644 --- a/crates/provider/src/kubernetes/client.rs +++ b/crates/provider/src/kubernetes/client.rs @@ -17,6 +17,7 @@ use kube::{ use serde::de::DeserializeOwned; use tokio::{io::AsyncRead, net::TcpListener, task::JoinHandle}; use tokio_util::compat::FuturesAsyncReadCompatExt; +use tracing::debug; use crate::{constants::LOCALHOST, types::ExecutionResult}; @@ -165,6 +166,7 @@ impl KubernetesClient { Error::from(anyhow!("error while awaiting pod {name} running: {err}")) })?; + debug!("Pod {name} is Ready!"); Ok(pod) } @@ -230,6 +232,15 @@ impl KubernetesClient { where S: Into<String> + std::fmt::Debug + Send, { + let _pod = Api::<Pod>::namespaced(self.inner.clone(), namespace) + .get(name) + .await + .map_err(|err| { + Error::from(anyhow!( + "error while trying to exec in the pod {name}, can't find it: {err}" + )) + })?; + let mut process = Api::<Pod>::namespaced(self.inner.clone(), namespace) .exec( name, @@ -296,8 +307,8 @@ impl KubernetesClient { Ok(Err((exit_status, stderr))) }, // due to other unknown reason - Some(reason) => Err(Error::from(anyhow!( - "unhandled reason while exec for {name}: {reason}" + Some(ref reason) => Err(Error::from(anyhow!( + format!("unhandled reason while exec for {name}: {reason}, stderr: {stderr}, status: {:?}", status) ))), None => { panic!("command had status but no reason was present, this is a bug") @@ -369,7 +380,13 @@ impl KubernetesClient { remote_port: u16, ) -> Result<(u16, JoinHandle<()>)> { let pods = Api::<Pod>::namespaced(self.inner.clone(), namespace); - let bind = TcpListener::bind((LOCALHOST, local_port)).await.unwrap(); + let bind = TcpListener::bind((LOCALHOST, local_port)) + .await + .map_err(|err| { + Error::from(anyhow!( + "error binding port {local_port} for pod {name}: {err}" + )) + })?; let local_port = bind.local_addr().map_err(|err| Error(err.into()))?.port(); let name = name.to_string(); @@ -467,6 +484,7 @@ impl KubernetesClient { mod helpers { use k8s_openapi::api::core::v1::Pod; use kube::runtime::wait::Condition; + use tracing::trace; /// An await condition for `Pod` that returns `true` once it is ready /// based on [`kube::runtime::wait::conditions::is_pod_running`] @@ -475,9 +493,14 @@ mod helpers { if let Some(pod) = &obj { if let Some(status) = &pod.status { if let Some(conditions) = &status.conditions { - return conditions + let ready = conditions .iter() .any(|cond| cond.status == "True" && cond.type_ == "Ready"); + + if ready { + trace!("{:#?}", status); + return ready; + } } } } diff --git a/crates/provider/src/kubernetes/namespace.rs b/crates/provider/src/kubernetes/namespace.rs index b4ffe3f8765f27db20043faa303a5df401712cac..998b003af932ccea468e4d338b3172fe7bac4167 100644 --- a/crates/provider/src/kubernetes/namespace.rs +++ b/crates/provider/src/kubernetes/namespace.rs @@ -401,8 +401,7 @@ where match temp_node .run_command(RunCommandOptions { program, args, env }) - .await - .map_err(|err| ProviderError::FileGenerationFailed(err.into()))? + .await? { Ok(contents) => self .filesystem diff --git a/crates/provider/src/kubernetes/node.rs b/crates/provider/src/kubernetes/node.rs index 34e4ce97bad0daf828f99eed572e682d09135f0c..9577cc0bd43b3a80446400c430f13d821103a20b 100644 --- a/crates/provider/src/kubernetes/node.rs +++ b/crates/provider/src/kubernetes/node.rs @@ -414,7 +414,13 @@ where vec!["sh", "-c", &command.join(" ")], ) .await - .map_err(|err| ProviderError::RunCommandError(self.name.to_string(), err.into())) + .map_err(|err| { + ProviderError::RunCommandError( + format!("sh -c {}", &command.join(" ")), + self.name.to_string(), + err.into(), + ) + }) } async fn run_script( diff --git a/crates/provider/src/lib.rs b/crates/provider/src/lib.rs index da238652a5eef7223d225058b8dd8d1b223127ae..5e6ccf9305b12894e5b3e12e6c752bf1a9154871 100644 --- a/crates/provider/src/lib.rs +++ b/crates/provider/src/lib.rs @@ -32,8 +32,8 @@ pub enum ProviderError { #[error("Failed to spawn node '{0}': {1}")] NodeSpawningFailed(String, anyhow::Error), - #[error("Error running command '{0}': {1}")] - RunCommandError(String, anyhow::Error), + #[error("Error running command '{0}' in pod {1}: {2}")] + RunCommandError(String, String, anyhow::Error), #[error("Error running script'{0}': {1}")] RunScriptError(String, anyhow::Error), diff --git a/crates/provider/src/native/node.rs b/crates/provider/src/native/node.rs index 88ca59b400997a75f00de58f9186a86c98ce452b..078fb805b4000718c05678053b884203c0f05b59 100644 --- a/crates/provider/src/native/node.rs +++ b/crates/provider/src/native/node.rs @@ -310,12 +310,18 @@ where options: RunCommandOptions, ) -> Result<ExecutionResult, ProviderError> { let result = Command::new(options.program.clone()) - .args(options.args) + .args(options.args.clone()) .envs(options.env) .current_dir(&self.base_dir) .output() .await - .map_err(|err| ProviderError::RunCommandError(options.program, err.into()))?; + .map_err(|err| { + ProviderError::RunCommandError( + format!("{} {}", &options.program, &options.args.join(" ")), + options.program, + err.into(), + ) + })?; if result.status.success() { Ok(Ok(String::from_utf8_lossy(&result.stdout).to_string()))