Skip to content

Commit

Permalink
feat: custom canister types
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Nowak-Liebiediew committed Oct 25, 2023
1 parent a302661 commit 08bc7c5
Show file tree
Hide file tree
Showing 11 changed files with 423 additions and 20 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dialoguer = "0.10.0"
directories-next = "2.0.0"
flate2 = { version = "1.0.11", default-features = false }
futures = "0.3.21"
handlebars = "4.3.3"
hex = "0.4.3"
humantime = "2.1.0"
itertools = "0.10.3"
Expand All @@ -48,6 +49,13 @@ mime_guess = "2.0.4"
num-traits = "0.2.14"
pem = "1.0.2"
proptest = "1.0.0"
regex = "1.5.5"
reqwest = { version = "0.11.9", default-features = false, features = [
"blocking",
"json",
"rustls-tls",
"native-tls-vendored",
]}
ring = "0.16.11"
schemars = "0.8"
sec1 = "0.3.0"
Expand Down
57 changes: 57 additions & 0 deletions e2e/tests-dfx/extension.bash
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,60 @@ EOF
assert_command dfx extension run test_extension abc --the-another-param 464646 --the-param 123 456 789
assert_eq "abc --the-another-param 464646 --the-param 123 456 789 --dfx-cache-path $CACHE_DIR"
}

@test "custom canister types" {
dfx cache install

CACHE_DIR=$(dfx cache show)
mkdir -p "$CACHE_DIR"/extensions/playground
echo '#!/usr/bin/env bash
echo testoutput' > "$CACHE_DIR"/extensions/playground/playground
chmod +x "$CACHE_DIR"/extensions/playground/playground

echo '{
"name": "playground",
"version": "0.1.0",
"homepage": "https://github.com/dfinity/playground",
"authors": "DFINITY",
"summary": "Motoko playground for the Internet Computer",
"categories": [],
"keywords": [],
"subcommands": {},
"canister_types": {
"playground": {
"type": "custom",
"build": "echo the wasm-utils canister is prebuilt",
"candid": "{{canister_name}}.did",
"wasm": "{{canister_name}}.wasm"
}
}
}' > "$CACHE_DIR"/extensions/playground/extension.json

assert_command dfx extension list
assert_match "playground"

dfx_new hello
create_networks_json
install_asset playground_backend

echo '{
"canisters": {
"wasm-utils": {
"type": "playground"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}' > dfx.json

dfx_start
assert_command dfx deploy -v
assert_match 'Backend canister via Candid interface'
}
4 changes: 3 additions & 1 deletion src/dfx-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ clap = { workspace = true, features = ["string"] }
dialoguer = "0.10.0"
directories-next.workspace = true
flate2 = { workspace = true, default-features = false, features = ["zlib-ng"] }
handlebars.workspace = true
hex = { workspace = true, features = ["serde"] }
humantime-serde = "1.1.1"
ic-agent = { workspace = true, features = ["reqwest"] }
Expand All @@ -26,7 +27,8 @@ ic-identity-hsm = { workspace = true }
k256 = { version = "0.11.4", features = ["pem"] }
keyring.workspace = true
lazy_static.workspace = true
reqwest = { version = "0.11.9", features = ["blocking", "json"] }
reqwest = { workspace = true, features = ["blocking", "json"] }
regex.workspace = true
ring.workspace = true
schemars.workspace = true
sec1 = { workspace = true, features = ["std"] }
Expand Down
84 changes: 72 additions & 12 deletions src/dfx-core/src/config/model/dfinity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::error::dfx_config::{
GetComputeAllocationError, GetFreezingThresholdError, GetMemoryAllocationError,
GetPullCanistersError, GetRemoteCanisterIdError, GetReservedCyclesLimitError,
};
use crate::error::extension::ExtensionError;
use crate::error::load_dfx_config::LoadDfxConfigError;
use crate::error::load_dfx_config::LoadDfxConfigError::{
DetermineCurrentWorkingDirFailed, LoadFromFileFailed, ResolveConfigPathFailed,
Expand Down Expand Up @@ -950,42 +951,64 @@ impl Config {
Ok(None)
}

fn from_file(path: &Path) -> Result<Config, StructuredFileError> {
fn from_file(
path: &Path,
dfx_version: &semver::Version,
) -> Result<Config, StructuredFileError> {
let content = crate::fs::read(path).map_err(ReadJsonFileFailed)?;
Config::from_slice(path.to_path_buf(), &content)
Config::from_slice(path.to_path_buf(), &content, dfx_version)
}

pub fn from_dir(working_dir: &Path) -> Result<Option<Config>, LoadDfxConfigError> {
pub fn from_dir(
working_dir: &Path,
dfx_version: &semver::Version,
) -> Result<Option<Config>, LoadDfxConfigError> {
let path = Config::resolve_config_path(working_dir)?;
path.map(|path| Config::from_file(&path))
path.map(|path| Config::from_file(&path, dfx_version))
.transpose()
.map_err(LoadFromFileFailed)
}

pub fn from_current_dir() -> Result<Option<Config>, LoadDfxConfigError> {
Config::from_dir(&std::env::current_dir().map_err(DetermineCurrentWorkingDirFailed)?)
pub fn from_current_dir(
dfx_version: &semver::Version,
) -> Result<Option<Config>, LoadDfxConfigError> {
Config::from_dir(
&std::env::current_dir().map_err(DetermineCurrentWorkingDirFailed)?,
dfx_version,
)
}

fn from_slice(path: PathBuf, content: &[u8]) -> Result<Config, StructuredFileError> {
let config = serde_json::from_slice(content)
fn from_slice(
path: PathBuf,
content: &[u8],
dfx_version: &semver::Version,
) -> Result<Config, StructuredFileError> {
let mut json: serde_json::Value = serde_json::from_slice(content)
.map_err(|e| DeserializeJsonFileFailed(Box::new(path.clone()), e))?;
let json = serde_json::from_slice(content)
let extension_manager =
crate::extension::manager::ExtensionManager::new(&dfx_version).unwrap();
transform_via_extension(&mut json, extension_manager).unwrap(); // TODO
let config = serde_json::from_value(json.clone())
.map_err(|e| DeserializeJsonFileFailed(Box::new(path.clone()), e))?;
Ok(Config { path, json, config })
}

/// Create a configuration from a string.
#[cfg(test)]
pub(crate) fn from_str(content: &str) -> Result<Config, StructuredFileError> {
Config::from_slice(PathBuf::from("-"), content.as_bytes())
pub(crate) fn from_str(
content: &str,
dfx_version: &semver::Version,
) -> Result<Config, StructuredFileError> {
Config::from_slice(PathBuf::from("-"), content.as_bytes(), dfx_version)
}

#[cfg(test)]
pub(crate) fn from_str_and_path(
path: PathBuf,
content: &str,
dfx_version: &semver::Version,
) -> Result<Config, StructuredFileError> {
Config::from_slice(path, content.as_bytes())
Config::from_slice(path, content.as_bytes(), dfx_version)
}

pub fn get_path(&self) -> &PathBuf {
Expand Down Expand Up @@ -1018,6 +1041,37 @@ impl Config {
}
}

fn transform_via_extension(
json: &mut Value,
extension_manager: crate::extension::manager::ExtensionManager,
) -> Result<(), ExtensionError> {
if let Some(canisters) = json
.get_mut("canisters")
.map(|v| v.as_object_mut())
.flatten()
{
for (canister_name, canister_declaration) in canisters.iter_mut() {
if let Some(canister_type) = canister_declaration.get("type").cloned() {
if !["rust", "motoko", "custom", "assets", "pull"]
.contains(&canister_type.as_str().unwrap_or_default())
// TODO
{
let canister_type = canister_type.as_str().unwrap_or_default();
let canister_declaration = canister_declaration.as_object_mut().unwrap();
let new = crate::extension::manifest::custom_canister_type::transform(
&extension_manager,
canister_name,
canister_type,
canister_declaration,
)?;
*canister_declaration = new;
}
}
}
}
Ok(())
}

// grumble grumble https://github.com/serde-rs/serde/issues/2231
impl<'de> Deserialize<'de> for CanisterTypeProperties {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
Expand Down Expand Up @@ -1203,6 +1257,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

Expand All @@ -1225,6 +1280,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

Expand All @@ -1246,6 +1302,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

Expand All @@ -1268,6 +1325,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

Expand Down Expand Up @@ -1301,6 +1359,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

Expand All @@ -1324,6 +1383,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();
let config_interface = config_no_values.get_config();
Expand Down
Loading

0 comments on commit 08bc7c5

Please sign in to comment.