Skip to content

Commit c994b61

Browse files
authored
chore: make ctx.agent, ctx.identity private (#184)
1 parent f6f0c51 commit c994b61

File tree

22 files changed

+311
-721
lines changed

22 files changed

+311
-721
lines changed

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

Lines changed: 38 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
// For now it's only used to set environment variables
33
// Eventually we will add support for canister settings operation
44

5-
use std::collections::{HashMap, HashSet};
5+
use std::collections::HashSet;
66

77
use clap::Args;
8-
use futures::{StreamExt, stream::FuturesOrdered};
8+
use futures::{StreamExt, future::try_join_all, stream::FuturesOrdered};
99
use ic_agent::AgentError;
1010
use ic_utils::interfaces::management_canister::builders::EnvironmentVariable;
11-
use icp::{agent, identity, network};
11+
use icp::{
12+
agent,
13+
context::{GetAgentForEnvError, GetCanisterIdForEnvError, GetEnvironmentError},
14+
identity, network,
15+
};
1216
use tracing::debug;
1317

1418
use icp::context::Context;
@@ -17,8 +21,8 @@ use crate::{
1721
options::{EnvironmentOpt, IdentityOpt},
1822
progress::{ProgressManager, ProgressManagerSettings},
1923
};
20-
use icp::store_artifact::LookupError as LookupArtifactError;
21-
use icp::store_id::{Key, LookupError as LookupIdError};
24+
use icp::store_artifact::LookupArtifactError;
25+
use icp::store_id::LookupIdError;
2226

2327
#[derive(Clone, Debug, Args)]
2428
pub(crate) struct BindingArgs {
@@ -40,27 +44,12 @@ pub(crate) enum CommandError {
4044
#[error(transparent)]
4145
Identity(#[from] identity::LoadError),
4246

43-
#[error("project does not contain an environment named '{name}'")]
44-
EnvironmentNotFound { name: String },
45-
4647
#[error(transparent)]
4748
Access(#[from] network::AccessError),
4849

4950
#[error(transparent)]
5051
Agent(#[from] agent::CreateError),
5152

52-
#[error("project does not contain a canister named '{name}'")]
53-
CanisterNotFound { name: String },
54-
55-
#[error("no canisters available to install")]
56-
NoCanisters,
57-
58-
#[error("environment '{environment}' does not include canister '{canister}'")]
59-
EnvironmentCanister {
60-
environment: String,
61-
canister: String,
62-
},
63-
6453
#[error("Could not find canister id(s) for '{}' in environment '{environment}' make sure they are created first", canister_names.join(", "))]
6554
CanisterNotCreated {
6655
environment: String,
@@ -75,66 +64,43 @@ pub(crate) enum CommandError {
7564

7665
#[error(transparent)]
7766
InstallAgent(#[from] AgentError),
78-
}
7967

80-
pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), CommandError> {
81-
// Load the project
82-
let p = ctx.project.load().await?;
68+
#[error(transparent)]
69+
GetAgentForEnv(#[from] GetAgentForEnvError),
8370

84-
// Load identity
85-
let id = ctx.identity.load(args.identity.clone().into()).await?;
71+
#[error(transparent)]
72+
GetEnvironment(#[from] GetEnvironmentError),
8673

87-
// Load target environment
88-
let env =
89-
p.environments
90-
.get(args.environment.name())
91-
.ok_or(CommandError::EnvironmentNotFound {
92-
name: args.environment.name().to_owned(),
93-
})?;
74+
#[error(transparent)]
75+
GetCanisterIdForEnv(#[from] GetCanisterIdForEnvError),
76+
}
9477

95-
// Access network
96-
let access = ctx.network.access(&env.network).await?;
78+
pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), CommandError> {
79+
// Load target environment
80+
let env = ctx.get_environment(args.environment.name()).await?;
9781

9882
// Agent
99-
let agent = ctx.agent.create(id, &access.url).await?;
100-
101-
if let Some(k) = access.root_key {
102-
agent.set_root_key(k);
103-
}
83+
let agent = ctx
84+
.get_agent_for_env(&args.identity.clone().into(), args.environment.name())
85+
.await?;
10486

105-
let cnames = match args.names.is_empty() {
106-
// No canisters specified
107-
true => env.canisters.keys().cloned().collect(),
108-
109-
// Individual canisters specified
87+
let target_canisters = match args.names.is_empty() {
88+
true => env.get_canister_names(),
11089
false => args.names.clone(),
11190
};
11291

113-
for name in &cnames {
114-
if !p.canisters.contains_key(name) {
115-
return Err(CommandError::CanisterNotFound {
116-
name: name.to_owned(),
117-
});
118-
}
119-
120-
if !env.canisters.contains_key(name) {
121-
return Err(CommandError::EnvironmentCanister {
122-
environment: env.name.to_owned(),
123-
canister: name.to_owned(),
124-
});
92+
let env_canisters = &env.canisters;
93+
let canisters = try_join_all(target_canisters.into_iter().map(|name| {
94+
let env_name = args.environment.name();
95+
async move {
96+
let cid = ctx.get_canister_id_for_env(&name, env_name).await?;
97+
let (_, info) = env_canisters
98+
.get(&name)
99+
.expect("Canister id exists but no canister info");
100+
Ok::<_, CommandError>((name, cid, info))
125101
}
126-
}
127-
128-
let cs = env
129-
.canisters
130-
.iter()
131-
.filter(|(k, _)| cnames.contains(k))
132-
.collect::<HashMap<_, _>>();
133-
134-
// Ensure at least one canister has been selected
135-
if cs.is_empty() {
136-
return Err(CommandError::NoCanisters);
137-
}
102+
}))
103+
.await?;
138104

139105
// Management Interface
140106
let mgmt = ic_utils::interfaces::ManagementCanister::create(&agent);
@@ -179,9 +145,9 @@ pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), Comman
179145
.map(|(n, p)| (format!("PUBLIC_CANISTER_ID:{n}"), p.to_text()))
180146
.collect::<Vec<(_, _)>>();
181147

182-
for (_, (_, c)) in cs {
148+
for (name, cid, info) in canisters {
183149
// Create progress bar with standard configuration
184-
let pb = progress_manager.create_progress_bar(&c.name);
150+
let pb = progress_manager.create_progress_bar(&name);
185151

186152
// Create an async closure that handles the operation for this specific canister
187153
let settings_fn = {
@@ -193,15 +159,8 @@ pub(crate) async fn exec(ctx: &Context, args: &BindingArgs) -> Result<(), Comman
193159
// Indicate to user that the canister's environment variables are being set
194160
pb.set_message("Updating environment variables...");
195161

196-
// Lookup the canister id
197-
let cid = ctx.ids.lookup(&Key {
198-
network: env.network.name.to_owned(),
199-
environment: env.name.to_owned(),
200-
canister: c.name.to_owned(),
201-
})?;
202-
203162
// Load the variables from the config files
204-
let mut environment_variables = c
163+
let mut environment_variables = info
205164
.settings
206165
.environment_variables
207166
.to_owned()

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

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ use candid::{Decode, Encode, Nat};
55
use clap::Args;
66
use futures::{StreamExt, stream::FuturesOrdered};
77
use ic_agent::{Agent, AgentError, export::Principal};
8-
use icp::{agent, identity, network, prelude::*};
8+
use icp::{
9+
agent,
10+
context::{GetAgentForEnvError, GetEnvironmentError},
11+
identity, network,
12+
prelude::*,
13+
};
914
use icp_canister_interfaces::{
1015
cycles_ledger::{
1116
CYCLES_LEDGER_PRINCIPAL, CanisterSettingsArg, CreateCanisterArgs, CreateCanisterResponse,
@@ -22,7 +27,7 @@ use crate::{
2227
options::{EnvironmentOpt, IdentityOpt},
2328
progress::{ProgressManager, ProgressManagerSettings},
2429
};
25-
use icp::store_id::{Key, LookupError, RegisterError};
30+
use icp::store_id::{Key, LookupIdError, RegisterError};
2631

2732
pub(crate) const DEFAULT_CANISTER_CYCLES: u128 = 2 * TRILLION;
2833

@@ -85,9 +90,6 @@ pub(crate) enum CommandError {
8590
#[error(transparent)]
8691
Identity(#[from] identity::LoadError),
8792

88-
#[error("project does not contain an environment named '{name}'")]
89-
EnvironmentNotFound { name: String },
90-
9193
#[error(transparent)]
9294
Access(#[from] network::AccessError),
9395

@@ -103,9 +105,6 @@ pub(crate) enum CommandError {
103105
canister: String,
104106
},
105107

106-
#[error("no canisters available to create")]
107-
NoCanisters,
108-
109108
#[error("canister exists already: {principal}")]
110109
CanisterExists { principal: Principal },
111110

@@ -126,6 +125,12 @@ pub(crate) enum CommandError {
126125

127126
#[error(transparent)]
128127
Unexpected(#[from] anyhow::Error),
128+
129+
#[error(transparent)]
130+
GetAgentForEnv(#[from] GetAgentForEnvError),
131+
132+
#[error(transparent)]
133+
GetEnvironment(#[from] GetEnvironmentError),
129134
}
130135

131136
// Creates canister(s) by asking the cycles ledger to create them.
@@ -135,27 +140,15 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
135140
// Load project
136141
let p = ctx.project.load().await?;
137142

138-
// Load identity
139-
let id = ctx.identity.load(args.identity.clone().into()).await?;
140-
141143
// Load target environment
142-
let env =
143-
p.environments
144-
.get(args.environment.name())
145-
.ok_or(CommandError::EnvironmentNotFound {
146-
name: args.environment.name().to_owned(),
147-
})?;
148-
149-
// Collect environment canisters
150-
let cnames = match args.names.is_empty() {
151-
// No canisters specified
152-
true => env.canisters.keys().cloned().collect(),
153-
154-
// Individual canisters specified
144+
let env = ctx.get_environment(args.environment.name()).await?;
145+
146+
let target_canisters = match args.names.is_empty() {
147+
true => env.get_canister_names(),
155148
false => args.names.clone(),
156149
};
157150

158-
for name in &cnames {
151+
for name in &target_canisters {
159152
if !p.canisters.contains_key(name) {
160153
return Err(CommandError::CanisterNotFound {
161154
name: name.to_owned(),
@@ -170,17 +163,12 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
170163
}
171164
}
172165

173-
let cs = env
166+
let canister_infos = env
174167
.canisters
175168
.iter()
176-
.filter(|(k, _)| cnames.contains(k))
169+
.filter(|(k, _)| target_canisters.contains(k))
177170
.collect::<HashMap<_, _>>();
178171

179-
// Ensure at least one canister has been selected
180-
if cs.is_empty() {
181-
return Err(CommandError::NoCanisters);
182-
}
183-
184172
// Do we have any already existing canisters?
185173
let cexist: Vec<_> = env
186174
.canisters
@@ -196,15 +184,10 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
196184
})
197185
.collect();
198186

199-
// Access network
200-
let access = ctx.network.access(&env.network).await?;
201-
202187
// Agent
203-
let agent = ctx.agent.create(id, &access.url).await?;
204-
205-
if let Some(k) = access.root_key {
206-
agent.set_root_key(k);
207-
}
188+
let agent = ctx
189+
.get_agent_for_env(&args.identity.clone().into(), args.environment.name())
190+
.await?;
208191

209192
// Select which subnet to deploy the canisters to
210193
//
@@ -241,9 +224,10 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
241224

242225
let progress_manager = ProgressManager::new(ProgressManagerSettings { hidden: ctx.debug });
243226

244-
for (_, c) in cs.values() {
227+
let env_ref = &env;
228+
for (name, (_path, info)) in canister_infos.iter() {
245229
// Create progress bar with standard configuration
246-
let pb = progress_manager.create_progress_bar(&c.name);
230+
let pb = progress_manager.create_progress_bar(name);
247231

248232
// Create an async closure that handles the operation for this specific canister
249233
let create_fn = {
@@ -257,9 +241,9 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
257241

258242
// Create canister-network association-key
259243
let k = Key {
260-
network: env.network.name.to_owned(),
261-
environment: env.name.to_owned(),
262-
canister: c.name.to_owned(),
244+
network: env_ref.network.name.to_owned(),
245+
environment: env_ref.name.to_owned(),
246+
canister: name.to_string(),
263247
};
264248

265249
match ctx.ids.lookup(&k) {
@@ -269,7 +253,7 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
269253
}
270254

271255
// Doesn't exist (include)
272-
Err(LookupError::IdNotFound { .. }) => {}
256+
Err(LookupIdError::IdNotFound { .. }) => {}
273257

274258
// Lookup failed
275259
Err(err) => panic!("{err}"),
@@ -280,7 +264,7 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
280264
freezing_threshold: cmd
281265
.settings
282266
.freezing_threshold
283-
.or(c.settings.freezing_threshold)
267+
.or(info.settings.freezing_threshold)
284268
.map(Nat::from),
285269

286270
controllers: if cmd.controller.is_empty() {
@@ -292,19 +276,19 @@ pub(crate) async fn exec(ctx: &Context, args: &CreateArgs) -> Result<(), Command
292276
reserved_cycles_limit: cmd
293277
.settings
294278
.reserved_cycles_limit
295-
.or(c.settings.reserved_cycles_limit)
279+
.or(info.settings.reserved_cycles_limit)
296280
.map(Nat::from),
297281

298282
memory_allocation: cmd
299283
.settings
300284
.memory_allocation
301-
.or(c.settings.memory_allocation)
285+
.or(info.settings.memory_allocation)
302286
.map(Nat::from),
303287

304288
compute_allocation: cmd
305289
.settings
306290
.compute_allocation
307-
.or(c.settings.compute_allocation)
291+
.or(info.settings.compute_allocation)
308292
.map(Nat::from),
309293
};
310294

0 commit comments

Comments
 (0)