diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index eac29d25dd..b61cfea48f 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -48,6 +48,10 @@ and then exit immediately. This avoids interference between a dfx process performing cleanup at shutdown and a dfx process that is starting. +=== fix: dfx ping no longer creates a default identity + +dfx ping now uses the anonymous identity, and no longer requires dfx.json to be present. + == Dependencies == Replica diff --git a/docs/cli-reference/dfx-ping.md b/docs/cli-reference/dfx-ping.md index aeae3a7495..48f5fc62f0 100644 --- a/docs/cli-reference/dfx-ping.md +++ b/docs/cli-reference/dfx-ping.md @@ -2,7 +2,9 @@ Use the `dfx ping` command to check connectivity to the IC or a testnet. This command enables you to verify that you can connect to the environment where you want to deploy to. -Note that you can only run this command from within the project directory structure. For example, if your project name is `hello_world`, your current working directory must be the `hello_world` top-level project directory or one of its subdirectories. +To ping your local server, please note that you can only run this command from within the project directory structure. For example, if your project name is `hello_world`, your current working directory must be the `hello_world` top-level project directory or one of its subdirectories. + +To ping mainnet, you can run `dfx ping ic` from any directory. ## Basic usage diff --git a/e2e/tests-dfx/identity.bash b/e2e/tests-dfx/identity.bash index afc2d56f73..e917758b19 100644 --- a/e2e/tests-dfx/identity.bash +++ b/e2e/tests-dfx/identity.bash @@ -79,12 +79,21 @@ teardown() { assert_eq '(false)' } -@test "dfx ping creates the default identity on first run" { - install_asset identity +@test "dfx ping does not create a default identity" { dfx_start + + assert_file_not_exists "$DFX_CONFIG_ROOT/.config/dfx/identity.json" + assert_file_not_exists "$DFX_CONFIG_ROOT/.config/dfx/identity/default/identity.pem" + assert_command dfx ping + + assert_file_not_exists "$DFX_CONFIG_ROOT/.config/dfx/identity.json" + assert_file_not_exists "$DFX_CONFIG_ROOT/.config/dfx/identity/default/identity.pem" + # shellcheck disable=SC2154 - assert_match 'Creating the "default" identity.' "$stderr" + assert_not_match 'Creating' "$stderr" + # shellcheck disable=SC2154 + assert_not_match 'default' "$stderr" # shellcheck disable=SC2154 assert_match "ic_api_version" "$stdout" } diff --git a/e2e/tests-dfx/ping.bash b/e2e/tests-dfx/ping.bash index fc418edb72..2276ad4ba8 100644 --- a/e2e/tests-dfx/ping.bash +++ b/e2e/tests-dfx/ping.bash @@ -34,6 +34,19 @@ teardown() { assert_match "\"ic_api_version\"" } +@test "dfx ping does not require dfx.json" { + dfx_start + webserver_port=$(cat .dfx/webserver-port) + + mkdir "$DFX_E2E_TEMP_DIR/not-a-project" + ( + cd "$DFX_E2E_TEMP_DIR/not-a-project" + + assert_command dfx ping http://127.0.0.1:"$webserver_port" + assert_match "\"ic_api_version\"" + ) +} + @test "dfx ping succeeds by network name" { dfx_start assert_command dfx ping local diff --git a/e2e/utils/_.bash b/e2e/utils/_.bash index 76bfae5bf3..34ce8847c3 100644 --- a/e2e/utils/_.bash +++ b/e2e/utils/_.bash @@ -145,11 +145,7 @@ dfx_start() { wait_until_replica_healthy() { echo "waiting for replica to become healthy" - ( - # dfx ping has side effects, like creating a default identity. - DFX_CONFIG_ROOT="$DFX_E2E_TEMP_DIR/dfx-ping-tmp" - dfx ping --wait-healthy - ) + dfx ping --wait-healthy echo "replica became healthy" } diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index 97ef785c3e..defe000cf6 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -1,7 +1,6 @@ -use crate::config::dfinity::NetworkType; -use crate::lib::environment::{AgentEnvironment, Environment}; +use crate::lib::environment::{create_agent, Environment}; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::network::network_descriptor::NetworkDescriptor; +use crate::lib::identity::Identity; use crate::lib::provider::{ command_line_provider_to_url, get_network_context, get_network_descriptor, }; @@ -28,32 +27,24 @@ pub struct PingOpts { } pub fn exec(env: &dyn Environment, opts: PingOpts) -> DfxResult { - env.get_config_or_anyhow()?; - // For ping, "provider" could either be a URL or a network name. // If not passed, we default to the "local" network. - let network_descriptor = - get_network_descriptor(env, opts.network).or_else::(|err| { + let agent_url = get_network_descriptor(env, opts.network) + .and_then(|network_descriptor| { + let url = network_descriptor.first_provider()?.to_string(); + Ok(url) + }) + .or_else::(|err| { let logger = env.get_logger(); warn!(logger, "{}", err); let network_name = get_network_context()?; let url = command_line_provider_to_url(&network_name)?; - let is_ic = NetworkDescriptor::is_ic(&network_name, &vec![url.to_string()]); - let network_descriptor = NetworkDescriptor { - name: "-ping-".to_string(), - providers: vec![url], - r#type: NetworkType::Ephemeral, - is_ic, - }; - Ok(network_descriptor) + Ok(url) })?; let timeout = expiry_duration(); - let env = AgentEnvironment::new(env, network_descriptor, timeout)?; - - let agent = env - .get_agent() - .ok_or_else(|| anyhow!("Cannot find dfx configuration file in the current working directory. Did you forget to create one?"))?; + let identity = Box::new(Identity::anonymous()); + let agent = create_agent(env.get_logger().clone(), &agent_url, identity, timeout)?; let runtime = Runtime::new().expect("Unable to create a runtime"); if opts.wait_healthy { diff --git a/src/dfx/src/lib/environment.rs b/src/dfx/src/lib/environment.rs index eb0b979256..f22fd8b099 100644 --- a/src/dfx/src/lib/environment.rs +++ b/src/dfx/src/lib/environment.rs @@ -232,19 +232,14 @@ impl<'a> AgentEnvironment<'a> { network_descriptor: NetworkDescriptor, timeout: Duration, ) -> DfxResult { + let logger = backend.get_logger().clone(); let mut identity_manager = IdentityManager::new(backend)?; let identity = identity_manager.instantiate_selected_identity()?; + let url = network_descriptor.first_provider()?; - let agent_url = network_descriptor.providers.first().with_context(|| { - format!( - "Network '{}' does not specify any network providers.", - network_descriptor.name - ) - })?; Ok(AgentEnvironment { backend, - agent: create_agent(backend.get_logger().clone(), agent_url, identity, timeout) - .expect("Failed to construct agent."), + agent: create_agent(logger, url, identity, timeout)?, network_descriptor: network_descriptor.clone(), identity_manager, }) @@ -466,26 +461,23 @@ impl ic_agent::agent::http_transport::PasswordManager for AgentClient { } } -fn create_agent( +#[context("Failed to create agent with url {}.", url)] +pub fn create_agent( logger: Logger, url: &str, identity: Box, timeout: Duration, -) -> Option { - AgentClient::new(logger, url.to_string()) - .ok() - .and_then(|executor| { - Agent::builder() - .with_transport( - ic_agent::agent::http_transport::ReqwestHttpReplicaV2Transport::create(url) - .unwrap() - .with_password_manager(executor), - ) - .with_boxed_identity(identity) - .with_ingress_expiry(Some(timeout)) - .build() - .ok() - }) +) -> DfxResult { + let executor = AgentClient::new(logger, url.to_string())?; + let agent = Agent::builder() + .with_transport( + ic_agent::agent::http_transport::ReqwestHttpReplicaV2Transport::create(url)? + .with_password_manager(executor), + ) + .with_boxed_identity(identity) + .with_ingress_expiry(Some(timeout)) + .build()?; + Ok(agent) } #[cfg(test)] diff --git a/src/dfx/src/lib/network/network_descriptor.rs b/src/dfx/src/lib/network/network_descriptor.rs index d42cc7579b..b5946ee8a3 100644 --- a/src/dfx/src/lib/network/network_descriptor.rs +++ b/src/dfx/src/lib/network/network_descriptor.rs @@ -1,5 +1,8 @@ use crate::config::dfinity::NetworkType; use crate::config::dfinity::{DEFAULT_IC_GATEWAY, DEFAULT_IC_GATEWAY_TRAILING_SLASH}; +use crate::lib::error::DfxResult; + +use anyhow::bail; #[derive(Clone, Debug)] pub struct NetworkDescriptor { @@ -26,6 +29,17 @@ impl NetworkDescriptor { }; name_match || provider_match } + + /// Return the first provider in the list + pub fn first_provider(&self) -> DfxResult<&str> { + match self.providers.first() { + Some(provider) => Ok(provider), + None => bail!( + "Network '{}' does not specify any network providers.", + self.name + ), + } + } } #[cfg(test)]