diff --git a/crates/icp-cli/src/commands/canister/mod.rs b/crates/icp-cli/src/commands/canister/mod.rs index b2b3b9abf..10ee38fe9 100644 --- a/crates/icp-cli/src/commands/canister/mod.rs +++ b/crates/icp-cli/src/commands/canister/mod.rs @@ -15,6 +15,7 @@ pub(crate) mod stop; pub(crate) mod top_up; #[derive(Debug, Subcommand)] +#[allow(clippy::large_enum_variant)] pub(crate) enum Command { /// Make a canister call Call(call::CallArgs), diff --git a/crates/icp-cli/src/commands/canister/settings/update.rs b/crates/icp-cli/src/commands/canister/settings/update.rs index 353dedb1c..b3800a866 100644 --- a/crates/icp-cli/src/commands/canister/settings/update.rs +++ b/crates/icp-cli/src/commands/canister/settings/update.rs @@ -4,12 +4,17 @@ use byte_unit::{Byte, Unit}; use clap::{ArgAction, Args}; use ic_agent::{AgentError, export::Principal}; use ic_management_canister_types::{CanisterStatusResult, EnvironmentVariable, LogVisibility}; -use icp::{agent, identity, network}; - -use icp::context::Context; +use icp::{ + agent, + context::{ + Context, GetAgentForEnvError, GetCanisterIdAndAgentError, GetCanisterIdForEnvError, + GetEnvironmentError, + }, + identity, network, + store_id::LookupError as LookupIdError, +}; -use crate::options::{EnvironmentOpt, IdentityOpt}; -use icp::store_id::{Key, LookupError as LookupIdError}; +use crate::commands::args; #[derive(Clone, Debug, Default, Args)] pub(crate) struct ControllerOpt { @@ -73,14 +78,8 @@ impl EnvironmentVariableOpt { #[derive(Debug, Args)] pub(crate) struct UpdateArgs { - /// The name of the canister within the current project - pub(crate) name: String, - - #[command(flatten)] - identity: IdentityOpt, - #[command(flatten)] - environment: EnvironmentOpt, + pub(crate) cmd_args: args::CanisterCommandArgs, #[command(flatten)] controllers: Option, @@ -118,21 +117,12 @@ pub(crate) enum CommandError { #[error(transparent)] Identity(#[from] identity::LoadError), - #[error("project does not contain an environment named '{name}'")] - EnvironmentNotFound { name: String }, - #[error(transparent)] Access(#[from] network::AccessError), #[error(transparent)] Agent(#[from] agent::CreateError), - #[error("environment '{environment}' does not include canister '{canister}'")] - EnvironmentCanister { - environment: String, - canister: String, - }, - #[error("invalid environment variable '{variable}'")] InvalidEnvironmentVariable { variable: String }, @@ -141,47 +131,30 @@ pub(crate) enum CommandError { #[error(transparent)] Update(#[from] AgentError), -} - -pub(crate) async fn exec(ctx: &Context, args: &UpdateArgs) -> Result<(), CommandError> { - // Load project - let p = ctx.project.load().await?; - - // Load identity - let id = ctx.identity.load(args.identity.clone().into()).await?; - - // Load target environment - let env = - p.environments - .get(args.environment.name()) - .ok_or(CommandError::EnvironmentNotFound { - name: args.environment.name().to_owned(), - })?; - // Access network - let access = ctx.network.access(&env.network).await?; + #[error(transparent)] + GetAgentForEnv(#[from] GetAgentForEnvError), - // Agent - let agent = ctx.agent.create(id, &access.url).await?; + #[error(transparent)] + GetEnvironment(#[from] GetEnvironmentError), - if let Some(k) = access.root_key { - agent.set_root_key(k); - } + #[error(transparent)] + GetCanisterIdForEnv(#[from] GetCanisterIdForEnvError), - // Ensure canister is included in the environment - if !env.canisters.contains_key(&args.name) { - return Err(CommandError::EnvironmentCanister { - environment: env.name.to_owned(), - canister: args.name.to_owned(), - }); - } + #[error(transparent)] + GetCanisterIdAndAgent(#[from] GetCanisterIdAndAgentError), +} - // Lookup the canister id - let cid = ctx.ids.lookup(&Key { - network: env.network.name.to_owned(), - environment: env.name.to_owned(), - canister: args.name.to_owned(), - })?; +pub(crate) async fn exec(ctx: &Context, args: &UpdateArgs) -> Result<(), CommandError> { + let selections = args.cmd_args.selections(); + let (cid, agent) = ctx + .get_canister_id_and_agent( + &selections.canister, + &selections.environment, + &selections.network, + &selections.identity, + ) + .await?; // Management Interface let mgmt = ic_utils::interfaces::ManagementCanister::create(&agent); @@ -291,6 +264,7 @@ fn log_visibility_parser(log_visibility: &str) -> Result } } +#[allow(clippy::result_large_err)] fn environment_variable_parser(env_var: &str) -> Result { let (name, value) = env_var diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 3a9107199..eb6a84b28 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -259,17 +259,17 @@ List the canisters in an environment ## `icp-cli canister settings update` -**Usage:** `icp-cli canister settings update [OPTIONS] ` +**Usage:** `icp-cli canister settings update [OPTIONS] ` ###### **Arguments:** -* `` — The name of the canister within the current project +* `` — Name or principal of canister to target When using a name an environment must be specified ###### **Options:** +* `--network ` — Name of the network to target, conflicts with environment argument +* `--environment ` — Name of the target environment * `--identity ` — The user identity to run this command as -* `--environment ` — Override the environment to connect to. By default, the local environment is used -* `--ic` — Shorthand for --environment=ic * `--add-controller ` * `--remove-controller ` * `--set-controller `