Skip to content

Commit

Permalink
add new calls
Browse files Browse the repository at this point in the history
  • Loading branch information
jost-s committed Jul 17, 2024
1 parent f9e8623 commit b9de845
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## \[Unreleased\]

### Added
- New value `NotStartedAfterProvidingMemproofs` for type `DisabledAppReason` which effectively allows a new app status, corresponding to the specific state where a UI has just called AppRequest::ProvideMemproofs, but the app has not yet been enabled for the first time.
- New `AppWebsocket` call `EnableAfterMemproofsProvided`, which allows enabling an app only if the app is in the `AppStatus::Disabled(DisabledAppReason::NotStartedAfterProvidingMemproofs)` state. Attempting to enable the app from other states (other than Running) will fail.
- New field `lineage` to the DNA manifest, which declares forward compatibility for any hash in that list with this DNA.
- New `AdminWebsocket` call `GetCompatibleCells`, which returns `CellId` for all installed cells which use a DNA that is forward-compatible with a given DNA hash. This can be used to find a compatible cell for use with the UseExisting cell provisioning method.
### Changed
### Fixed
### Removed
Expand Down
2 changes: 2 additions & 0 deletions fixture/dna.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
manifest_version: "1"
name: test-dna
lineage:
- uhC0kDYtR49WteLI9NStqJ6wezkFQU3Z71o7NM5-P5gzsjhlVzKoM
integrity:
origin_time: "2022-09-30T00:00:00.000000Z"
zomes:
Expand Down
14 changes: 13 additions & 1 deletion src/admin_websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use anyhow::Result;
use holo_hash::DnaHash;
use holochain_conductor_api::{
AdminRequest, AdminResponse, AppAuthenticationTokenIssued, AppInfo, AppInterfaceInfo,
AppStatusFilter, IssueAppAuthenticationTokenPayload, StorageInfo,
AppStatusFilter, CompatibleCells, IssueAppAuthenticationTokenPayload, StorageInfo,
};
use holochain_types::websocket::AllowedOrigins;
use holochain_types::{
Expand Down Expand Up @@ -210,6 +210,18 @@ impl AdminWebsocket {
}
}

pub async fn get_compatible_cells(
&self,
dna_hash: DnaHash,
) -> ConductorApiResult<CompatibleCells> {
let msg = AdminRequest::GetCompatibleCells(dna_hash);
let response = self.send(msg).await?;
match response {
AdminResponse::CompatibleCells(compatible_cells) => Ok(compatible_cells),
_ => unreachable!("Unexpected response {:?}", response),
}
}

pub async fn grant_zome_call_capability(
&self,
payload: GrantZomeCallCapabilityPayload,
Expand Down
9 changes: 9 additions & 0 deletions src/app_websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ impl AppWebsocket {
}
}

pub async fn enable_app(&self) -> ConductorApiResult<()> {
let app_request = AppRequest::EnableApp;
let response = self.inner.send(app_request).await?;
match response {
AppResponse::Ok => Ok(()),
_ => unreachable!("Unexpected response {:?}", response),
}
}

pub async fn create_clone_cell(
&self,
msg: CreateCloneCellPayload,
Expand Down
52 changes: 51 additions & 1 deletion tests/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ use holochain_client::{
use holochain_conductor_api::{CellInfo, StorageBlob};
use holochain_types::websocket::AllowedOrigins;
use holochain_zome_types::prelude::ExternIO;
use std::collections::BTreeSet;
use std::net::Ipv4Addr;
use std::{collections::HashMap, path::PathBuf};

const ROLE_NAME: &str = "foo";

#[tokio::test(flavor = "multi_thread")]
async fn app_interfaces() {
let conductor = SweetConductor::from_standard_config().await;
Expand Down Expand Up @@ -45,6 +48,7 @@ async fn signed_zome_call() {
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
Expand All @@ -59,7 +63,7 @@ async fn signed_zome_call() {
.issue_app_auth_token(app_id.clone().into())
.await
.unwrap();
let mut signer = ClientAgentSigner::default();
let signer = ClientAgentSigner::default();
let app_ws = AppWebsocket::connect(
(Ipv4Addr::LOCALHOST, app_ws_port),
issued_token.token,
Expand Down Expand Up @@ -119,6 +123,7 @@ async fn storage_info() {
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
Expand Down Expand Up @@ -152,6 +157,7 @@ async fn dump_network_stats() {
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
Expand All @@ -161,3 +167,47 @@ async fn dump_network_stats() {

assert!(network_stats.contains("\"backend\": \"tx2-quic\""));
}

#[tokio::test(flavor = "multi_thread")]
async fn get_compatible_cells() {
let conductor = SweetConductor::from_standard_config().await;
let admin_port = conductor.get_arbitrary_admin_websocket_port().unwrap();
let admin_ws = AdminWebsocket::connect(format!("127.0.0.1:{}", admin_port))
.await
.unwrap();
let app_id: InstalledAppId = "test-app".into();
let agent_key = admin_ws.generate_agent_pub_key().await.unwrap();
let app_info = admin_ws
.install_app(InstallAppPayload {
agent_key: agent_key.clone(),
installed_app_id: Some(app_id.clone()),
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
let cell_id = if let CellInfo::Provisioned(provisioned_cell) =
&app_info.cell_info.get(ROLE_NAME).unwrap()[0]
{
provisioned_cell.cell_id.clone()
} else {
panic!("expected provisioned cell")
};
let dna_hash = cell_id.dna_hash().clone();
let mut compatible_cells = admin_ws.get_compatible_cells(dna_hash).await.unwrap();
assert_eq!(
compatible_cells.len(),
1,
"compatible cells set should have 1 element"
);
let cell_1 = compatible_cells.pop_first().unwrap();
let mut expected_cells = BTreeSet::new();
expected_cells.insert(cell_id);
assert_eq!(
cell_1,
(app_id, expected_cells),
"only cell should be expected app cell"
);
}
4 changes: 3 additions & 1 deletion tests/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ async fn deferred_memproof_installation() {
.expect("app info must exist");
assert_eq!(app_info.status, AppInfoStatus::AwaitingMemproofs);

app_ws.enable_app().await.unwrap_err();

let response = app_ws.provide_memproofs(HashMap::new()).await.unwrap();
assert_eq!(response, ());

Expand All @@ -327,7 +329,7 @@ async fn deferred_memproof_installation() {
"app status should be NotStartedAfterProvidingMemproofs"
);

admin_ws.enable_app(app_id.clone()).await.unwrap();
app_ws.enable_app().await.unwrap();

// App status should be `Running` now.
let app_info = app_ws
Expand Down
6 changes: 4 additions & 2 deletions tests/clone_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async fn clone_cell_management() {
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
Expand All @@ -50,7 +51,7 @@ async fn clone_cell_management() {
.issue_app_auth_token(app_id.clone().into())
.await
.unwrap();
let mut signer = ClientAgentSigner::default();
let signer = ClientAgentSigner::default();
let app_ws = AppWebsocket::connect(
format!("127.0.0.1:{}", app_api_port),
issued_token.token,
Expand Down Expand Up @@ -189,12 +190,13 @@ pub async fn app_info_refresh() {
membrane_proofs: HashMap::new(),
network_seed: None,
source: AppBundleSource::Path(PathBuf::from("./fixture/test.happ")),
ignore_genesis_failure: false,
})
.await
.unwrap();
admin_ws.enable_app(app_id.clone()).await.unwrap();

let mut signer = ClientAgentSigner::default();
let signer = ClientAgentSigner::default();

// Create an app interface and connect an app agent to it
let app_api_port = admin_ws
Expand Down

0 comments on commit b9de845

Please sign in to comment.