Skip to content

Commit d9404ff

Browse files
committed
feat: Support global mode for more canister commands
1 parent ef339b9 commit d9404ff

File tree

9 files changed

+92
-307
lines changed

9 files changed

+92
-307
lines changed

crates/icp-cli/src/commands/canister/binding_env_vars.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub(crate) enum CommandError {
7777
InstallAgent(#[from] AgentError),
7878
}
7979

80+
// TODO: Needs to take a single canister arg and change to call an operation
8081
pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), CommandError> {
8182
// Load the project
8283
let p = ctx.project.load().await?;

crates/icp-cli/src/commands/canister/create.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub(crate) enum CommandError {
128128
Unexpected(#[from] anyhow::Error),
129129
}
130130

131+
// TODO: Needs to take a single canister arg and change to call an operation
131132
// Creates canister(s) by asking the cycles ledger to create them.
132133
// The cycles ledger will take cycles out of the user's account, and attaches them to a call to CMC::create_canister.
133134
// The CMC will then pick a subnet according to the user's preferences and permissions, and create a canister on that subnet.

crates/icp-cli/src/commands/canister/info.rs

Lines changed: 14 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,37 @@
11
use clap::Args;
2-
use ic_agent::AgentError;
32
use ic_utils::interfaces::management_canister::CanisterStatusResult;
4-
use icp::{agent, identity, network};
53
use itertools::Itertools;
64

75
use icp::context::Context;
86

9-
use crate::options::{EnvironmentOpt, IdentityOpt};
10-
use icp::store_id::{Key, LookupError as LookupIdError};
7+
use crate::commands::args;
118

129
#[derive(Debug, Args)]
1310
pub(crate) struct InfoArgs {
14-
/// The name of the canister within the current project
15-
pub(crate) name: String,
16-
17-
#[command(flatten)]
18-
identity: IdentityOpt,
19-
2011
#[command(flatten)]
21-
environment: EnvironmentOpt,
12+
pub(crate) cmd_args: args::CanisterCommandArgs,
2213
}
2314

2415
#[derive(Debug, thiserror::Error)]
2516
pub(crate) enum CommandError {
2617
#[error(transparent)]
27-
Project(#[from] icp::LoadError),
28-
29-
#[error(transparent)]
30-
Identity(#[from] identity::LoadError),
31-
32-
#[error("project does not contain an environment named '{name}'")]
33-
EnvironmentNotFound { name: String },
34-
35-
#[error(transparent)]
36-
Access(#[from] network::AccessError),
37-
38-
#[error(transparent)]
39-
Agent(#[from] agent::CreateError),
40-
41-
#[error("environment '{environment}' does not include canister '{canister}'")]
42-
EnvironmentCanister {
43-
environment: String,
44-
canister: String,
45-
},
46-
47-
#[error(transparent)]
48-
Lookup(#[from] LookupIdError),
18+
Call(#[from] ic_agent::AgentError),
4919

5020
#[error(transparent)]
51-
Status(#[from] AgentError),
21+
GetCanisterIdAndAgent(#[from] icp::context::GetCanisterIdAndAgentError),
5222
}
5323

5424
pub(crate) async fn exec(ctx: &Context, args: &InfoArgs) -> Result<(), CommandError> {
55-
// Load project
56-
let p = ctx.project.load().await?;
57-
58-
// Load identity
59-
let id = ctx.identity.load(args.identity.clone().into()).await?;
60-
61-
// Load target environment
62-
let env =
63-
p.environments
64-
.get(args.environment.name())
65-
.ok_or(CommandError::EnvironmentNotFound {
66-
name: args.environment.name().to_owned(),
67-
})?;
68-
69-
// Access network
70-
let access = ctx.network.access(&env.network).await?;
71-
72-
// Agent
73-
let agent = ctx.agent.create(id, &access.url).await?;
74-
75-
if let Some(k) = access.root_key {
76-
agent.set_root_key(k);
77-
}
78-
79-
// Ensure canister is included in the environment
80-
if !env.canisters.contains_key(&args.name) {
81-
return Err(CommandError::EnvironmentCanister {
82-
environment: env.name.to_owned(),
83-
canister: args.name.to_owned(),
84-
});
85-
}
86-
87-
// Lookup the canister id
88-
let cid = ctx.ids.lookup(&Key {
89-
network: env.network.name.to_owned(),
90-
environment: env.name.to_owned(),
91-
canister: args.name.to_owned(),
92-
})?;
25+
let selections = args.cmd_args.selections();
26+
27+
let (cid, agent) = ctx
28+
.get_canister_id_and_agent(
29+
&selections.canister,
30+
&selections.environment,
31+
&selections.network,
32+
&selections.identity,
33+
)
34+
.await?;
9335

9436
// Management Interface
9537
let mgmt = ic_utils::interfaces::ManagementCanister::create(&agent);

crates/icp-cli/src/commands/canister/install.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub(crate) enum CommandError {
7171
InstallAgent(#[from] AgentError),
7272
}
7373

74+
// TODO: Needs to take a single canister arg and change to call an operation
7475
pub(crate) async fn exec(ctx: &Context, args: &InstallArgs) -> Result<(), CommandError> {
7576
// Load the project
7677
let p = ctx.project.load().await?;

crates/icp-cli/src/commands/canister/start.rs

Lines changed: 14 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,36 @@
11
use clap::Args;
22
use ic_agent::AgentError;
3-
use icp::{agent, identity, network};
43

54
use icp::context::Context;
65

7-
use crate::options::{EnvironmentOpt, IdentityOpt};
8-
use icp::store_id::{Key, LookupError as LookupIdError};
6+
use crate::commands::args;
97

108
#[derive(Debug, Args)]
119
pub(crate) struct StartArgs {
12-
/// The name of the canister within the current project
13-
pub(crate) name: String,
14-
15-
#[command(flatten)]
16-
identity: IdentityOpt,
17-
1810
#[command(flatten)]
19-
environment: EnvironmentOpt,
11+
pub(crate) cmd_args: args::CanisterCommandArgs,
2012
}
2113

2214
#[derive(Debug, thiserror::Error)]
2315
pub(crate) enum CommandError {
2416
#[error(transparent)]
25-
Project(#[from] icp::LoadError),
26-
27-
#[error(transparent)]
28-
Identity(#[from] identity::LoadError),
29-
30-
#[error("project does not contain an environment named '{name}'")]
31-
EnvironmentNotFound { name: String },
32-
33-
#[error(transparent)]
34-
Access(#[from] network::AccessError),
35-
36-
#[error(transparent)]
37-
Agent(#[from] agent::CreateError),
38-
39-
#[error("environment '{environment}' does not include canister '{canister}'")]
40-
EnvironmentCanister {
41-
environment: String,
42-
canister: String,
43-
},
44-
45-
#[error(transparent)]
46-
LookupCanisterId(#[from] LookupIdError),
17+
Start(#[from] AgentError),
4718

4819
#[error(transparent)]
49-
Start(#[from] AgentError),
20+
GetCanisterIdAndAgent(#[from] icp::context::GetCanisterIdAndAgentError),
5021
}
5122

5223
pub(crate) async fn exec(ctx: &Context, args: &StartArgs) -> Result<(), CommandError> {
53-
// Load project
54-
let p = ctx.project.load().await?;
55-
56-
// Load identity
57-
let id = ctx.identity.load(args.identity.clone().into()).await?;
58-
59-
// Load target environment
60-
let env =
61-
p.environments
62-
.get(args.environment.name())
63-
.ok_or(CommandError::EnvironmentNotFound {
64-
name: args.environment.name().to_owned(),
65-
})?;
66-
67-
// Access network
68-
let access = ctx.network.access(&env.network).await?;
69-
70-
// Agent
71-
let agent = ctx.agent.create(id, &access.url).await?;
72-
73-
if let Some(k) = access.root_key {
74-
agent.set_root_key(k);
75-
}
76-
77-
// Ensure canister is included in the environment
78-
if !env.canisters.contains_key(&args.name) {
79-
return Err(CommandError::EnvironmentCanister {
80-
environment: env.name.to_owned(),
81-
canister: args.name.to_owned(),
82-
});
83-
}
84-
85-
// Lookup the canister id
86-
let cid = ctx.ids.lookup(&Key {
87-
network: env.network.name.to_owned(),
88-
environment: env.name.to_owned(),
89-
canister: args.name.to_owned(),
90-
})?;
24+
let selections = args.cmd_args.selections();
25+
26+
let (cid, agent) = ctx
27+
.get_canister_id_and_agent(
28+
&selections.canister,
29+
&selections.environment,
30+
&selections.network,
31+
&selections.identity,
32+
)
33+
.await?;
9134

9235
// Management Interface
9336
let mgmt = ic_utils::interfaces::ManagementCanister::create(&agent);

crates/icp-cli/src/commands/canister/stop.rs

Lines changed: 14 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,36 @@
11
use clap::Args;
22
use ic_agent::AgentError;
3-
use icp::{agent, identity, network};
43

54
use icp::context::Context;
65

7-
use crate::options::{EnvironmentOpt, IdentityOpt};
8-
use icp::store_id::{Key, LookupError as LookupIdError};
6+
use crate::commands::args;
97

108
#[derive(Debug, Args)]
119
pub(crate) struct StopArgs {
12-
/// The name of the canister within the current project
13-
pub(crate) name: String,
14-
15-
#[command(flatten)]
16-
identity: IdentityOpt,
17-
1810
#[command(flatten)]
19-
environment: EnvironmentOpt,
11+
pub(crate) cmd_args: args::CanisterCommandArgs,
2012
}
2113

2214
#[derive(Debug, thiserror::Error)]
2315
pub(crate) enum CommandError {
2416
#[error(transparent)]
25-
Project(#[from] icp::LoadError),
26-
27-
#[error(transparent)]
28-
Identity(#[from] identity::LoadError),
29-
30-
#[error("project does not contain an environment named '{name}'")]
31-
EnvironmentNotFound { name: String },
32-
33-
#[error(transparent)]
34-
Access(#[from] network::AccessError),
35-
36-
#[error(transparent)]
37-
Agent(#[from] agent::CreateError),
38-
39-
#[error("environment '{environment}' does not include canister '{canister}'")]
40-
EnvironmentCanister {
41-
environment: String,
42-
canister: String,
43-
},
44-
45-
#[error(transparent)]
46-
LookupCanisterId(#[from] LookupIdError),
17+
Stop(#[from] AgentError),
4718

4819
#[error(transparent)]
49-
Stop(#[from] AgentError),
20+
GetCanisterIdAndAgent(#[from] icp::context::GetCanisterIdAndAgentError),
5021
}
5122

5223
pub(crate) async fn exec(ctx: &Context, args: &StopArgs) -> Result<(), CommandError> {
53-
// Load project
54-
let p = ctx.project.load().await?;
55-
56-
// Load identity
57-
let id = ctx.identity.load(args.identity.clone().into()).await?;
58-
59-
// Load target environment
60-
let env =
61-
p.environments
62-
.get(args.environment.name())
63-
.ok_or(CommandError::EnvironmentNotFound {
64-
name: args.environment.name().to_owned(),
65-
})?;
66-
67-
// Access network
68-
let access = ctx.network.access(&env.network).await?;
69-
70-
// Agent
71-
let agent = ctx.agent.create(id, &access.url).await?;
72-
73-
if let Some(k) = access.root_key {
74-
agent.set_root_key(k);
75-
}
76-
77-
// Ensure canister is included in the environment
78-
if !env.canisters.contains_key(&args.name) {
79-
return Err(CommandError::EnvironmentCanister {
80-
environment: env.name.to_owned(),
81-
canister: args.name.to_owned(),
82-
});
83-
}
84-
85-
// Lookup the canister id
86-
let cid = ctx.ids.lookup(&Key {
87-
network: env.network.name.to_owned(),
88-
environment: env.name.to_owned(),
89-
canister: args.name.to_owned(),
90-
})?;
24+
let selections = args.cmd_args.selections();
25+
26+
let (cid, agent) = ctx
27+
.get_canister_id_and_agent(
28+
&selections.canister,
29+
&selections.environment,
30+
&selections.network,
31+
&selections.identity,
32+
)
33+
.await?;
9134

9235
// Management Interface
9336
let mgmt = ic_utils::interfaces::ManagementCanister::create(&agent);

0 commit comments

Comments
 (0)