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 27, 2023
1 parent b9ccecf commit 7124055
Show file tree
Hide file tree
Showing 13 changed files with 562 additions and 27 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
59 changes: 59 additions & 0 deletions e2e/tests-dfx/extension.bash
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,62 @@ 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",
"gzip": false
}
}
}' > "$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",
"gzip": true
}
},
"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
54 changes: 42 additions & 12 deletions src/dfx-core/src/config/model/dfinity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::error::structured_file::StructuredFileError;
use crate::error::structured_file::StructuredFileError::{
DeserializeJsonFileFailed, ReadJsonFileFailed,
};
use crate::extension::manifest::custom_canister_type;
use crate::json::save_json_file;
use crate::json::structure::{PossiblyStr, SerdeVec};
use byte_unit::Byte;
Expand Down Expand Up @@ -950,42 +951,65 @@ 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();
custom_canister_type::transform_dfx_json_via_extension(&mut json, extension_manager)
.unwrap(); // TODO: error handling
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 @@ -1203,6 +1227,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();

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

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

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

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

Expand All @@ -1324,6 +1353,7 @@ mod tests {
}
}
}"#,
&semver::Version::new(0, 0, 0),
)
.unwrap();
let config_interface = config_no_values.get_config();
Expand Down
10 changes: 10 additions & 0 deletions src/dfx-core/src/error/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,14 @@ pub enum ExtensionError {

#[error("Extension exited with non-zero status code '{0}'.")]
ExtensionExitedWithNonZeroStatus(i32),

// errors related to custom canister types
#[error("Extension '{0}' does not support any custom canister types.")]
ExtensionDoesNotSupportAnyCustomCanisterTypes(String),

#[error("Extension '{0}' does not support the specific custom canister type '{1}'.")]
ExtensionDoesNotSupportSpecificCustomCanisterType(String, String),

#[error("'{0}'")]
CustomCanisterTypeTemplateError(String),
}
Loading

0 comments on commit 7124055

Please sign in to comment.