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
19 changes: 13 additions & 6 deletions crates/icp-cli/src/commands/canister/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::anyhow;
use candid::{Nat, Principal};
use clap::{ArgGroup, Args, Parser};
use icp::context::Context;
use icp::parsers::{CyclesAmount, MemoryAmount};
use icp::parsers::{CyclesAmount, DurationAmount, MemoryAmount};
use icp::{Canister, context::CanisterSelection, prelude::*};
use icp_canister_interfaces::cycles_ledger::CanisterSettingsArg;

Expand All @@ -21,9 +21,11 @@ pub(crate) struct CanisterSettings {
#[arg(long)]
pub(crate) memory_allocation: Option<MemoryAmount>,

/// Optional freezing threshold in seconds. Controls how long a canister can be inactive before being frozen.
/// Optional freezing threshold. Controls how long a canister can be inactive before being frozen.
/// Supports duration suffixes: s (seconds), m (minutes), h (hours), d (days), w (weeks).
/// A bare number is treated as seconds.
#[arg(long)]
pub(crate) freezing_threshold: Option<u64>,
pub(crate) freezing_threshold: Option<DurationAmount>,

/// Optional upper limit on cycles reserved for future resource payments.
/// Memory allocations that would push the reserved balance above this limit will fail.
Expand Down Expand Up @@ -96,8 +98,9 @@ impl CreateArgs {
freezing_threshold: self
.settings
.freezing_threshold
.or(default.settings.freezing_threshold)
.map(Nat::from),
.clone()
.or(default.settings.freezing_threshold.clone())
.map(|d| Nat::from(d.get())),
controllers: if self.controller.is_empty() {
None
} else {
Expand Down Expand Up @@ -127,7 +130,11 @@ impl CreateArgs {

pub(crate) fn canister_settings(&self) -> CanisterSettingsArg {
CanisterSettingsArg {
freezing_threshold: self.settings.freezing_threshold.map(Nat::from),
freezing_threshold: self
.settings
.freezing_threshold
.clone()
.map(|d| Nat::from(d.get())),
controllers: if self.controller.is_empty() {
None
} else {
Expand Down
20 changes: 8 additions & 12 deletions crates/icp-cli/src/commands/canister/settings/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ic_agent::export::Principal;
use ic_management_canister_types::{CanisterStatusResult, EnvironmentVariable, LogVisibility};
use icp::ProjectLoadError;
use icp::context::{CanisterSelection, Context, TermWriter};
use icp::parsers::{CyclesAmount, MemoryAmount};
use icp::parsers::{CyclesAmount, DurationAmount, MemoryAmount};
use std::collections::{HashMap, HashSet};
use std::io::Write;

Expand Down Expand Up @@ -100,8 +100,11 @@ pub(crate) struct UpdateArgs {
#[arg(long)]
memory_allocation: Option<MemoryAmount>,

#[arg(long, value_parser = freezing_threshold_parser)]
freezing_threshold: Option<u64>,
/// Freezing threshold. Controls how long a canister can be inactive before being frozen.
/// Supports duration suffixes: s (seconds), m (minutes), h (hours), d (days), w (weeks).
/// A bare number is treated as seconds.
#[arg(long)]
freezing_threshold: Option<DurationAmount>,

/// Upper limit on cycles reserved for future resource payments.
/// Memory allocations that would push the reserved balance above this limit will fail.
Expand Down Expand Up @@ -231,13 +234,13 @@ pub(crate) async fn exec(ctx: &Context, args: &UpdateArgs) -> Result<(), anyhow:
}
update = update.with_memory_allocation(memory_allocation.get());
}
if let Some(freezing_threshold) = args.freezing_threshold {
if let Some(freezing_threshold) = &args.freezing_threshold {
if configured_settings.freezing_threshold.is_some() {
ctx.term.write_line(
"Warning: Freezing threshold is already set in icp.yaml; this new value will be overridden on next settings sync"
)?
}
update = update.with_freezing_threshold(freezing_threshold);
update = update.with_freezing_threshold(freezing_threshold.get());
}
if let Some(reserved_cycles_limit) = &args.reserved_cycles_limit {
if configured_settings.reserved_cycles_limit.is_some() {
Expand Down Expand Up @@ -288,13 +291,6 @@ fn compute_allocation_parser(compute_allocation: &str) -> Result<u8, String> {
Err("Must be a percent between 0 and 100".to_string())
}

fn freezing_threshold_parser(freezing_threshold: &str) -> Result<u64, String> {
if let Ok(num) = freezing_threshold.parse::<u64>() {
return Ok(num);
}
Err("Must be a value between 0..2^64-1 inclusive".to_string())
}

fn log_visibility_parser(log_visibility: &str) -> Result<LogVisibility, String> {
match log_visibility {
"public" => Ok(LogVisibility::Public),
Expand Down
9 changes: 6 additions & 3 deletions crates/icp-cli/src/operations/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub(crate) async fn sync_settings(
ref log_visibility,
compute_allocation,
ref memory_allocation,
freezing_threshold,
ref freezing_threshold,
ref reserved_cycles_limit,
ref wasm_memory_limit,
ref wasm_memory_threshold,
Expand Down Expand Up @@ -119,7 +119,10 @@ pub(crate) async fn sync_settings(
.as_ref()
.map(|m| m.get())
.is_none_or(|s| current_settings.memory_allocation.0.to_u64() == Some(s))
&& freezing_threshold.is_none_or(|s| s == current_settings.freezing_threshold)
&& freezing_threshold
.as_ref()
.map(|d| d.get())
.is_none_or(|s| s == current_settings.freezing_threshold)
&& reserved_cycles_limit
.as_ref()
.is_none_or(|s| s.get() == current_settings.reserved_cycles_limit)
Expand All @@ -142,7 +145,7 @@ pub(crate) async fn sync_settings(
.with_optional_log_visibility(log_visibility_setting)
.with_optional_compute_allocation(compute_allocation)
.with_optional_memory_allocation(memory_allocation.as_ref().map(|m| m.get()))
.with_optional_freezing_threshold(freezing_threshold)
.with_optional_freezing_threshold(freezing_threshold.as_ref().map(|d| d.get()))
.with_optional_reserved_cycles_limit(reserved_cycles_limit.as_ref().map(|r| r.get()))
.with_optional_wasm_memory_limit(wasm_memory_limit.as_ref().map(|m| m.get()))
.with_optional_wasm_memory_threshold(wasm_memory_threshold.as_ref().map(|m| m.get()))
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/tests/canister_create_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ async fn canister_create_with_settings() {
log_visibility: public
compute_allocation: 1
memory_allocation: 4294967296
freezing_threshold: 2592000
freezing_threshold: 30d
reserved_cycles_limit: 1000000000000

{NETWORK_RANDOM_PORT}
Expand Down
2 changes: 1 addition & 1 deletion crates/icp-cli/tests/canister_settings_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ async fn canister_settings_update_miscellaneous() {
"--memory-allocation",
"6GiB",
"--freezing-threshold",
"8640000",
"100d",
"--reserved-cycles-limit",
"6t",
"--wasm-memory-limit",
Expand Down
7 changes: 4 additions & 3 deletions crates/icp/src/canister/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use icp_canister_interfaces::cycles_ledger::CanisterSettingsArg;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::parsers::{CyclesAmount, MemoryAmount};
use crate::parsers::{CyclesAmount, DurationAmount, MemoryAmount};

pub mod build;
pub mod recipe;
Expand Down Expand Up @@ -214,7 +214,8 @@ pub struct Settings {
pub memory_allocation: Option<MemoryAmount>,

/// Freezing threshold in seconds. Controls how long a canister can be inactive before being frozen.
pub freezing_threshold: Option<u64>,
/// Supports duration suffixes in YAML: s, m, h, d, w (e.g. "30d" or "4w").
pub freezing_threshold: Option<DurationAmount>,

/// Upper limit on cycles reserved for future resource payments.
/// Memory allocations that would push the reserved balance above this limit will fail.
Expand All @@ -239,7 +240,7 @@ pub struct Settings {
impl From<Settings> for CanisterSettingsArg {
fn from(settings: Settings) -> Self {
CanisterSettingsArg {
freezing_threshold: settings.freezing_threshold.map(Nat::from),
freezing_threshold: settings.freezing_threshold.map(|d| Nat::from(d.get())),
controllers: None,
reserved_cycles_limit: settings.reserved_cycles_limit.map(|c| Nat::from(c.get())),
log_visibility: settings.log_visibility.map(Into::into),
Expand Down
Loading
Loading