Non-Interactive Script
This script is a simplified and automated way to manage your canisters (install, reinstall, or upgrade) using the CLI with minimal setup. However, before using it, you must modify the script to suit your specific use case. Here's what you need to update:
What You Need to Modify
-
Root Canister ID:
- Replace the placeholder
ROOT_CANISTER_ID=""
with the principal ID of your root canister. The root canister is the one that manages the other canisters.
- Replace the placeholder
-
Target Canister ID:
- Replace the placeholder
CANISTER_ID=""
with the principal ID of the canister you want to manage (install, reinstall, or upgrade).
- Replace the placeholder
-
WASM Module Path:
- Update the variable
WASM_MODULE_PATH="wasm/path-to-wasm.wasm.gz"
with the correct path to the WASM module you want to deploy to the target canister.
- Update the variable
Choosing the Operation
The script supports the following operations:
-
Reinstall:
./scripts/upgrade_canister.sh reinstall '(record { field1 = value1; field2 = value2 })'
-
Install:
./scripts/upgrade_canister.sh install '(record { field1 = value1; field2 = value2 })'
-
Upgrade:
./scripts/upgrade_canister.sh upgrade '(record { field1 = value1; field2 = value2 })'
Steps to Use the Script
-
Modify the Script:
- Open the script in a text editor.
- Update
ROOT_CANISTER_ID
,CANISTER_ID
, andWASM_MODULE_PATH
with the appropriate values for your project.
-
Run the Script:
- Execute the script with the desired operation and optional Candid arguments:
./scripts/upgrade_canister.sh install '(record { field1 = value1; field2 = value2 })'
- If no arguments are required, pass
(null)
:./scripts/upgrade_canister.sh upgrade '(null)'
- Execute the script with the desired operation and optional Candid arguments:
The Script
#!/bin/bash
# Variables
ROOT_CANISTER_ID="aaaaa-aa" # Toolkit root canister ID
CANISTER_ID="aaaaa-aa" # Target canister ID
WASM_MODULE_PATH="PATH_TO_WASM.wasm.gz" # Path to the WASM module file
REPL_SCRIPT="upgrade_canister.repl" # Temporary ic-repl script file
TEMP_PEM_FILE="temp_identity.pem" # Temporary PEM file for the identity
IDENTITY=$(dfx identity whoami) # Get the current DFX identity name
# Helper function to display usage
usage() {
echo "Usage: $0 <operation> [candid_arguments]"
echo "Example: $0 install '(record { field1 = value1; field2 = \"value2\" })'"
exit 1
}
# Helper function to clean up temporary files
cleanup() {
rm -f "$REPL_SCRIPT" "$TEMP_PEM_FILE"
}
# Validate arguments
if [[ $# -lt 1 ]]; then
usage
fi
# Parse arguments
OPERATION=$1
CANDID_ARGS=${2:-"(null)"} # Default to (null) if no Candid arguments are provided
# Validate operation
if [[ "$OPERATION" != "install" && "$OPERATION" != "upgrade" && "$OPERATION" != "reinstall" ]]; then
echo "Invalid operation: $OPERATION. Valid options are: install, upgrade, reinstall."
exit 1
fi
# Check if the WASM file exists
if [[ ! -f "$WASM_MODULE_PATH" ]]; then
echo "Error: WASM module not found at $WASM_MODULE_PATH."
exit 1
fi
# Check governance status
GOV_STATUS=$(dfx canister call $ROOT_CANISTER_ID --ic get_config --output json | jq -r '.Ok.governance_enabled')
if [[ $? -ne 0 ]]; then
echo "Error: Failed to check governance status."
exit 1
fi
echo "Governance status: $GOV_STATUS"
# Export the current identity
dfx identity export "$IDENTITY" > "$TEMP_PEM_FILE"
if [[ $? -ne 0 ]]; then
echo "Error: Failed to export identity for '$IDENTITY'. Ensure DFX is properly configured."
cleanup
exit 1
fi
# Encode the Candid arguments
ENCODED_ARGS=$(didc encode "$CANDID_ARGS" --format blob)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to encode Candid arguments. Please check the syntax."
cleanup
exit 1
fi
# Generate ic-repl script based on governance status
if [[ "$GOV_STATUS" == "true" ]]; then
echo "Governance is enabled. Using create_proposal."
POST_PROPOSAL=$(cat <<EOF
(record {
title = "$OPERATION canister";
summary = "Proposal to $OPERATION canister $CANISTER_ID.";
url = "";
action = variant {
ManageCanister = variant {
Upgrade = record {
mode = variant { $OPERATION };
canister_id = principal "$CANISTER_ID";
wasm = file("$WASM_MODULE_PATH");
args = opt $ENCODED_ARGS;
}
}
}
})
EOF
)
cat > "$REPL_SCRIPT" <<EOF
#!/usr/bin/ic-repl
identity file("$TEMP_PEM_FILE");
let root_canister = principal "$ROOT_CANISTER_ID";
call root_canister.create_proposal($POST_PROPOSAL);
EOF
echo "Proposal form canister $OPERATION created successfully."
else
echo "Governance is not enabled. Proceeding with ${OPERATION}_canister."
cat > "$REPL_SCRIPT" <<EOF
#!/usr/bin/ic-repl
identity file("$TEMP_PEM_FILE");
let root_canister = principal "$ROOT_CANISTER_ID";
let canister_id = principal "$CANISTER_ID";
let wasm_blob = file("$WASM_MODULE_PATH");
let args_blob = $ENCODED_ARGS;
call root_canister.${OPERATION}_canister(canister_id, wasm_blob, opt args_blob);
EOF
echo "$OPERATION operation completed successfully."
fi
# Execute the ic-repl script
echo "Executing $OPERATION on canister $CANISTER_ID..."
ic-repl -r ic "$REPL_SCRIPT"
# Clean up temporary files
cleanup
echo "Script execution completed."
Notes
- The script dynamically generates and runs an
ic-repl
script for the specified operation. - It validates the inputs and ensures dependencies are installed before execution.
- Ideal for automating repetitive canister management tasks in CI/CD pipelines.