Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/icp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ tiny-bip39.workspace = true
tokio.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
url.workspace = true

[dev-dependencies]
assert_cmd = "2"
Expand All @@ -65,7 +66,6 @@ predicates = "3"
rand.workspace = true
serde_yaml.workspace = true
serial_test = { version = "3.2.0", features = ["file_locks"] }
url.workspace = true
uuid.workspace = true

[lints]
Expand Down
114 changes: 10 additions & 104 deletions crates/icp-cli/src/commands/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,23 @@ use clap::Args;
use icp::context::{CanisterSelection, EnvironmentSelection, NetworkSelection};
use icp::identity::IdentitySelection;

use crate::options::IdentityOpt;
use crate::options::{EnvironmentOpt, IdentityOpt, NetworkOpt};

#[derive(Args, Debug)]
pub(crate) struct CanisterEnvironmentArgs {
/// Name or principal of canister to target
/// When using a name an environment must be specified
pub(crate) canister: Canister,

/// Name of the target environment
#[arg(long)]
pub(crate) environment: Option<Environment>,
#[command(flatten)]
pub(crate) environment: EnvironmentOpt,
}

impl CanisterEnvironmentArgs {
/// Convert arguments into selection enums for canister and environment
pub(crate) fn selections(&self) -> (CanisterSelection, EnvironmentSelection) {
let canister_selection: CanisterSelection = self.canister.clone().into();
let environment_selection: EnvironmentSelection =
self.environment.clone().unwrap_or_default().into();
let environment_selection: EnvironmentSelection = self.environment.clone().into();
(canister_selection, environment_selection)
}
}
Expand All @@ -35,15 +33,12 @@ pub(crate) struct CanisterCommandArgs {
/// When using a name an environment must be specified
pub(crate) canister: Canister,

/// Name of the network to target, conflicts with environment argument
#[arg(long, conflicts_with = "environment")]
pub(crate) network: Option<Network>,
#[command(flatten)]
pub(crate) network: NetworkOpt,

/// Name of the target environment
#[arg(long)]
pub(crate) environment: Option<Environment>,
#[command(flatten)]
pub(crate) environment: EnvironmentOpt,

/// The identity to use for this request
#[command(flatten)]
pub(crate) identity: IdentityOpt,
}
Expand All @@ -60,12 +55,8 @@ impl CanisterCommandArgs {
/// Convert command arguments into selection enums
pub(crate) fn selections(&self) -> CommandSelections {
let canister_selection: CanisterSelection = self.canister.clone().into();
let environment_selection: EnvironmentSelection =
self.environment.clone().unwrap_or_default().into();
let network_selection: NetworkSelection = match self.network.clone() {
Some(network) => network.into_selection(),
None => NetworkSelection::FromEnvironment,
};
let environment_selection: EnvironmentSelection = self.environment.clone().into();
let network_selection: NetworkSelection = self.network.clone().into();
let identity_selection: IdentitySelection = self.identity.clone().into();

CommandSelections {
Expand Down Expand Up @@ -111,73 +102,6 @@ impl Display for Canister {
}
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Network {
Name(String),
Url(String),
}

impl From<&str> for Network {
fn from(v: &str) -> Self {
if v.starts_with("http://") || v.starts_with("https://") {
return Self::Url(v.to_string());
}

Self::Name(v.to_string())
}
}

impl Network {
pub(crate) fn into_selection(self) -> NetworkSelection {
match self {
Network::Name(name) => NetworkSelection::Named(name),
Network::Url(url) => NetworkSelection::Url(url),
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Environment {
Name(String),
Default(String),
}

impl Environment {
pub(crate) fn name(&self) -> &str {
match self {
Environment::Name(name) => name,
Environment::Default(name) => name,
}
}
}

impl Default for Environment {
fn default() -> Self {
Self::Default("local".to_string())
}
}

impl From<&str> for Environment {
fn from(v: &str) -> Self {
Self::Name(v.to_string())
}
}

impl From<Environment> for EnvironmentSelection {
fn from(v: Environment) -> Self {
match v {
Environment::Name(name) => EnvironmentSelection::Named(name),
Environment::Default(_) => EnvironmentSelection::Default,
}
}
}

impl Display for Environment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}

#[cfg(test)]
mod tests {
use candid::Principal;
Expand All @@ -201,22 +125,4 @@ mod tests {
Canister::Principal(Principal::from_text(cid).expect("failed to parse principal")),
);
}

#[test]
fn network_by_name() {
assert_eq!(
Network::from("my-network"),
Network::Name("my-network".to_string()),
);
}

#[test]
fn network_by_url_http() {
let url = "http://www.example.com";

assert_eq!(
Network::from(url),
Network::Url("http://www.example.com".to_string()),
);
}
}
18 changes: 12 additions & 6 deletions crates/icp-cli/src/commands/canister/binding_env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use ic_agent::AgentError;
use ic_utils::interfaces::management_canister::builders::EnvironmentVariable;
use icp::{
agent,
context::{GetAgentForEnvError, GetCanisterIdForEnvError, GetEnvironmentError},
context::{
EnvironmentSelection, GetAgentForEnvError, GetCanisterIdForEnvError, GetEnvironmentError,
},
identity, network,
};
use tracing::debug;
Expand Down Expand Up @@ -48,7 +50,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error("Could not find canister id(s) for '{}' in environment '{environment}' make sure they are created first", canister_names.join(", "))]
CanisterNotCreated {
Expand Down Expand Up @@ -76,12 +78,14 @@ pub(crate) enum CommandError {
}

pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), CommandError> {
let environment_selection: EnvironmentSelection = args.environment.clone().into();

// Load target environment
let env = ctx.get_environment(args.environment.name()).await?;
let env = ctx.get_environment(&environment_selection).await?;

// Agent
let agent = ctx
.get_agent_for_env(&args.identity.clone().into(), args.environment.name())
.get_agent_for_env(&args.identity.clone().into(), &environment_selection)
.await?;

let target_canisters = match args.names.is_empty() {
Expand All @@ -91,9 +95,11 @@ pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), Comman

let env_canisters = &env.canisters;
let canisters = try_join_all(target_canisters.into_iter().map(|name| {
let env_name = args.environment.name();
let environment_selection = environment_selection.clone();
async move {
let cid = ctx.get_canister_id_for_env(&name, env_name).await?;
let cid = ctx
.get_canister_id_for_env(&name, &environment_selection)
.await?;
let (_, info) = env_canisters
.get(&name)
.expect("Canister id exists but no canister info");
Expand Down
10 changes: 6 additions & 4 deletions crates/icp-cli/src/commands/canister/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use futures::{StreamExt, stream::FuturesOrdered};
use ic_agent::{Agent, AgentError, export::Principal};
use icp::{
agent,
context::{GetAgentForEnvError, GetEnvironmentError},
context::{EnvironmentSelection, GetAgentForEnvError, GetEnvironmentError},
identity, network,
prelude::*,
};
Expand Down Expand Up @@ -94,7 +94,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error("project does not contain a canister named '{name}'")]
CanisterNotFound { name: String },
Expand Down Expand Up @@ -137,11 +137,13 @@ pub(crate) enum CommandError {
// The cycles ledger will take cycles out of the user's account, and attaches them to a call to CMC::create_canister.
// The CMC will then pick a subnet according to the user's preferences and permissions, and create a canister on that subnet.
pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), CommandError> {
let environment_selection: EnvironmentSelection = args.environment.clone().into();

// Load project
let p = ctx.project.load().await?;

// Load target environment
let env = ctx.get_environment(args.environment.name()).await?;
let env = ctx.get_environment(&environment_selection).await?;

let target_canisters = match args.names.is_empty() {
true => env.get_canister_names(),
Expand Down Expand Up @@ -185,7 +187,7 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command

// Agent
let agent = ctx
.get_agent_for_env(&args.identity.clone().into(), args.environment.name())
.get_agent_for_env(&args.identity.clone().into(), &environment_selection)
.await?;

// Select which subnet to deploy the canisters to
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
Lookup(#[from] LookupIdError),
Expand Down
18 changes: 12 additions & 6 deletions crates/icp-cli/src/commands/canister/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use ic_agent::AgentError;
use ic_utils::interfaces::management_canister::builders::CanisterInstallMode;
use icp::{
agent,
context::{GetAgentForEnvError, GetCanisterIdForEnvError, GetEnvironmentError},
context::{
EnvironmentSelection, GetAgentForEnvError, GetCanisterIdForEnvError, GetEnvironmentError,
},
identity, network,
};
use tracing::debug;
Expand Down Expand Up @@ -46,7 +48,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
LookupCanisterId(#[from] LookupIdError),
Expand All @@ -68,12 +70,14 @@ pub(crate) enum CommandError {
}

pub(crate) async fn exec(ctx: &Context, args: &InstallArgs) -> Result<(), CommandError> {
let environment_selection: EnvironmentSelection = args.environment.clone().into();

// Load target environment
let env = ctx.get_environment(args.environment.name()).await?;
let env = ctx.get_environment(&environment_selection).await?;

// Agent
let agent = ctx
.get_agent_for_env(&args.identity.clone().into(), args.environment.name())
.get_agent_for_env(&args.identity.clone().into(), &environment_selection)
.await?;

let target_canisters = match args.names.is_empty() {
Expand All @@ -82,9 +86,11 @@ pub(crate) async fn exec(ctx: &Context, args: &InstallArgs) -> Result<(), Comman
};

let canisters = try_join_all(target_canisters.into_iter().map(|name| {
let env_name = args.environment.name();
let environment_selection = environment_selection.clone();
async move {
let cid = ctx.get_canister_id_for_env(&name, env_name).await?;
let cid = ctx
.get_canister_id_for_env(&name, &environment_selection)
.await?;
Ok::<_, CommandError>((name, cid))
}
}))
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/settings/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
Lookup(#[from] LookupIdError),
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/settings/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error("invalid environment variable '{variable}'")]
InvalidEnvironmentVariable { variable: String },
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
LookupCanisterId(#[from] LookupIdError),
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/stop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
LookupCanisterId(#[from] LookupIdError),
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/src/commands/canister/top_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(crate) enum CommandError {
Access(#[from] network::AccessError),

#[error(transparent)]
Agent(#[from] agent::CreateError),
Agent(#[from] agent::CreateAgentError),

#[error(transparent)]
Lookup(#[from] LookupIdError),
Expand Down
Loading