diff --git a/.gitignore b/.gitignore index 8fa347c3..ef660c28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies -/node_modules +node_modules /.pnp .pnp.js @@ -12,6 +12,7 @@ .dfx /build target/ +*.env # misc .DS_Store diff --git a/service/pool/Main.mo b/service/pool/Main.mo index 8e7cb2f8..677a8e39 100644 --- a/service/pool/Main.mo +++ b/service/pool/Main.mo @@ -132,15 +132,11 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { return true; }; - // Combine create_canister and install_code into a single update call. If no_uninstall is set, args should be null, and returns the current available canister id. - public shared ({ caller }) func deployCanister(opt_info: ?Types.CanisterInfo, args: ?Types.DeployArgs) : async Types.CanisterInfo { + // Combine create_canister and install_code into a single update call. Returns the current available canister id. + public shared ({ caller }) func deployCanister(opt_info: ?Types.CanisterInfo, args: ?Types.DeployArgs) : async (Types.CanisterInfo, {#install; #upgrade; #reinstall}) { if (not Principal.isController(caller)) { throw Error.reject "Only called by controller"; }; - let no_uninstall = Option.get(params.no_uninstall, false); - if (no_uninstall and Option.isSome(args)) { - throw Error.reject "Cannot specify args when no_uninstall is set"; - }; let origin = { origin = "admin"; tags = [] }; let (info, mode) = switch (opt_info) { case null { await* getExpiredCanisterInfo(origin) }; @@ -164,7 +160,13 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { }; case null {}; }; - info + switch (pool.refresh(info, false)) { + case (?newInfo) { + updateTimer(newInfo); + (newInfo, mode); + }; + case null { throw Error.reject "Cannot find canister" }; + }; }; public shared ({ caller }) func getCanisterId(nonce : PoW.Nonce, origin : Logs.Origin) : async Types.CanisterInfo { @@ -280,6 +282,17 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { stats := Logs.updateStats(stats, #mismatch); }; }; + public shared({caller}) func releaseAllCanisters() : async () { + if (not Principal.isController(caller)) { + throw Error.reject "only called by controllers"; + }; + for (info in pool.getAllCanisters()) { + if (not Option.get(params.no_uninstall, false)) { + await IC.uninstall_code { canister_id = info.id }; + }; + ignore pool.retire info; + }; + }; public func GCCanisters() { for (id in pool.gcList().vals()) { @@ -490,6 +503,7 @@ shared (creator) actor class Self(opt_params : ?Types.InitParams) = this { #http_request : Any; #installCode : Any; #deployCanister : Any; + #releaseAllCanisters : Any; #removeCode : Any; #resetStats : Any; #mergeTags : Any; diff --git a/service/pool/Types.mo b/service/pool/Types.mo index 57eddc6f..74f3b747 100644 --- a/service/pool/Types.mo +++ b/service/pool/Types.mo @@ -178,6 +178,9 @@ module { }; result }; + public func getAllCanisters() : Iter.Iter { + tree.entries(); + }; public func share() : ([CanisterInfo], [(Principal, (Int, Bool))], [(Principal, [Principal])], [CanisterInfo]) { let stableInfos = Iter.toArray(tree.entries());