From ce8fa15a7db974ec453061589a2ac49242274b0c Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 18:47:29 -0500 Subject: [PATCH 01/27] feat: add TUF delegated targets support in perform_update Walk the delegation chain from targets.json when a delegations block is present: fetch each delegation file from metadata/delegations/.json, verify its hash/length against snapshot.json, verify its signature against the content key declared in the delegation keys map, then merge the delegated targets into the download set. Old flat-targets repos (no delegations block) continue to work unchanged. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/update.rs | 544 +++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 501 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a38542..3d85ca1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,7 +112,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "avocadoctl" -version = "0.5.0" +version = "0.6.0-dev" dependencies = [ "base64", "clap", diff --git a/Cargo.toml b/Cargo.toml index ff4aab5..9786b2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "avocadoctl" -version = "0.5.0" +version = "0.6.0-dev" edition = "2021" description = "Avocado Linux control CLI tool" authors = ["Avocado"] diff --git a/src/update.rs b/src/update.rs index dc18ffb..8444771 100644 --- a/src/update.rs +++ b/src/update.rs @@ -118,9 +118,54 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U ); } - // 3. Enumerate and download targets - let target_map = &targets.signed.targets; - println!(" Downloading {} target(s)...", target_map.len()); + // 3a. Walk delegations if present — collect delegated targets + let mut delegated_targets: Vec<(String, tough::schema::Target)> = Vec::new(); + + if let Some(delegations) = &targets.signed.delegations { + for role in &delegations.roles { + let role_path = format!("delegations/{}.json", role.name); + let delegation_url = format!("{url}/metadata/{role_path}"); + let delegation_raw = fetch_url(&delegation_url)?; + + // Verify hash + length against snapshot meta entry + verify_delegation_hash(&role_path, &delegation_raw, &snapshot)?; + + // Parse and verify signature against content key from targets.json delegations.keys + let delegation: tough::schema::Signed = + parse_metadata(&role_path, &delegation_raw)?; + verify_delegation_signatures( + &role_path, + &delegation_raw, + &delegation.signatures, + &delegations.keys, + &role.keyids, + role.threshold, + )?; + + if verbose { + println!( + " Verified delegation {} ({} target(s))", + role.name, + delegation.signed.targets.len() + ); + } + + for (name, info) in &delegation.signed.targets { + delegated_targets.push((name.raw().to_string(), info.clone())); + } + } + } + + // 3b. Enumerate and download targets (inline + delegated) + let inline_targets: Vec<(String, &tough::schema::Target)> = targets + .signed + .targets + .iter() + .map(|(k, v)| (k.raw().to_string(), v)) + .collect(); + + let all_count = inline_targets.len() + delegated_targets.len(); + println!(" Downloading {all_count} target(s)..."); let staging_dir = base_dir.join(".update-staging"); fs::create_dir_all(&staging_dir).map_err(|e| { @@ -144,49 +189,28 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U }) .unwrap_or_default(); - for (target_name, target_info) in target_map { - let name_str = target_name.raw(); - - // Content-addressable skip: if this target is an image that already - // exists locally, the UUIDv5 name guarantees identical content. - if name_str != "manifest.json" && existing_images.contains(name_str) { - if verbose { - println!(" Already present, skipping: {name_str}"); - } - continue; - } - - let target_url = format!("{url}/targets/{name_str}"); - - if verbose { - println!(" Downloading {name_str}..."); - } - - let data = fetch_url_bytes(&target_url)?; - - // Verify length - if data.len() as u64 != target_info.length { - return Err(UpdateError::HashMismatch { - target: name_str.to_string(), - expected: format!("{} bytes", target_info.length), - actual: format!("{} bytes", data.len()), - }); - } - - // Verify sha256 hash - let expected_hex = hex_encode(target_info.hashes.sha256.as_ref()); - let actual_hash = sha256_hex(&data); - if actual_hash != expected_hex { - return Err(UpdateError::HashMismatch { - target: name_str.to_string(), - expected: expected_hex, - actual: actual_hash, - }); - } + // Download inline targets (empty for delegated format; kept for backward compat) + for (name_str, target_info) in &inline_targets { + download_target( + url, + name_str, + target_info, + &staging_dir, + &existing_images, + verbose, + )?; + } - let target_path = staging_dir.join(name_str); - fs::write(&target_path, &data) - .map_err(|e| UpdateError::StagingFailed(format!("Failed to write {name_str}: {e}")))?; + // Download delegated targets + for (name_str, target_info) in &delegated_targets { + download_target( + url, + name_str, + target_info, + &staging_dir, + &existing_images, + verbose, + )?; } // 4. Parse the downloaded manifest and stage the update @@ -232,6 +256,160 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U Ok(()) } +/// Download a single target file into the staging directory, verifying hash and length. +/// Skips content-addressable image files that already exist on disk. +fn download_target( + url: &str, + name_str: &str, + target_info: &tough::schema::Target, + staging_dir: &Path, + existing_images: &std::collections::HashSet, + verbose: bool, +) -> Result<(), UpdateError> { + // Content-addressable skip: if this target is an image that already + // exists locally, the UUIDv5 name guarantees identical content. + if name_str != "manifest.json" && existing_images.contains(name_str) { + if verbose { + println!(" Already present, skipping: {name_str}"); + } + return Ok(()); + } + + let target_url = format!("{url}/targets/{name_str}"); + + if verbose { + println!(" Downloading {name_str}..."); + } + + let data = fetch_url_bytes(&target_url)?; + + // Verify length + if data.len() as u64 != target_info.length { + return Err(UpdateError::HashMismatch { + target: name_str.to_string(), + expected: format!("{} bytes", target_info.length), + actual: format!("{} bytes", data.len()), + }); + } + + // Verify sha256 hash + let expected_hex = hex_encode(target_info.hashes.sha256.as_ref()); + let actual_hash = sha256_hex(&data); + if actual_hash != expected_hex { + return Err(UpdateError::HashMismatch { + target: name_str.to_string(), + expected: expected_hex, + actual: actual_hash, + }); + } + + let target_path = staging_dir.join(name_str); + fs::write(&target_path, &data) + .map_err(|e| UpdateError::StagingFailed(format!("Failed to write {name_str}: {e}")))?; + + Ok(()) +} + +/// Verify a delegation file's hash and length against the snapshot metadata. +fn verify_delegation_hash( + role_path: &str, + raw_json: &str, + snapshot: &tough::schema::Signed, +) -> Result<(), UpdateError> { + // The snapshot meta key uses the full path like "delegations/runtime-.json" + let meta_entry = snapshot.signed.meta.get(role_path).ok_or_else(|| { + UpdateError::MetadataError(format!( + "Delegation '{role_path}' not found in snapshot.json meta" + )) + })?; + + let actual_len = raw_json.len() as u64; + if let Some(expected_len) = meta_entry.length { + if actual_len != expected_len { + return Err(UpdateError::MetadataError(format!( + "Length mismatch for '{role_path}': snapshot says {expected_len}, got {actual_len}" + ))); + } + } + + let actual_hash = sha256_hex(raw_json.as_bytes()); + let hashes = meta_entry.hashes.as_ref().ok_or_else(|| { + UpdateError::MetadataError(format!( + "No hashes in snapshot.json for '{role_path}'" + )) + })?; + let expected_hash = hex_encode(hashes.sha256.as_ref()); + if actual_hash != expected_hash { + return Err(UpdateError::MetadataError(format!( + "Hash mismatch for '{role_path}': snapshot says {expected_hash}, got {actual_hash}" + ))); + } + + Ok(()) +} + +/// Verify signatures on a delegation file using the keys declared in the +/// parent targets.json `delegations.keys` map. +fn verify_delegation_signatures>( + name: &str, + raw_json: &str, + signatures: &[tough::schema::Signature], + delegation_keys: &std::collections::HashMap, + authorized_keyids: &[K], + threshold: std::num::NonZeroU64, +) -> Result<(), UpdateError> { + let authorized_hex: Vec = authorized_keyids + .iter() + .map(|id| hex_encode(id.as_ref())) + .collect(); + + let threshold = threshold.get() as usize; + + // Build a map of keyid-hex → PublicKey from the delegation keys + let mut key_map: Vec<(String, PublicKey)> = Vec::new(); + for (key_id, key) in delegation_keys { + let key_id_hex = hex_encode(key_id.as_ref()); + if let tough::schema::key::Key::Ed25519 { keyval, .. } = key { + let public_hex = hex_encode(keyval.public.as_ref()); + if let Ok(public_bytes) = hex_decode(&public_hex) { + if let Ok(pk) = PublicKey::from_slice(&public_bytes) { + key_map.push((key_id_hex, pk)); + } + } + } + } + + let canonical = extract_signed_canonical(raw_json) + .map_err(|e| UpdateError::SignatureVerification(name.to_string(), e))?; + + let mut valid_count = 0; + + for sig in signatures { + let sig_key_id = hex_encode(sig.keyid.as_ref()); + + if !authorized_hex.contains(&sig_key_id) { + continue; + } + + if let Some((_, pk)) = key_map.iter().find(|(id, _)| *id == sig_key_id) { + if let Ok(signature) = ed25519_compact::Signature::from_slice(sig.sig.as_ref()) { + if pk.verify(canonical.as_bytes(), &signature).is_ok() { + valid_count += 1; + } + } + } + } + + if valid_count < threshold { + return Err(UpdateError::SignatureVerification( + name.to_string(), + format!("Insufficient valid signatures: got {valid_count}, need {threshold}"), + )); + } + + Ok(()) +} + fn extract_trusted_keys( root: &tough::schema::Root, ) -> Result, UpdateError> { @@ -406,6 +584,11 @@ mod tests { ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::from(seed_bytes)) } + fn content_keypair() -> ed25519_compact::KeyPair { + let seed_bytes = [99u8; 32]; + ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::from(seed_bytes)) + } + fn make_test_root_json() -> (String, ed25519_compact::KeyPair) { let kp = test_keypair(); let pk_hex = hex_encode(kp.pk.as_ref()); @@ -449,6 +632,25 @@ mod tests { (serde_json::to_string_pretty(&root).unwrap(), kp) } + /// Build a signed TUF metadata envelope. + fn sign_json(payload: &serde_json::Value, kp: &ed25519_compact::KeyPair) -> (String, String) { + let pk_hex = hex_encode(kp.pk.as_ref()); + let key_id = sha256_hex( + format!( + r#"{{"keytype":"ed25519","keyval":{{"public":"{pk_hex}"}},"scheme":"ed25519"}}"# + ) + .as_bytes(), + ); + let canonical = serde_json::to_string(payload).unwrap(); + let sig = kp.sk.sign(canonical.as_bytes(), None); + let sig_hex = hex_encode(sig.as_ref()); + let envelope = serde_json::json!({ + "signatures": [{ "keyid": &key_id, "sig": sig_hex }], + "signed": payload + }); + (serde_json::to_string_pretty(&envelope).unwrap(), key_id) + } + #[test] fn test_extract_trusted_keys() { let (root_json, _kp) = make_test_root_json(); @@ -541,4 +743,256 @@ mod tests { "Signature verification should succeed: {result:?}" ); } + + // ---- Delegation tests ---- + + fn make_delegated_targets_json( + runtime_uuid: &str, + content_kp: &ed25519_compact::KeyPair, + targets: &[(&str, &str, u64)], // (name, sha256_hex, size) + ) -> String { + let mut targets_map = serde_json::Map::new(); + for (name, hash, size) in targets { + targets_map.insert( + name.to_string(), + serde_json::json!({ + "hashes": { "sha256": hash }, + "length": size + }), + ); + } + let payload = serde_json::json!({ + "_type": "targets", + "expires": "2030-01-01T00:00:00Z", + "spec_version": "1.0.0", + "targets": targets_map, + "version": 1, + "_delegation_name": format!("runtime-{runtime_uuid}") + }); + let (json, _) = sign_json(&payload, content_kp); + json + } + + fn make_targets_with_delegation( + runtime_uuid: &str, + content_kp: &ed25519_compact::KeyPair, + signer_kp: &ed25519_compact::KeyPair, + ) -> String { + let content_pk_hex = hex_encode(content_kp.pk.as_ref()); + let content_key_id = sha256_hex( + format!( + r#"{{"keytype":"ed25519","keyval":{{"public":"{content_pk_hex}"}},"scheme":"ed25519"}}"# + ) + .as_bytes(), + ); + + let payload = serde_json::json!({ + "_type": "targets", + "expires": "2030-01-01T00:00:00Z", + "spec_version": "1.0.0", + "targets": {}, + "delegations": { + "keys": { + &content_key_id: { + "keytype": "ed25519", + "keyval": { "public": content_pk_hex }, + "scheme": "ed25519" + } + }, + "roles": [ + { + "name": format!("runtime-{runtime_uuid}"), + "keyids": [&content_key_id], + "threshold": 1, + "paths": ["manifest.json", "*.raw"], + "terminating": true + } + ] + }, + "version": 1 + }); + let (json, _) = sign_json(&payload, signer_kp); + json + } + + fn make_snapshot_with_delegation( + targets_json: &str, + delegation_json: &str, + runtime_uuid: &str, + signer_kp: &ed25519_compact::KeyPair, + ) -> String { + let targets_hash = sha256_hex(targets_json.as_bytes()); + let targets_len = targets_json.len() as u64; + let del_hash = sha256_hex(delegation_json.as_bytes()); + let del_len = delegation_json.len() as u64; + let del_path = format!("delegations/runtime-{runtime_uuid}.json"); + + let payload = serde_json::json!({ + "_type": "snapshot", + "expires": "2030-01-01T00:00:00Z", + "spec_version": "1.0.0", + "meta": { + "targets.json": { + "hashes": { "sha256": targets_hash }, + "length": targets_len, + "version": 1 + }, + del_path: { + "hashes": { "sha256": del_hash }, + "length": del_len, + "version": 1 + } + }, + "version": 1 + }); + let (json, _) = sign_json(&payload, signer_kp); + json + } + + #[test] + fn test_verify_delegation_hash_ok() { + let kp = test_keypair(); + let ckp = content_keypair(); + let uuid = "550e8400-e29b-41d4-a716-446655440000"; + let del_json = make_delegated_targets_json(uuid, &ckp, &[]); + let targets_json = make_targets_with_delegation(uuid, &ckp, &kp); + let snapshot_json = make_snapshot_with_delegation(&targets_json, &del_json, uuid, &kp); + let snapshot: tough::schema::Signed = + serde_json::from_str(&snapshot_json).unwrap(); + + let role_path = format!("delegations/runtime-{uuid}.json"); + assert!(verify_delegation_hash(&role_path, &del_json, &snapshot).is_ok()); + } + + #[test] + fn test_verify_delegation_hash_mismatch() { + let kp = test_keypair(); + let ckp = content_keypair(); + let uuid = "550e8400-e29b-41d4-a716-446655440000"; + let del_json = make_delegated_targets_json(uuid, &ckp, &[]); + let targets_json = make_targets_with_delegation(uuid, &ckp, &kp); + let snapshot_json = make_snapshot_with_delegation(&targets_json, &del_json, uuid, &kp); + let snapshot: tough::schema::Signed = + serde_json::from_str(&snapshot_json).unwrap(); + + let role_path = format!("delegations/runtime-{uuid}.json"); + let tampered = del_json.replace("runtime", "TAMPERED"); + assert!(verify_delegation_hash(&role_path, &tampered, &snapshot).is_err()); + } + + #[test] + fn test_verify_delegation_signatures_ok() { + let ckp = content_keypair(); + let uuid = "550e8400-e29b-41d4-a716-446655440000"; + let del_json = + make_delegated_targets_json(uuid, &ckp, &[("manifest.json", &"aa".repeat(32), 10)]); + + let del: tough::schema::Signed = + serde_json::from_str(&del_json).unwrap(); + + // Build keys + keyids matching the content keypair + let content_pk_hex = hex_encode(ckp.pk.as_ref()); + let content_key_id_hex = sha256_hex( + format!( + r#"{{"keytype":"ed25519","keyval":{{"public":"{content_pk_hex}"}},"scheme":"ed25519"}}"# + ) + .as_bytes(), + ); + + // Parse from a full targets.json with delegation block to get proper tough types + let kp = test_keypair(); + let targets_json = make_targets_with_delegation(uuid, &ckp, &kp); + let targets: tough::schema::Signed = + serde_json::from_str(&targets_json).unwrap(); + let delegations = targets.signed.delegations.unwrap(); + let role = &delegations.roles[0]; + + let role_path = format!("delegations/runtime-{uuid}.json"); + let result = verify_delegation_signatures( + &role_path, + &del_json, + &del.signatures, + &delegations.keys, + &role.keyids, + role.threshold, + ); + assert!( + result.is_ok(), + "Delegation signature verification should succeed: {result:?}" + ); + let _ = content_key_id_hex; + } + + #[test] + fn test_verify_delegation_signatures_wrong_key() { + let ckp = content_keypair(); + let wrong_kp = test_keypair(); // different key + let uuid = "550e8400-e29b-41d4-a716-446655440000"; + + // Sign with the content key, but declare a different key in delegation + let del_json = make_delegated_targets_json(uuid, &wrong_kp, &[]); + let del: tough::schema::Signed = + serde_json::from_str(&del_json).unwrap(); + + // targets.json delegates to ckp, but the file is signed by wrong_kp + let targets_json = make_targets_with_delegation(uuid, &ckp, &ckp); + let targets: tough::schema::Signed = + serde_json::from_str(&targets_json).unwrap(); + let delegations = targets.signed.delegations.unwrap(); + let role = &delegations.roles[0]; + + let role_path = format!("delegations/runtime-{uuid}.json"); + let result = verify_delegation_signatures( + &role_path, + &del_json, + &del.signatures, + &delegations.keys, + &role.keyids, + role.threshold, + ); + assert!(result.is_err(), "Should fail with wrong signing key"); + } + + #[test] + fn test_flat_targets_no_delegation() { + // Without a delegations block, delegated_targets should be empty + // and processing continues using inline targets only. + let kp = test_keypair(); + let pk_hex = hex_encode(kp.pk.as_ref()); + let key_id = sha256_hex( + format!( + r#"{{"keytype":"ed25519","keyval":{{"public":"{pk_hex}"}},"scheme":"ed25519"}}"# + ) + .as_bytes(), + ); + + // Build a flat targets.json without delegations + let payload = serde_json::json!({ + "_type": "targets", + "expires": "2030-01-01T00:00:00Z", + "spec_version": "1.0.0", + "targets": { + "manifest.json": { + "hashes": { "sha256": "aa".repeat(32) }, + "length": 10 + } + }, + "version": 1 + }); + let canonical = serde_json::to_string(&payload).unwrap(); + let sig = kp.sk.sign(canonical.as_bytes(), None); + let sig_hex = hex_encode(sig.as_ref()); + let targets_json = serde_json::to_string(&serde_json::json!({ + "signatures": [{ "keyid": key_id, "sig": sig_hex }], + "signed": payload + })) + .unwrap(); + + let targets: tough::schema::Signed = + serde_json::from_str(&targets_json).unwrap(); + + // No delegations block → no delegation walking + assert!(targets.signed.delegations.is_none()); + assert_eq!(targets.signed.targets.len(), 1); + } } From 4301e0a979cbbc73b53b9200e493c351998f43ad Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 18:53:41 -0500 Subject: [PATCH 02/27] fix: enable rustfmt in varlink code generator Passing true to cargo_build_tosource ensures generated .rs files are formatted consistently, preventing them from appearing as modified after every cargo build. --- build.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index b51e357..0ce53af 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,6 @@ fn main() { - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Extensions.varlink", false); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Runtimes.varlink", false); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Hitl.varlink", false); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.RootAuthority.varlink", false); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Extensions.varlink", true); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Runtimes.varlink", true); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Hitl.varlink", true); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.RootAuthority.varlink", true); } From a439f988138a8cf793e9a5cc34d3f65f7dd5ee10 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 18:59:12 -0500 Subject: [PATCH 03/27] revert: restore varlink generator rustfmt=false Yocto builds do not have rustfmt available as a build-time tool, causing build-script-build to fail. cargo fmt --check runs before cargo build in CI so the committed formatted files are checked correctly regardless. --- build.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index 0ce53af..b51e357 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,6 @@ fn main() { - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Extensions.varlink", true); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Runtimes.varlink", true); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Hitl.varlink", true); - varlink_generator::cargo_build_tosource("src/varlink/org.avocado.RootAuthority.varlink", true); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Extensions.varlink", false); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Runtimes.varlink", false); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.Hitl.varlink", false); + varlink_generator::cargo_build_tosource("src/varlink/org.avocado.RootAuthority.varlink", false); } From d941bacdef998de1ea6ed83b9eb743ca970b2a0b Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 19:44:45 -0500 Subject: [PATCH 04/27] feat: add bearer auth support for protected TUF endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - perform_update gains auth_token: Option<&str>; all HTTP fetches (metadata, delegations, targets) use a make_request helper that injects Authorization: Bearer when a token is present - varlink AddFromUrl(url, authToken: ?string) — existing callers omitting authToken get None → plain HTTP unchanged - CLI runtime add reads AVOCADO_TUF_AUTH_TOKEN env var (keeps JWT out of process listings) - Sideload path (avocado deploy, no env var) is unaffected --- src/commands/runtime.rs | 3 ++- src/service/runtime.rs | 4 +-- src/update.rs | 33 ++++++++++++++++-------- src/varlink/org.avocado.Runtimes.varlink | 4 +-- src/varlink_server.rs | 3 ++- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/commands/runtime.rs b/src/commands/runtime.rs index f42ff37..d8a430c 100644 --- a/src/commands/runtime.rs +++ b/src/commands/runtime.rs @@ -88,7 +88,8 @@ fn handle_add(matches: &ArgMatches, config: &Config, output: &OutputManager) { println!(" Adding runtime from {url}"); println!(); - match update::perform_update(url, base_path, output.is_verbose()) { + let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); + match update::perform_update(url, base_path, auth_token.as_deref(), output.is_verbose()) { Ok(()) => { crate::commands::ext::refresh_extensions(config, output); println!(); diff --git a/src/service/runtime.rs b/src/service/runtime.rs index 9bbe055..2185f4a 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -39,10 +39,10 @@ pub fn list_runtimes(config: &Config) -> Result, AvocadoError> } /// Add a runtime from a TUF repository URL. -pub fn add_from_url(url: &str, config: &Config) -> Result<(), AvocadoError> { +pub fn add_from_url(url: &str, auth_token: Option<&str>, config: &Config) -> Result<(), AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); - update::perform_update(url, base_path, false)?; + update::perform_update(url, base_path, auth_token, false)?; Ok(()) } diff --git a/src/update.rs b/src/update.rs index 8444771..14bb673 100644 --- a/src/update.rs +++ b/src/update.rs @@ -32,7 +32,7 @@ pub enum UpdateError { MetadataError(String), } -pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), UpdateError> { +pub fn perform_update(url: &str, base_dir: &Path, auth_token: Option<&str>, verbose: bool) -> Result<(), UpdateError> { let url = url.trim_end_matches('/'); // 1. Load the local trust anchor @@ -59,7 +59,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U println!(" Fetching update metadata..."); let timestamp_url = format!("{url}/metadata/timestamp.json"); - let timestamp_raw = fetch_url(×tamp_url)?; + let timestamp_raw = fetch_url(×tamp_url, auth_token)?; let timestamp: tough::schema::Signed = parse_metadata("timestamp.json", ×tamp_raw)?; verify_signatures( @@ -79,7 +79,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U } let snapshot_url = format!("{url}/metadata/snapshot.json"); - let snapshot_raw = fetch_url(&snapshot_url)?; + let snapshot_raw = fetch_url(&snapshot_url, auth_token)?; let snapshot: tough::schema::Signed = parse_metadata("snapshot.json", &snapshot_raw)?; verify_signatures( @@ -99,7 +99,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U } let targets_url = format!("{url}/metadata/targets.json"); - let targets_raw = fetch_url(&targets_url)?; + let targets_raw = fetch_url(&targets_url, auth_token)?; let targets: tough::schema::Signed = parse_metadata("targets.json", &targets_raw)?; verify_signatures( @@ -125,7 +125,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U for role in &delegations.roles { let role_path = format!("delegations/{}.json", role.name); let delegation_url = format!("{url}/metadata/{role_path}"); - let delegation_raw = fetch_url(&delegation_url)?; + let delegation_raw = fetch_url(&delegation_url, auth_token)?; // Verify hash + length against snapshot meta entry verify_delegation_hash(&role_path, &delegation_raw, &snapshot)?; @@ -197,6 +197,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U target_info, &staging_dir, &existing_images, + auth_token, verbose, )?; } @@ -209,6 +210,7 @@ pub fn perform_update(url: &str, base_dir: &Path, verbose: bool) -> Result<(), U target_info, &staging_dir, &existing_images, + auth_token, verbose, )?; } @@ -264,6 +266,7 @@ fn download_target( target_info: &tough::schema::Target, staging_dir: &Path, existing_images: &std::collections::HashSet, + auth_token: Option<&str>, verbose: bool, ) -> Result<(), UpdateError> { // Content-addressable skip: if this target is an image that already @@ -281,7 +284,7 @@ fn download_target( println!(" Downloading {name_str}..."); } - let data = fetch_url_bytes(&target_url)?; + let data = fetch_url_bytes(&target_url, auth_token)?; // Verify length if data.len() as u64 != target_info.length { @@ -509,8 +512,16 @@ fn extract_signed_canonical(raw_json: &str) -> Result { serde_json::to_string(signed).map_err(|e| format!("Failed to serialize: {e}")) } -fn fetch_url(url: &str) -> Result { - let response = ureq::get(url) +fn make_request(url: &str, auth_token: Option<&str>) -> ureq::RequestBuilder { + let req = ureq::get(url); + match auth_token { + Some(token) => req.header("Authorization", format!("Bearer {token}")), + None => req, + } +} + +fn fetch_url(url: &str, auth_token: Option<&str>) -> Result { + let response = make_request(url, auth_token) .call() .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; @@ -524,8 +535,8 @@ fn fetch_url(url: &str) -> Result { Ok(body) } -fn fetch_url_bytes(url: &str) -> Result, UpdateError> { - let response = ureq::get(url) +fn fetch_url_bytes(url: &str, auth_token: Option<&str>) -> Result, UpdateError> { + let response = make_request(url, auth_token) .call() .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; @@ -679,7 +690,7 @@ mod tests { #[test] fn test_no_trust_anchor() { let tmp = tempfile::TempDir::new().unwrap(); - let result = perform_update("http://localhost:9999", tmp.path(), false); + let result = perform_update("http://localhost:9999", tmp.path(), None, false); assert!(matches!(result, Err(UpdateError::NoTrustAnchor))); } diff --git a/src/varlink/org.avocado.Runtimes.varlink b/src/varlink/org.avocado.Runtimes.varlink index 94ee00c..d8597ab 100644 --- a/src/varlink/org.avocado.Runtimes.varlink +++ b/src/varlink/org.avocado.Runtimes.varlink @@ -24,8 +24,8 @@ type Runtime ( # List all available runtimes method List() -> (runtimes: []Runtime) -# Add a runtime from a TUF repository URL -method AddFromUrl(url: string) -> () +# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints) +method AddFromUrl(url: string, authToken: ?string) -> () # Add a runtime from a local manifest file method AddFromManifest(manifestPath: string) -> () diff --git a/src/varlink_server.rs b/src/varlink_server.rs index ae28bff..4279d68 100644 --- a/src/varlink_server.rs +++ b/src/varlink_server.rs @@ -174,8 +174,9 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { &self, call: &mut dyn vl_rt::Call_AddFromUrl, r#url: String, + r#authToken: Option, ) -> varlink::Result<()> { - match service::runtime::add_from_url(&url, &self.config) { + match service::runtime::add_from_url(&url, authToken.as_deref(), &self.config) { Ok(()) => call.reply(), Err(e) => map_rt_error!(call, e), } From 1d93eaf768e09ddd835fbfbc73b32a22a4c2f132 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 19:48:30 -0500 Subject: [PATCH 05/27] =?UTF-8?q?fix:=20inline=20ureq=20bearer=20auth=20?= =?UTF-8?q?=E2=80=94=20remove=20make=5Frequest=20helper=20with=20unresolva?= =?UTF-8?q?ble=20generic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RequestBuilder requires an explicit type parameter in ureq 3.x. Inline the auth header match directly in fetch_url and fetch_url_bytes to let the compiler infer the body type from context. --- src/update.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/update.rs b/src/update.rs index 14bb673..a03b8f0 100644 --- a/src/update.rs +++ b/src/update.rs @@ -512,18 +512,14 @@ fn extract_signed_canonical(raw_json: &str) -> Result { serde_json::to_string(signed).map_err(|e| format!("Failed to serialize: {e}")) } -fn make_request(url: &str, auth_token: Option<&str>) -> ureq::RequestBuilder { +fn fetch_url(url: &str, auth_token: Option<&str>) -> Result { let req = ureq::get(url); - match auth_token { + let response = match auth_token { Some(token) => req.header("Authorization", format!("Bearer {token}")), None => req, } -} - -fn fetch_url(url: &str, auth_token: Option<&str>) -> Result { - let response = make_request(url, auth_token) - .call() - .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; + .call() + .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; let mut body = String::new(); response @@ -536,9 +532,13 @@ fn fetch_url(url: &str, auth_token: Option<&str>) -> Result } fn fetch_url_bytes(url: &str, auth_token: Option<&str>) -> Result, UpdateError> { - let response = make_request(url, auth_token) - .call() - .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; + let req = ureq::get(url); + let response = match auth_token { + Some(token) => req.header("Authorization", format!("Bearer {token}")), + None => req, + } + .call() + .map_err(|e| UpdateError::FetchFailed(url.to_string(), e.to_string()))?; let mut body = Vec::new(); response From f15f8aef2515cbb0e920910d0d8bc6a58890baa0 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 19:49:09 -0500 Subject: [PATCH 06/27] chore: regenerate varlink bindings after AddFromUrl authToken parameter cargo build regenerates these from the .varlink schema files (rustfmt=false). --- src/varlink/org_avocado_Extensions.rs | 629 +---------------------- src/varlink/org_avocado_Hitl.rs | 347 +------------ src/varlink/org_avocado_RootAuthority.rs | 261 +--------- src/varlink/org_avocado_Runtimes.rs | 579 +-------------------- 4 files changed, 4 insertions(+), 1812 deletions(-) diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index 4e2962c..2bb6182 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1,628 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - CommandFailed(Option), - ConfigurationError(Option), - ExtensionNotFound(Option), - MergeFailed(Option), - UnmergeFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::CommandFailed(v) => { - write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) - } - ErrorKind::ConfigurationError(v) => { - write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) - } - ErrorKind::ExtensionNotFound(v) => { - write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) - } - ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), - ErrorKind::UnmergeFailed(v) => { - write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.CommandFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::CommandFailed(v), - Err(_) => ErrorKind::CommandFailed(None), - }, - _ => ErrorKind::CommandFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ConfigurationError" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ConfigurationError(v), - Err(_) => ErrorKind::ConfigurationError(None), - }, - _ => ErrorKind::ConfigurationError(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ExtensionNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ExtensionNotFound(v), - Err(_) => ErrorKind::ExtensionNotFound(None), - }, - _ => ErrorKind::ExtensionNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MergeFailed(v), - Err(_) => ErrorKind::MergeFailed(None), - }, - _ => ErrorKind::MergeFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.UnmergeFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmergeFailed(v), - Err(_) => ErrorKind::UnmergeFailed(None), - }, - _ => ErrorKind::UnmergeFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_command_failed( - &mut self, - r#command: String, - r#message: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.CommandFailed", - Some( - serde_json::to_value(CommandFailed_Args { - r#command, - r#message, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ConfigurationError", - Some( - serde_json::to_value(ConfigurationError_Args { r#message }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ExtensionNotFound", - Some( - serde_json::to_value(ExtensionNotFound_Args { r#name }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.MergeFailed", - Some( - serde_json::to_value(MergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.UnmergeFailed", - Some( - serde_json::to_value(UnmergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Extension { - pub r#name: String, - pub r#version: Option, - pub r#path: String, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isDirectory: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ExtensionStatus { - pub r#name: String, - pub r#version: Option, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isMerged: bool, - pub r#origin: Option, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct CommandFailed_Args { - pub r#command: String, - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ConfigurationError_Args { - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ExtensionNotFound_Args { - pub r#name: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Reply { - pub r#disabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Disable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#extensions: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#all: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Disable: VarlinkCallError { - fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Disable_Reply { - r#disabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Disable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Reply { - pub r#enabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Enable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Args { - pub r#extensions: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Enable: VarlinkCallError { - fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Enable_Reply { - r#enabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Enable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#extensions }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Reply {} -impl varlink::VarlinkReply for Merge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Args {} -#[allow(dead_code)] -pub trait Call_Merge: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Merge for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Reply {} -impl varlink::VarlinkReply for Refresh_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Args {} -#[allow(dead_code)] -pub trait Call_Refresh: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Refresh for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for Status_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Args {} -#[allow(dead_code)] -pub trait Call_Status: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(Status_Reply { r#extensions }.into()) - } -} -impl Call_Status for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Reply {} -impl varlink::VarlinkReply for Unmerge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#unmount: Option, -} -#[allow(dead_code)] -pub trait Call_Unmerge: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Unmerge for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn disable( - &self, - call: &mut dyn Call_Disable, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn enable( - &self, - call: &mut dyn Call_Enable, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; - fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; - fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; - fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn merge(&mut self) -> varlink::MethodCall; - fn refresh(&mut self) -> varlink::MethodCall; - fn status(&mut self) -> varlink::MethodCall; - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Disable", - Disable_Args { - r#extensions, - r#all, - r#osRelease, - }, - ) - } - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Enable", - Enable_Args { - r#extensions, - r#osRelease, - }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.List", - List_Args {}, - ) - } - fn merge(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Merge", - Merge_Args {}, - ) - } - fn refresh(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Refresh", - Refresh_Args {}, - ) - } - fn status(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Status", - Status_Args {}, - ) - } - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Unmerge", - Unmerge_Args { r#unmount }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> ()\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> ()\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> ()\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Extensions" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Extensions.Disable" => { - if let Some(args) = req.parameters.clone() { - let args: Disable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.disable( - call as &mut dyn Call_Disable, - args.r#extensions, - args.r#all, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.Enable" => { - if let Some(args) = req.parameters.clone() { - let args: Enable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.enable( - call as &mut dyn Call_Enable, - args.r#extensions, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), - "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), - "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), - "org.avocado.Extensions.Unmerge" => { - if let Some(args) = req.parameters.clone() { - let args: Unmerge_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> ()\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> ()\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> ()\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 59a04ea..7720a1d 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1,346 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - MountFailed(Option), - UnmountFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), - ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e - { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MountFailed(v), - Err(_) => ErrorKind::MountFailed(None), - }, - _ => ErrorKind::MountFailed(None), - }, - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmountFailed(v), - Err(_) => ErrorKind::UnmountFailed(None), - }, - _ => ErrorKind::UnmountFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.MountFailed", - Some( - serde_json::to_value(MountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmount_failed( - &mut self, - r#extension: String, - r#reason: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.UnmountFailed", - Some( - serde_json::to_value(UnmountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Reply {} -impl varlink::VarlinkReply for Mount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Args { - pub r#serverIp: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#serverPort: Option, - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Mount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Mount for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Reply {} -impl varlink::VarlinkReply for Unmount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Args { - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Unmount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Unmount for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn mount( - &self, - call: &mut dyn Call_Mount, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn unmount( - &self, - call: &mut dyn Call_Unmount, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall; - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Mount", - Mount_Args { - r#serverIp, - r#serverPort, - r#extensions, - }, - ) - } - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Unmount", - Unmount_Args { r#extensions }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Hitl" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Hitl.Mount" => { - if let Some(args) = req.parameters.clone() { - let args: Mount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.mount( - call as &mut dyn Call_Mount, - args.r#serverIp, - args.r#serverPort, - args.r#extensions, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Hitl.Unmount" => { - if let Some(args) = req.parameters.clone() { - let args: Unmount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmount(call as &mut dyn Call_Unmount, args.r#extensions) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index c8d4a18..029ad69 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1,260 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - NoRootAuthority(Option), - ParseFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::NoRootAuthority(v) => { - write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) - } - ErrorKind::ParseFailed(v) => { - write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.NoRootAuthority" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::NoRootAuthority(v), - Err(_) => ErrorKind::NoRootAuthority(None), - }, - _ => ErrorKind::NoRootAuthority(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.ParseFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ParseFailed(v), - Err(_) => ErrorKind::ParseFailed(None), - }, - _ => ErrorKind::ParseFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_no_root_authority(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.NoRootAuthority", - None, - )) - } - fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.ParseFailed", - Some( - serde_json::to_value(ParseFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RootAuthorityInfo { - pub r#version: i64, - pub r#expires: String, - pub r#keys: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#TrustedKey { - pub r#keyId: String, - pub r#keyType: String, - pub r#roles: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct NoRootAuthority_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ParseFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Reply { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#authority: Option, -} -impl varlink::VarlinkReply for Show_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Args {} -#[allow(dead_code)] -pub trait Call_Show: VarlinkCallError { - fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { - self.reply_struct(Show_Reply { r#authority }.into()) - } -} -impl Call_Show for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn show(&mut self) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn show(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.RootAuthority.Show", - Show_Args {}, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.RootAuthority" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index 97b3f9b..1baf5c4 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1,578 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - AmbiguousRuntimeId(Option), - RemoveActiveRuntime(Option), - RuntimeNotFound(Option), - StagingFailed(Option), - UpdateFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::AmbiguousRuntimeId(v) => { - write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) - } - ErrorKind::RemoveActiveRuntime(v) => { - write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) - } - ErrorKind::RuntimeNotFound(v) => { - write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) - } - ErrorKind::StagingFailed(v) => { - write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) - } - ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::AmbiguousRuntimeId(v), - Err(_) => ErrorKind::AmbiguousRuntimeId(None), - }, - _ => ErrorKind::AmbiguousRuntimeId(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RemoveActiveRuntime" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RemoveActiveRuntime(v), - Err(_) => ErrorKind::RemoveActiveRuntime(None), - }, - _ => ErrorKind::RemoveActiveRuntime(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RuntimeNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RuntimeNotFound(v), - Err(_) => ErrorKind::RuntimeNotFound(None), - }, - _ => ErrorKind::RuntimeNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::StagingFailed(v), - Err(_) => ErrorKind::StagingFailed(None), - }, - _ => ErrorKind::StagingFailed(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UpdateFailed(v), - Err(_) => ErrorKind::UpdateFailed(None), - }, - _ => ErrorKind::UpdateFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_ambiguous_runtime_id( - &mut self, - r#id: String, - r#candidates: Vec, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.AmbiguousRuntimeId", - Some( - serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RemoveActiveRuntime", - None, - )) - } - fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RuntimeNotFound", - Some( - serde_json::to_value(RuntimeNotFound_Args { r#id }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.StagingFailed", - Some( - serde_json::to_value(StagingFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.UpdateFailed", - Some( - serde_json::to_value(UpdateFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ManifestExtension { - pub r#name: String, - pub r#version: String, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Runtime { - pub r#id: String, - pub r#manifestVersion: i64, - pub r#builtAt: String, - pub r#runtime: RuntimeInfo, - pub r#extensions: Vec, - pub r#active: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RuntimeInfo { - pub r#name: String, - pub r#version: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AmbiguousRuntimeId_Args { - pub r#id: String, - pub r#candidates: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RemoveActiveRuntime_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RuntimeNotFound_Args { - pub r#id: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct StagingFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UpdateFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Reply {} -impl varlink::VarlinkReply for Activate_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Activate: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Activate for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Reply {} -impl varlink::VarlinkReply for AddFromManifest_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Args { - pub r#manifestPath: String, -} -#[allow(dead_code)] -pub trait Call_AddFromManifest: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_AddFromManifest for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Reply {} -impl varlink::VarlinkReply for AddFromUrl_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Args { - pub r#url: String, -} -#[allow(dead_code)] -pub trait Call_AddFromUrl: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_AddFromUrl for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Reply { - pub r#runtime: Runtime, -} -impl varlink::VarlinkReply for Inspect_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Inspect: VarlinkCallError { - fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { - self.reply_struct(Inspect_Reply { r#runtime }.into()) - } -} -impl Call_Inspect for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#runtimes: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#runtimes }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Reply {} -impl varlink::VarlinkReply for Remove_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Remove: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Remove for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; - fn add_from_manifest( - &self, - call: &mut dyn Call_AddFromManifest, - r#manifestPath: String, - ) -> varlink::Result<()>; - fn add_from_url(&self, call: &mut dyn Call_AddFromUrl, r#url: String) -> varlink::Result<()>; - fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall; - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall; - fn add_from_url( - &mut self, - r#url: String, - ) -> varlink::MethodCall; - fn inspect(&mut self, r#id: String) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn remove(&mut self, r#id: String) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Activate", - Activate_Args { r#id }, - ) - } - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromManifest", - AddFromManifest_Args { r#manifestPath }, - ) - } - fn add_from_url( - &mut self, - r#url: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromUrl", - AddFromUrl_Args { r#url }, - ) - } - fn inspect(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Inspect", - Inspect_Args { r#id }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.List", - List_Args {}, - ) - } - fn remove(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Remove", - Remove_Args { r#id }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL\nmethod AddFromUrl(url: string) -> ()\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> ()\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> ()\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Runtimes" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Runtimes.Activate" => { - if let Some(args) = req.parameters.clone() { - let args: Activate_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .activate(call as &mut dyn Call_Activate, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromManifest" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromManifest_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.add_from_manifest( - call as &mut dyn Call_AddFromManifest, - args.r#manifestPath, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromUrl" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromUrl_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .add_from_url(call as &mut dyn Call_AddFromUrl, args.r#url) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.Inspect" => { - if let Some(args) = req.parameters.clone() { - let args: Inspect_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Runtimes.Remove" => { - if let Some(args) = req.parameters.clone() { - let args: Remove_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.remove(call as &mut dyn Call_Remove, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> ()\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> ()\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> ()\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file From fa90fa60eefa6e4bf7a51c774ba8919a43bb995c Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 20:27:32 -0500 Subject: [PATCH 07/27] feat: route all CLI commands through varlink daemon for serialisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All avocadoctl commands (ext, hitl, runtime, root-authority, and top-level aliases) now connect to the running varlink daemon socket and forward requests as RPC calls, rather than calling service functions directly. This ensures concurrent CLI invocations are queued and serialised by the daemon, preventing race conditions when multiple processes attempt to modify system state (merge extensions, activate runtimes, etc.) simultaneously. Changes: - src/config.rs: add optional `avocado.socket` config key; add Config::socket_address() helper (default: unix:/run/avocado/avocadoctl.sock) - src/varlink_client.rs (new): connect_or_exit(), exit_with_rpc_error(), and output-formatting helpers for all four varlink interfaces - src/main.rs: add --socket global flag; dispatch all commands through the generated VarlinkClient types; keep `serve` as a direct path (it starts the daemon); add AVOCADO_TEST_MODE bypass (handle_direct) so existing integration tests with mock executables continue to work without a live daemon - tests/ext_integration_tests.rs: add AVOCADO_TEST_MODE=1 to three tests that were invoking the CLI without it - tests/varlink_interface_tests.rs (new): 8 integration tests that start a real daemon on a temp socket and exercise the full varlink client→daemon→service path, including a concurrent-requests test and a no-daemon error-message test --- src/config.rs | 14 ++ src/main.rs | 376 +++++++++++++++++++++++++++++-- src/varlink_client.rs | 311 +++++++++++++++++++++++++ tests/ext_integration_tests.rs | 12 +- tests/varlink_interface_tests.rs | 293 ++++++++++++++++++++++++ 5 files changed, 980 insertions(+), 26 deletions(-) create mode 100644 src/varlink_client.rs create mode 100644 tests/varlink_interface_tests.rs diff --git a/src/config.rs b/src/config.rs index b96f52c..9158818 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,10 @@ pub struct AvocadoConfig { /// Override for the avocado base directory (default: /var/lib/avocado) #[serde(default, skip_serializing_if = "Option::is_none")] pub runtimes_dir: Option, + /// Varlink socket address for daemon communication + /// (default: unix:/run/avocado/avocadoctl.sock) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub socket: Option, } /// Extension configuration @@ -47,6 +51,7 @@ impl Default for Config { mutable: None, }, runtimes_dir: None, + socket: None, }, } } @@ -81,6 +86,15 @@ impl Config { Self::load(config_path) } + /// Get the varlink socket address for daemon communication. + /// Resolution order: config file → hardcoded default. + pub fn socket_address(&self) -> &str { + self.avocado + .socket + .as_deref() + .unwrap_or("unix:/run/avocado/avocadoctl.sock") + } + /// Get the extensions directory, checking environment variable first pub fn get_extensions_dir(&self) -> String { // Environment variable takes precedence (for testing) diff --git a/src/main.rs b/src/main.rs index 565a55f..c9e4284 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,12 +6,20 @@ pub mod service; pub mod staging; pub mod update; mod varlink; +mod varlink_client; mod varlink_server; use clap::{Arg, Command}; use commands::{ext, hitl, root_authority, runtime}; use config::Config; use output::OutputManager; +use varlink::org_avocado_Extensions as vl_ext; +use varlink::org_avocado_Hitl as vl_hitl; +use varlink::org_avocado_RootAuthority as vl_ra; +use varlink::org_avocado_Runtimes as vl_rt; +use varlink_client::{ + ExtClientInterface, HitlClientInterface, RaClientInterface, RtClientInterface, +}; fn main() { let app = Command::new(env!("CARGO_PKG_NAME")) @@ -43,10 +51,17 @@ fn main() { .global(true) .default_value("table"), ) - .subcommand(ext::create_command()) - .subcommand(hitl::create_command()) - .subcommand(root_authority::create_command()) - .subcommand(runtime::create_command()) + .arg( + Arg::new("socket") + .long("socket") + .value_name("ADDRESS") + .help("Varlink daemon socket address (overrides config)") + .global(true), + ) + .subcommand(commands::ext::create_command()) + .subcommand(commands::hitl::create_command()) + .subcommand(commands::root_authority::create_command()) + .subcommand(commands::runtime::create_command()) .subcommand( Command::new("status").about("Show overall system status including extensions"), ) @@ -144,19 +159,205 @@ fn main() { } }; + // Resolve socket address: CLI flag > config > default + let socket_address = matches + .get_one::("socket") + .map(|s| s.clone()) + .unwrap_or_else(|| config.socket_address().to_string()); + + // In test mode, skip the varlink daemon and call service functions directly. + // This allows existing integration tests (which use AVOCADO_TEST_MODE=1 with mock + // executables) to keep running without needing a live daemon. + if std::env::var("AVOCADO_TEST_MODE").is_ok() { + handle_direct(&matches, &config, &output); + return; + } + match matches.subcommand() { + // ── ext subcommands ────────────────────────────────────────────────── Some(("ext", ext_matches)) => { - ext::handle_command(ext_matches, &config, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + match ext_matches.subcommand() { + Some(("list", _)) => { + let mut client = vl_ext::VarlinkClient::new(conn); + match client.list().recv() { + Ok(reply) => varlink_client::print_extensions(&reply.extensions, &output), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } + Some(("merge", _)) => { + let mut client = vl_ext::VarlinkClient::new(conn); + match client.merge().recv() { + Ok(_) => output.success("Merge", "Extensions merged successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("unmerge", unmerge_matches)) => { + let unmount = unmerge_matches.get_flag("unmount"); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.unmerge(Some(unmount)).recv() { + Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("refresh", _)) => { + let mut client = vl_ext::VarlinkClient::new(conn); + match client.refresh().recv() { + Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("status", _)) => { + let mut client = vl_ext::VarlinkClient::new(conn); + match client.status().recv() { + Ok(reply) => { + varlink_client::print_extension_status(&reply.extensions, &output) + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } + _ => { + println!("Use 'avocadoctl ext --help' for available extension commands"); + } + } } + + // ── hitl subcommands ───────────────────────────────────────────────── Some(("hitl", hitl_matches)) => { - hitl::handle_command(hitl_matches, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + match hitl_matches.subcommand() { + Some(("mount", mount_matches)) => { + let server_ip = mount_matches + .get_one::("server-ip") + .expect("server-ip is required") + .clone(); + let server_port = mount_matches + .get_one::("server-port") + .map(|s| s.clone()); + let extensions: Vec = mount_matches + .get_many::("extension") + .expect("at least one extension is required") + .cloned() + .collect(); + let mut client = vl_hitl::VarlinkClient::new(conn); + match client.mount(server_ip, server_port, extensions).recv() { + Ok(_) => { + output.success("HITL Mount", "Extensions mounted successfully") + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("unmount", unmount_matches)) => { + let extensions: Vec = unmount_matches + .get_many::("extension") + .expect("at least one extension is required") + .cloned() + .collect(); + let mut client = vl_hitl::VarlinkClient::new(conn); + match client.unmount(extensions).recv() { + Ok(_) => { + output.success("HITL Unmount", "Extensions unmounted successfully") + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + _ => { + println!("Use 'avocadoctl hitl --help' for available HITL commands"); + } + } } + + // ── root-authority ─────────────────────────────────────────────────── Some(("root-authority", _)) => { - root_authority::handle_command(&config, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ra::VarlinkClient::new(conn); + match client.show().recv() { + Ok(reply) => varlink_client::print_root_authority(&reply.authority, &output), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } } + + // ── runtime subcommands ────────────────────────────────────────────── Some(("runtime", runtime_matches)) => { - runtime::handle_command(runtime_matches, &config, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + match runtime_matches.subcommand() { + Some(("list", _)) => { + let mut client = vl_rt::VarlinkClient::new(conn); + match client.list().recv() { + Ok(reply) => varlink_client::print_runtimes(&reply.runtimes, &output), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } + Some(("add", add_matches)) => { + if let Some(url) = add_matches.get_one::("url") { + let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); + let mut client = vl_rt::VarlinkClient::new(conn); + match client + .add_from_url(url.clone(), auth_token) + .recv() + { + Ok(_) => output.success("Runtime Add", "Runtime added successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } else if let Some(manifest) = add_matches.get_one::("manifest") { + let mut client = vl_rt::VarlinkClient::new(conn); + match client.add_from_manifest(manifest.clone()).recv() { + Ok(_) => output.success("Runtime Add", "Runtime added successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } + json_ok(&output); + } + Some(("remove", remove_matches)) => { + let id = remove_matches + .get_one::("id") + .expect("id is required") + .clone(); + let mut client = vl_rt::VarlinkClient::new(conn); + match client.remove(id).recv() { + Ok(_) => output.success("Runtime Remove", "Runtime removed successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("activate", activate_matches)) => { + let id = activate_matches + .get_one::("id") + .expect("id is required") + .clone(); + let mut client = vl_rt::VarlinkClient::new(conn); + match client.activate(id).recv() { + Ok(_) => { + output.success("Runtime Activate", "Runtime activated successfully") + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("inspect", inspect_matches)) => { + let id = inspect_matches + .get_one::("id") + .expect("id is required") + .clone(); + let mut client = vl_rt::VarlinkClient::new(conn); + match client.inspect(id).recv() { + Ok(reply) => varlink_client::print_runtime_detail(&reply.runtime, &output), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } + _ => { + println!("Use 'runtime list' to see available runtimes."); + println!("Run 'avocadoctl runtime --help' for more information."); + } + } } + + // ── serve (starts the daemon — direct, no varlink client) ──────────── Some(("serve", serve_matches)) => { let address = serve_matches .get_one::("address") @@ -166,23 +367,158 @@ fn main() { std::process::exit(1); } } + + // ── status (top-level) ─────────────────────────────────────────────── Some(("status", _)) => { - show_system_status(&config, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.status().recv() { + Ok(reply) => { + output.status_header("System Status"); + varlink_client::print_extension_status(&reply.extensions, &output); + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } } - // Top-level command aliases + + // ── Top-level aliases ──────────────────────────────────────────────── Some(("merge", _)) => { - ext::merge_extensions_direct(&output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.merge().recv() { + Ok(_) => output.success("Merge", "Extensions merged successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } json_ok(&output); } Some(("unmerge", unmerge_matches)) => { let unmount = unmerge_matches.get_flag("unmount"); - ext::unmerge_extensions_direct(unmount, &output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.unmerge(Some(unmount)).recv() { + Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } json_ok(&output); } Some(("refresh", _)) => { - ext::refresh_extensions_direct(&output); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.refresh().recv() { + Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } json_ok(&output); } + Some(("enable", enable_matches)) => { + let os_release = enable_matches + .get_one::("os_release") + .cloned(); + let extensions: Vec = enable_matches + .get_many::("extensions") + .unwrap() + .cloned() + .collect(); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.enable(extensions, os_release).recv() { + Ok(reply) => { + if !output.is_json() { + output.success( + "Enable", + &format!( + "{} extension(s) enabled, {} failed", + reply.enabled, reply.failed + ), + ); + } + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + Some(("disable", disable_matches)) => { + let os_release = disable_matches + .get_one::("os_release") + .cloned(); + let all = disable_matches.get_flag("all"); + let extensions: Option> = disable_matches + .get_many::("extensions") + .map(|values| values.cloned().collect()); + let conn = varlink_client::connect_or_exit(&socket_address, &output); + let mut client = vl_ext::VarlinkClient::new(conn); + match client.disable(extensions, Some(all), os_release).recv() { + Ok(reply) => { + if !output.is_json() { + output.success( + "Disable", + &format!( + "{} extension(s) disabled, {} failed", + reply.disabled, reply.failed + ), + ); + } + } + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + json_ok(&output); + } + + _ => { + println!( + "{} - {}", + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_DESCRIPTION") + ); + println!("Use --help for more information or --version for version details"); + } + } +} + +/// Direct dispatch used when AVOCADO_TEST_MODE is set. +/// Calls service functions directly, bypassing the varlink daemon. +/// This keeps existing integration tests (with mock executables) working +/// without needing a live daemon process. +fn handle_direct(matches: &clap::ArgMatches, config: &Config, output: &OutputManager) { + match matches.subcommand() { + Some(("ext", ext_matches)) => { + ext::handle_command(ext_matches, config, output); + } + Some(("hitl", hitl_matches)) => { + hitl::handle_command(hitl_matches, output); + } + Some(("root-authority", _)) => { + root_authority::handle_command(config, output); + } + Some(("runtime", runtime_matches)) => { + runtime::handle_command(runtime_matches, config, output); + } + Some(("serve", serve_matches)) => { + let address = serve_matches + .get_one::("address") + .expect("address has a default value"); + if let Err(e) = varlink_server::run_server(address, config.clone()) { + output.error("Server Error", &format!("Varlink server failed: {e}")); + std::process::exit(1); + } + } + Some(("status", _)) => { + output.status_header("System Status"); + ext::status_extensions(config, output); + } + Some(("merge", _)) => { + ext::merge_extensions_direct(output); + json_ok(output); + } + Some(("unmerge", unmerge_matches)) => { + let unmount = unmerge_matches.get_flag("unmount"); + ext::unmerge_extensions_direct(unmount, output); + json_ok(output); + } + Some(("refresh", _)) => { + ext::refresh_extensions_direct(output); + json_ok(output); + } Some(("enable", enable_matches)) => { let os_release = enable_matches .get_one::("os_release") @@ -192,8 +528,8 @@ fn main() { .unwrap() .map(|s| s.as_str()) .collect(); - ext::enable_extensions(os_release, &extensions, &config, &output); - json_ok(&output); + ext::enable_extensions(os_release, &extensions, config, output); + json_ok(output); } Some(("disable", disable_matches)) => { let os_release = disable_matches @@ -203,8 +539,8 @@ fn main() { let extensions: Option> = disable_matches .get_many::("extensions") .map(|values| values.map(|s| s.as_str()).collect()); - ext::disable_extensions(os_release, extensions.as_deref(), all, &config, &output); - json_ok(&output); + ext::disable_extensions(os_release, extensions.as_deref(), all, config, output); + json_ok(output); } _ => { println!( @@ -217,12 +553,6 @@ fn main() { } } -/// Show overall system status including extensions -fn show_system_status(config: &Config, output: &OutputManager) { - output.info("System Status", "Checking overall system status"); - ext::status_extensions(config, output); -} - /// Emit a JSON success result when in JSON mode (no-op otherwise). /// Action commands that exit(1) on failure never reach this, /// so it only runs on success. diff --git a/src/varlink_client.rs b/src/varlink_client.rs new file mode 100644 index 0000000..1b44712 --- /dev/null +++ b/src/varlink_client.rs @@ -0,0 +1,311 @@ +use crate::output::OutputManager; +use crate::varlink::{ + org_avocado_Extensions as vl_ext, org_avocado_Hitl as vl_hitl, + org_avocado_RootAuthority as vl_ra, org_avocado_Runtimes as vl_rt, +}; +use std::sync::{Arc, RwLock}; +use varlink::Connection; + +pub use vl_ext::VarlinkClientInterface as ExtClientInterface; +pub use vl_hitl::VarlinkClientInterface as HitlClientInterface; +pub use vl_ra::VarlinkClientInterface as RaClientInterface; +pub use vl_rt::VarlinkClientInterface as RtClientInterface; + +/// Connect to the varlink daemon socket. +/// Prints an error and exits with code 1 if the daemon is not reachable. +pub fn connect_or_exit(address: &str, output: &OutputManager) -> Arc> { + match varlink::Connection::with_address(address) { + Ok(conn) => conn, + Err(e) => { + output.error( + "Daemon Not Running", + &format!( + "Cannot connect to avocadoctl daemon at {address}: {e}\n \ + Start it with: systemctl start avocadoctl" + ), + ); + std::process::exit(1); + } + } +} + +/// Print an RPC error and exit with code 1. +pub fn exit_with_rpc_error(err: impl std::fmt::Display, output: &OutputManager) -> ! { + output.error("RPC Error", &err.to_string()); + std::process::exit(1); +} + +// ── Extension output helpers ───────────────────────────────────────────────── + +pub fn print_extensions(extensions: &[vl_ext::Extension], output: &OutputManager) { + if output.is_json() { + match serde_json::to_string(extensions) { + Ok(json) => println!("{json}"), + Err(e) => { + output.error("Output", &format!("JSON serialization failed: {e}")); + std::process::exit(1); + } + } + return; + } + + if extensions.is_empty() { + println!("No extensions found."); + return; + } + + let name_width = extensions + .iter() + .map(|e| { + e.name.len() + + e.version + .as_ref() + .map(|v| v.len() + 1) + .unwrap_or(0) + }) + .max() + .unwrap_or(9) + .max(9); + + println!( + "{: ext.name.clone(), + }; + + let mut types = Vec::new(); + if ext.isSysext { + types.push("sys"); + } + if ext.isConfext { + types.push("conf"); + } + let type_str = if types.is_empty() { + "?".to_string() + } else { + types.join("+") + }; + + println!( + "{: println!("{json}"), + Err(e) => { + output.error("Output", &format!("JSON serialization failed: {e}")); + std::process::exit(1); + } + } + return; + } + + if extensions.is_empty() { + println!("No extensions currently merged."); + return; + } + + let name_width = extensions + .iter() + .map(|e| { + e.name.len() + + e.version + .as_ref() + .map(|v| v.len() + 1) + .unwrap_or(0) + }) + .max() + .unwrap_or(9) + .max(9); + + println!( + "{: ext.name.clone(), + }; + + let mut types = Vec::new(); + if ext.isSysext { + types.push("sys"); + } + if ext.isConfext { + types.push("conf"); + } + let type_str = if types.is_empty() { + "?".to_string() + } else { + types.join("+") + }; + + let merged_str = if ext.isMerged { "yes" } else { "no" }; + let origin = ext.origin.as_deref().unwrap_or("-"); + + println!( + "{: println!("{json}"), + Err(e) => { + output.error("Output", &format!("JSON serialization failed: {e}")); + std::process::exit(1); + } + } + return; + } + + if runtimes.is_empty() { + println!("No runtimes found."); + return; + } + + let id_width = runtimes + .iter() + .map(|r| r.id.len().min(12)) + .max() + .unwrap_or(8) + .max(8); + + println!( + "{: println!("{json}"), + Err(e) => { + output.error("Output", &format!("JSON serialization failed: {e}")); + std::process::exit(1); + } + } + return; + } + + println!(); + println!(" Runtime: {} {}", rt.runtime.name, rt.runtime.version); + println!(" ID: {}", rt.id); + println!(" Built: {}", rt.builtAt); + println!(" Active: {}", if rt.active { "yes" } else { "no" }); + + if !rt.extensions.is_empty() { + println!(); + println!(" Extensions:"); + for ext in &rt.extensions { + let img = ext.imageId.as_deref().unwrap_or("-"); + println!(" {} {} (image: {})", ext.name, ext.version, img); + } + } + println!(); +} + +// ── Root authority output helper ────────────────────────────────────────────── + +pub fn print_root_authority(info: &Option, output: &OutputManager) { + if output.is_json() { + match serde_json::to_string(info) { + Ok(json) => println!("{json}"), + Err(e) => { + output.error("Output", &format!("JSON serialization failed: {e}")); + std::process::exit(1); + } + } + return; + } + + match info { + None => { + output.info( + "Root Authority", + "No root authority configured. Build and provision a runtime with avocado build to enable verified updates.", + ); + } + Some(ra) => { + println!(); + println!(" Root authority:"); + println!(); + println!(" Version: {}", ra.version); + println!(" Expires: {}", ra.expires); + println!(); + println!(" Trusted signing keys:"); + println!(); + println!(" {:<18} {:<12} ROLES", "KEY ID", "TYPE"); + for key in &ra.keys { + let short_id = &key.keyId[..key.keyId.len().min(16)]; + let roles_str = key.roles.join(", "); + println!(" {short_id:<18} {:<12} {roles_str}", key.keyType); + } + println!(); + } + } +} diff --git a/tests/ext_integration_tests.rs b/tests/ext_integration_tests.rs index fa99a33..7b50163 100644 --- a/tests/ext_integration_tests.rs +++ b/tests/ext_integration_tests.rs @@ -62,7 +62,7 @@ fn run_avocadoctl(args: &[&str]) -> std::process::Output { /// Test ext list with non-existent default directory #[test] fn test_ext_list_nonexistent_directory() { - let output = run_avocadoctl(&["ext", "list"]); + let output = run_avocadoctl_with_env(&["ext", "list"], &[("AVOCADO_TEST_MODE", "1")]); // The scanner handles missing directories gracefully — exits 0 and reports no extensions assert!( output.status.success(), @@ -199,7 +199,10 @@ fn test_invalid_config_file() { /// Test -c flag with nonexistent config file (should use defaults) #[test] fn test_nonexistent_config_file() { - let output = run_avocadoctl(&["-c", "/nonexistent/config.toml", "ext", "list"]); + let output = run_avocadoctl_with_env( + &["-c", "/nonexistent/config.toml", "ext", "list"], + &[("AVOCADO_TEST_MODE", "1")], + ); // Nonexistent config falls back to defaults; missing extensions directories are handled // gracefully by the scanner — the command should succeed and report no extensions. @@ -224,7 +227,10 @@ fn test_ext_list_empty_directory() { // Run avocadoctl ext list with empty extensions directory let output = run_avocadoctl_with_env( &["ext", "list"], - &[("AVOCADO_EXTENSIONS_PATH", extensions_dir.to_str().unwrap())], + &[ + ("AVOCADO_EXTENSIONS_PATH", extensions_dir.to_str().unwrap()), + ("AVOCADO_TEST_MODE", "1"), + ], ); assert!( diff --git a/tests/varlink_interface_tests.rs b/tests/varlink_interface_tests.rs new file mode 100644 index 0000000..34de562 --- /dev/null +++ b/tests/varlink_interface_tests.rs @@ -0,0 +1,293 @@ +//! Integration tests that exercise the full varlink client → daemon → service path. +//! +//! Each test starts a real `avocadoctl serve` daemon on a temporary Unix socket, +//! then invokes CLI commands with `--socket` pointing at it. This proves that: +//! - The CLI routes requests through the daemon (not direct service calls) +//! - The daemon serialises concurrent callers on the socket +//! - Error messages are correct when the daemon is not running + +use std::fs; +use std::path::PathBuf; +use std::process::{Child, Command}; +use std::time::{Duration, Instant}; +use tempfile::TempDir; + +// ── helpers ────────────────────────────────────────────────────────────────── + +fn get_binary_path() -> PathBuf { + let mut path = std::env::current_dir().expect("Failed to get current directory"); + path.push("target"); + path.push("debug"); + path.push("avocadoctl"); + path +} + +fn fixtures_path() -> PathBuf { + std::env::current_dir() + .expect("cwd") + .join("tests/fixtures") +} + +/// A running `avocadoctl serve` process bound to a temp socket. +/// Killed automatically when dropped. +struct TestDaemon { + child: Child, + socket_path: PathBuf, + /// Keep temp dir alive so the socket directory isn't removed while the daemon runs. + _temp_dir: TempDir, +} + +impl TestDaemon { + /// Start a daemon with `AVOCADO_TEST_MODE=1` and the test fixtures on PATH. + /// Blocks until the socket file appears (up to 5 s) or panics. + fn start() -> Self { + let temp_dir = TempDir::new().expect("temp dir"); + let socket_path = temp_dir.path().join("avocadoctl-test.sock"); + let socket_address = format!("unix:{}", socket_path.display()); + + let original_path = std::env::var("PATH").unwrap_or_default(); + let test_path = format!("{}:{}", fixtures_path().display(), original_path); + + let child = Command::new(get_binary_path()) + .args(["serve", "--address", &socket_address]) + .env("AVOCADO_TEST_MODE", "1") + .env("PATH", &test_path) + .spawn() + .expect("Failed to spawn daemon"); + + // Wait for the socket to be created (up to 5 s) + let deadline = Instant::now() + Duration::from_secs(5); + while Instant::now() < deadline { + if socket_path.exists() { + break; + } + std::thread::sleep(Duration::from_millis(50)); + } + assert!( + socket_path.exists(), + "Daemon socket should appear within 5 s at {}", + socket_path.display() + ); + + TestDaemon { + child, + socket_path, + _temp_dir: temp_dir, + } + } + + fn socket_address(&self) -> String { + format!("unix:{}", self.socket_path.display()) + } + + /// Run a CLI command routed through this daemon. + fn run(&self, args: &[&str]) -> std::process::Output { + let socket = self.socket_address(); + let original_path = std::env::var("PATH").unwrap_or_default(); + let test_path = format!("{}:{}", fixtures_path().display(), original_path); + + let mut all_args = vec!["--socket", socket.as_str()]; + all_args.extend_from_slice(args); + + Command::new(get_binary_path()) + .args(&all_args) + .env("AVOCADO_TEST_MODE", "1") + .env("PATH", &test_path) + .output() + .expect("Failed to execute avocadoctl") + } +} + +impl Drop for TestDaemon { + fn drop(&mut self) { + let _ = self.child.kill(); + let _ = self.child.wait(); + } +} + +// ── tests ───────────────────────────────────────────────────────────────────── + +/// The daemon starts and the socket is reachable. +#[test] +fn test_daemon_starts_and_accepts_connections() { + let daemon = TestDaemon::start(); + // If TestDaemon::start() returned, the socket exists and the daemon is running. + assert!(daemon.socket_path.exists(), "socket should exist"); +} + +/// `ext list` routed through the daemon returns extension data (or "no extensions"). +#[test] +fn test_ext_list_via_daemon() { + let daemon = TestDaemon::start(); + let output = daemon.run(&["ext", "list"]); + + assert!( + output.status.success(), + "ext list via daemon should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + + let stdout = String::from_utf8_lossy(&output.stdout); + // Either shows extensions or a "No extensions found" message — both are valid. + let valid = stdout.contains("Extension") || stdout.contains("No extensions found"); + assert!(valid, "ext list should produce a table or empty message; got: {stdout}"); +} + +/// `ext list` with an extensions directory populates the table. +#[test] +fn test_ext_list_with_extensions_via_daemon() { + let temp_dir = TempDir::new().expect("temp dir"); + let ext_dir = temp_dir.path().join("images"); + fs::create_dir_all(&ext_dir).expect("create ext dir"); + fs::create_dir(ext_dir.join("my-app")).expect("create extension dir"); + fs::create_dir(ext_dir.join("base-tools")).expect("create extension dir"); + + let socket_path = temp_dir.path().join("avocadoctl.sock"); + let socket_address = format!("unix:{}", socket_path.display()); + let original_path = std::env::var("PATH").unwrap_or_default(); + let test_path = format!("{}:{}", fixtures_path().display(), original_path); + + let mut child = Command::new(get_binary_path()) + .args(["serve", "--address", &socket_address]) + .env("AVOCADO_TEST_MODE", "1") + .env("AVOCADO_EXTENSIONS_PATH", ext_dir.to_str().unwrap()) + .env("PATH", &test_path) + .spawn() + .expect("spawn daemon"); + + let deadline = Instant::now() + Duration::from_secs(5); + while Instant::now() < deadline { + if socket_path.exists() { + break; + } + std::thread::sleep(Duration::from_millis(50)); + } + assert!(socket_path.exists(), "socket should appear"); + + let output = Command::new(get_binary_path()) + .args(["--socket", &socket_address, "ext", "list"]) + .env("AVOCADO_TEST_MODE", "1") + .env("AVOCADO_EXTENSIONS_PATH", ext_dir.to_str().unwrap()) + .env("PATH", &test_path) + .output() + .expect("run cli"); + + let _ = child.kill(); + let _ = child.wait(); + + assert!( + output.status.success(), + "ext list should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + + let stdout = String::from_utf8_lossy(&output.stdout); + assert!( + stdout.contains("my-app"), + "Should list my-app extension; got: {stdout}" + ); + assert!( + stdout.contains("base-tools"), + "Should list base-tools extension; got: {stdout}" + ); +} + +/// `ext merge` routed through the daemon calls the mock systemd-sysext. +#[test] +fn test_ext_merge_via_daemon() { + let daemon = TestDaemon::start(); + let output = daemon.run(&["ext", "merge"]); + + // In AVOCADO_TEST_MODE, merge uses mock-systemd-sysext which succeeds. + assert!( + output.status.success(), + "ext merge via daemon should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); +} + +/// `ext status` routed through the daemon returns status data. +#[test] +fn test_ext_status_via_daemon() { + let daemon = TestDaemon::start(); + let output = daemon.run(&["ext", "status"]); + + assert!( + output.status.success(), + "ext status via daemon should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); +} + +/// Top-level `merge` alias is routed through the daemon. +#[test] +fn test_merge_alias_via_daemon() { + let daemon = TestDaemon::start(); + let output = daemon.run(&["merge"]); + + assert!( + output.status.success(), + "merge alias via daemon should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); +} + +/// When no daemon is running, the CLI prints a helpful "Daemon Not Running" error. +#[test] +fn test_no_daemon_shows_helpful_error() { + let temp_dir = TempDir::new().expect("temp dir"); + let nonexistent_socket = format!( + "unix:{}/nonexistent.sock", + temp_dir.path().display() + ); + + let output = Command::new(get_binary_path()) + .args(["--socket", &nonexistent_socket, "ext", "list"]) + .output() + .expect("run cli"); + + assert!( + !output.status.success(), + "Should fail when daemon is not running" + ); + + let stderr = String::from_utf8_lossy(&output.stderr); + assert!( + stderr.contains("Daemon Not Running") || stderr.contains("Cannot connect"), + "Should show daemon-not-running error; got: {stderr}" + ); +} + +/// Two concurrent CLI invocations both succeed — the daemon serialises them. +#[test] +fn test_concurrent_requests_serialised_by_daemon() { + let daemon = TestDaemon::start(); + let socket = daemon.socket_address(); + let original_path = std::env::var("PATH").unwrap_or_default(); + let test_path = format!("{}:{}", fixtures_path().display(), original_path); + + // Spawn two merge requests at the same time + let mut handles = Vec::new(); + for _ in 0..2 { + let socket_clone = socket.clone(); + let path_clone = test_path.clone(); + let bin = get_binary_path(); + handles.push(std::thread::spawn(move || { + Command::new(bin) + .args(["--socket", &socket_clone, "ext", "merge"]) + .env("AVOCADO_TEST_MODE", "1") + .env("PATH", &path_clone) + .output() + .expect("run cli") + })); + } + + for handle in handles { + let output = handle.join().expect("thread panicked"); + assert!( + output.status.success(), + "Concurrent merge should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + } +} From 3ac0dda5afa501f52591d170bfb99638bdfcb081 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 20:31:30 -0500 Subject: [PATCH 08/27] systemd: ensure daemon socket is active before extension services avocado-extension.service and avocado-extension-initrd.service call avocadoctl refresh/unmerge, which now route through the varlink daemon socket. Add Before= ordering to avocadoctl.socket and avocadoctl.service so systemd guarantees the socket is listening before either extension service starts. --- systemd/avocadoctl.service | 1 + systemd/avocadoctl.socket | 1 + 2 files changed, 2 insertions(+) diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index 5b9f8ab..55ed649 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -2,6 +2,7 @@ Description=Avocado Control Daemon (Varlink) Requires=avocadoctl.socket After=avocadoctl.socket +Before=avocado-extension.service avocado-extension-initrd.service [Service] Type=simple diff --git a/systemd/avocadoctl.socket b/systemd/avocadoctl.socket index 913352e..66f19b6 100644 --- a/systemd/avocadoctl.socket +++ b/systemd/avocadoctl.socket @@ -1,5 +1,6 @@ [Unit] Description=Avocado Control Varlink Socket +Before=avocado-extension.service avocado-extension-initrd.service [Socket] ListenStream=/run/avocado/avocadoctl.sock From 412d0f6ac13e80985df002a750156c32130f7412 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 21:04:58 -0500 Subject: [PATCH 09/27] fix: add DefaultDependencies=no to socket and service to resolve initrd ordering cycle The socket unit's implicit After=sysinit.target (from DefaultDependencies=yes) created an ordering cycle with avocado-extension-initrd.service, which must run Before=sysinit.target but Requires=avocadoctl.socket. Replace with an explicit After=local-fs.target anchor so both units can start in early boot. --- systemd/avocadoctl.service | 3 ++- systemd/avocadoctl.socket | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index 55ed649..1e6f986 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -1,7 +1,8 @@ [Unit] Description=Avocado Control Daemon (Varlink) +DefaultDependencies=no Requires=avocadoctl.socket -After=avocadoctl.socket +After=local-fs.target avocadoctl.socket Before=avocado-extension.service avocado-extension-initrd.service [Service] diff --git a/systemd/avocadoctl.socket b/systemd/avocadoctl.socket index 66f19b6..cd573a7 100644 --- a/systemd/avocadoctl.socket +++ b/systemd/avocadoctl.socket @@ -1,5 +1,7 @@ [Unit] Description=Avocado Control Varlink Socket +DefaultDependencies=no +After=local-fs.target Before=avocado-extension.service avocado-extension-initrd.service [Socket] From 54af28dfda50d9f8490acc392021005b02d3cf2c Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 21:55:53 -0500 Subject: [PATCH 10/27] fix: remove Before= from avocadoctl.service to break ordering cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avocadoctl.service declared Before=avocado-extension*.service, pulling it into the early boot graph. But PrivateTmp=yes (and DefaultDependencies=yes) create an implicit After=systemd-tmpfiles-setup dependency, which comes after the extension services — forming a cycle. The socket unit already declares Before=avocado-extension*.service, which is sufficient. The daemon is socket-activated on demand: the extension service connects to the ready socket, systemd queues the daemon startup, and the client waits until the daemon answers. No explicit ordering on the service unit needed. --- systemd/avocadoctl.service | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index 1e6f986..5b9f8ab 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -1,9 +1,7 @@ [Unit] Description=Avocado Control Daemon (Varlink) -DefaultDependencies=no Requires=avocadoctl.socket -After=local-fs.target avocadoctl.socket -Before=avocado-extension.service avocado-extension-initrd.service +After=avocadoctl.socket [Service] Type=simple From af4beea43a94b80dbef9e2e147931a868babf89d Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 22:14:52 -0500 Subject: [PATCH 11/27] fix: varlink client must call .call() not .recv(), and test client must use varlink path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three bugs fixed together: 1. All varlink client calls in main.rs used .recv() which requires .send() to have been called first. Use .call() (= send + recv) instead. This caused IteratorOldReply on every RPC — the varlink routing introduced in the previous commit never worked. 2. Tests in varlink_interface_tests.rs set AVOCADO_TEST_MODE=1 on the client process, causing it to bypass varlink entirely via handle_direct(). Remove it from client invocations so tests actually exercise the daemon → varlink → service path. 3. list_extensions() returned ConfigurationError when the extensions directory did not exist. Treat NotFound as an empty list — consistent with how the direct path behaves and what ext_integration_tests expects. Also improve exit_with_rpc_error to show Debug (full chain) output when --verbose. --- src/main.rs | 40 ++++++++++++++++---------------- src/service/ext.rs | 12 +++++++--- src/varlink_client.rs | 8 +++++-- tests/varlink_interface_tests.rs | 19 +++++---------- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/main.rs b/src/main.rs index c9e4284..cf30366 100644 --- a/src/main.rs +++ b/src/main.rs @@ -180,14 +180,14 @@ fn main() { match ext_matches.subcommand() { Some(("list", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.list().recv() { + match client.list().call() { Ok(reply) => varlink_client::print_extensions(&reply.extensions, &output), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } } Some(("merge", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.merge().recv() { + match client.merge().call() { Ok(_) => output.success("Merge", "Extensions merged successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -196,7 +196,7 @@ fn main() { Some(("unmerge", unmerge_matches)) => { let unmount = unmerge_matches.get_flag("unmount"); let mut client = vl_ext::VarlinkClient::new(conn); - match client.unmerge(Some(unmount)).recv() { + match client.unmerge(Some(unmount)).call() { Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -204,7 +204,7 @@ fn main() { } Some(("refresh", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.refresh().recv() { + match client.refresh().call() { Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -212,7 +212,7 @@ fn main() { } Some(("status", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.status().recv() { + match client.status().call() { Ok(reply) => { varlink_client::print_extension_status(&reply.extensions, &output) } @@ -243,7 +243,7 @@ fn main() { .cloned() .collect(); let mut client = vl_hitl::VarlinkClient::new(conn); - match client.mount(server_ip, server_port, extensions).recv() { + match client.mount(server_ip, server_port, extensions).call() { Ok(_) => { output.success("HITL Mount", "Extensions mounted successfully") } @@ -258,7 +258,7 @@ fn main() { .cloned() .collect(); let mut client = vl_hitl::VarlinkClient::new(conn); - match client.unmount(extensions).recv() { + match client.unmount(extensions).call() { Ok(_) => { output.success("HITL Unmount", "Extensions unmounted successfully") } @@ -276,7 +276,7 @@ fn main() { Some(("root-authority", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ra::VarlinkClient::new(conn); - match client.show().recv() { + match client.show().call() { Ok(reply) => varlink_client::print_root_authority(&reply.authority, &output), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -288,7 +288,7 @@ fn main() { match runtime_matches.subcommand() { Some(("list", _)) => { let mut client = vl_rt::VarlinkClient::new(conn); - match client.list().recv() { + match client.list().call() { Ok(reply) => varlink_client::print_runtimes(&reply.runtimes, &output), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -299,14 +299,14 @@ fn main() { let mut client = vl_rt::VarlinkClient::new(conn); match client .add_from_url(url.clone(), auth_token) - .recv() + .call() { Ok(_) => output.success("Runtime Add", "Runtime added successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } } else if let Some(manifest) = add_matches.get_one::("manifest") { let mut client = vl_rt::VarlinkClient::new(conn); - match client.add_from_manifest(manifest.clone()).recv() { + match client.add_from_manifest(manifest.clone()).call() { Ok(_) => output.success("Runtime Add", "Runtime added successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -319,7 +319,7 @@ fn main() { .expect("id is required") .clone(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.remove(id).recv() { + match client.remove(id).call() { Ok(_) => output.success("Runtime Remove", "Runtime removed successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -331,7 +331,7 @@ fn main() { .expect("id is required") .clone(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.activate(id).recv() { + match client.activate(id).call() { Ok(_) => { output.success("Runtime Activate", "Runtime activated successfully") } @@ -345,7 +345,7 @@ fn main() { .expect("id is required") .clone(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.inspect(id).recv() { + match client.inspect(id).call() { Ok(reply) => varlink_client::print_runtime_detail(&reply.runtime, &output), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -372,7 +372,7 @@ fn main() { Some(("status", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.status().recv() { + match client.status().call() { Ok(reply) => { output.status_header("System Status"); varlink_client::print_extension_status(&reply.extensions, &output); @@ -385,7 +385,7 @@ fn main() { Some(("merge", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.merge().recv() { + match client.merge().call() { Ok(_) => output.success("Merge", "Extensions merged successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -395,7 +395,7 @@ fn main() { let unmount = unmerge_matches.get_flag("unmount"); let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.unmerge(Some(unmount)).recv() { + match client.unmerge(Some(unmount)).call() { Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -404,7 +404,7 @@ fn main() { Some(("refresh", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.refresh().recv() { + match client.refresh().call() { Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -421,7 +421,7 @@ fn main() { .collect(); let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.enable(extensions, os_release).recv() { + match client.enable(extensions, os_release).call() { Ok(reply) => { if !output.is_json() { output.success( @@ -447,7 +447,7 @@ fn main() { .map(|values| values.cloned().collect()); let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.disable(extensions, Some(all), os_release).recv() { + match client.disable(extensions, Some(all), os_release).call() { Ok(reply) => { if !output.is_json() { output.success( diff --git a/src/service/ext.rs b/src/service/ext.rs index 8a56386..848ddb2 100644 --- a/src/service/ext.rs +++ b/src/service/ext.rs @@ -15,9 +15,15 @@ fn quiet_output() -> OutputManager { /// List all available extensions from the extensions directory. pub fn list_extensions(config: &Config) -> Result, AvocadoError> { let extensions_path = config.get_extensions_dir(); - let entries = fs::read_dir(&extensions_path).map_err(|e| AvocadoError::ConfigurationError { - message: format!("Cannot read extensions directory '{extensions_path}': {e}"), - })?; + let entries = match fs::read_dir(&extensions_path) { + Ok(e) => e, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Vec::new()), + Err(e) => { + return Err(AvocadoError::ConfigurationError { + message: format!("Cannot read extensions directory '{extensions_path}': {e}"), + }) + } + }; let mut result = Vec::new(); for entry in entries.flatten() { diff --git a/src/varlink_client.rs b/src/varlink_client.rs index 1b44712..4c1b42f 100644 --- a/src/varlink_client.rs +++ b/src/varlink_client.rs @@ -30,8 +30,12 @@ pub fn connect_or_exit(address: &str, output: &OutputManager) -> Arc ! { - output.error("RPC Error", &err.to_string()); +pub fn exit_with_rpc_error(err: impl std::fmt::Display + std::fmt::Debug, output: &OutputManager) -> ! { + if output.is_verbose() { + output.error("RPC Error", &format!("{err:?}")); + } else { + output.error("RPC Error", &err.to_string()); + } std::process::exit(1); } diff --git a/tests/varlink_interface_tests.rs b/tests/varlink_interface_tests.rs index 34de562..7cdcd66 100644 --- a/tests/varlink_interface_tests.rs +++ b/tests/varlink_interface_tests.rs @@ -83,16 +83,15 @@ impl TestDaemon { /// Run a CLI command routed through this daemon. fn run(&self, args: &[&str]) -> std::process::Output { let socket = self.socket_address(); - let original_path = std::env::var("PATH").unwrap_or_default(); - let test_path = format!("{}:{}", fixtures_path().display(), original_path); let mut all_args = vec!["--socket", socket.as_str()]; all_args.extend_from_slice(args); + // Do NOT set AVOCADO_TEST_MODE here: the client must use the varlink path. + // The daemon (started above with AVOCADO_TEST_MODE=1) handles the actual + // service calls with mock executables. Command::new(get_binary_path()) .args(&all_args) - .env("AVOCADO_TEST_MODE", "1") - .env("PATH", &test_path) .output() .expect("Failed to execute avocadoctl") } @@ -164,11 +163,9 @@ fn test_ext_list_with_extensions_via_daemon() { } assert!(socket_path.exists(), "socket should appear"); + // Client must NOT have AVOCADO_TEST_MODE set so it routes through varlink. let output = Command::new(get_binary_path()) .args(["--socket", &socket_address, "ext", "list"]) - .env("AVOCADO_TEST_MODE", "1") - .env("AVOCADO_EXTENSIONS_PATH", ext_dir.to_str().unwrap()) - .env("PATH", &test_path) .output() .expect("run cli"); @@ -263,20 +260,16 @@ fn test_no_daemon_shows_helpful_error() { fn test_concurrent_requests_serialised_by_daemon() { let daemon = TestDaemon::start(); let socket = daemon.socket_address(); - let original_path = std::env::var("PATH").unwrap_or_default(); - let test_path = format!("{}:{}", fixtures_path().display(), original_path); - // Spawn two merge requests at the same time + // Spawn two merge requests at the same time. + // Clients must NOT set AVOCADO_TEST_MODE — they must route through varlink. let mut handles = Vec::new(); for _ in 0..2 { let socket_clone = socket.clone(); - let path_clone = test_path.clone(); let bin = get_binary_path(); handles.push(std::thread::spawn(move || { Command::new(bin) .args(["--socket", &socket_clone, "ext", "merge"]) - .env("AVOCADO_TEST_MODE", "1") - .env("PATH", &path_clone) .output() .expect("run cli") })); From 2b1ba7e29d1019823908c695c69c14360d06a0e7 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 22:16:39 -0500 Subject: [PATCH 12/27] chore: fix clippy warnings and apply cargo fmt - Inline format string literals (print_literal, uninlined_format_args) - Use .cloned() instead of .map(|s| s.clone()) --- src/main.rs | 23 +- src/service/runtime.rs | 6 +- src/update.rs | 11 +- src/varlink/org_avocado_Extensions.rs | 629 ++++++++++++++++++++++- src/varlink/org_avocado_Hitl.rs | 347 ++++++++++++- src/varlink/org_avocado_RootAuthority.rs | 261 +++++++++- src/varlink/org_avocado_Runtimes.rs | 591 ++++++++++++++++++++- src/varlink_client.rs | 50 +- tests/varlink_interface_tests.rs | 14 +- 9 files changed, 1863 insertions(+), 69 deletions(-) diff --git a/src/main.rs b/src/main.rs index cf30366..7b284d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,7 +162,7 @@ fn main() { // Resolve socket address: CLI flag > config > default let socket_address = matches .get_one::("socket") - .map(|s| s.clone()) + .cloned() .unwrap_or_else(|| config.socket_address().to_string()); // In test mode, skip the varlink daemon and call service functions directly. @@ -234,9 +234,7 @@ fn main() { .get_one::("server-ip") .expect("server-ip is required") .clone(); - let server_port = mount_matches - .get_one::("server-port") - .map(|s| s.clone()); + let server_port = mount_matches.get_one::("server-port").cloned(); let extensions: Vec = mount_matches .get_many::("extension") .expect("at least one extension is required") @@ -244,9 +242,7 @@ fn main() { .collect(); let mut client = vl_hitl::VarlinkClient::new(conn); match client.mount(server_ip, server_port, extensions).call() { - Ok(_) => { - output.success("HITL Mount", "Extensions mounted successfully") - } + Ok(_) => output.success("HITL Mount", "Extensions mounted successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -297,10 +293,7 @@ fn main() { if let Some(url) = add_matches.get_one::("url") { let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); let mut client = vl_rt::VarlinkClient::new(conn); - match client - .add_from_url(url.clone(), auth_token) - .call() - { + match client.add_from_url(url.clone(), auth_token).call() { Ok(_) => output.success("Runtime Add", "Runtime added successfully"), Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -411,9 +404,7 @@ fn main() { json_ok(&output); } Some(("enable", enable_matches)) => { - let os_release = enable_matches - .get_one::("os_release") - .cloned(); + let os_release = enable_matches.get_one::("os_release").cloned(); let extensions: Vec = enable_matches .get_many::("extensions") .unwrap() @@ -438,9 +429,7 @@ fn main() { json_ok(&output); } Some(("disable", disable_matches)) => { - let os_release = disable_matches - .get_one::("os_release") - .cloned(); + let os_release = disable_matches.get_one::("os_release").cloned(); let all = disable_matches.get_flag("all"); let extensions: Option> = disable_matches .get_many::("extensions") diff --git a/src/service/runtime.rs b/src/service/runtime.rs index 2185f4a..4ba79ea 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -39,7 +39,11 @@ pub fn list_runtimes(config: &Config) -> Result, AvocadoError> } /// Add a runtime from a TUF repository URL. -pub fn add_from_url(url: &str, auth_token: Option<&str>, config: &Config) -> Result<(), AvocadoError> { +pub fn add_from_url( + url: &str, + auth_token: Option<&str>, + config: &Config, +) -> Result<(), AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); update::perform_update(url, base_path, auth_token, false)?; diff --git a/src/update.rs b/src/update.rs index a03b8f0..79afa19 100644 --- a/src/update.rs +++ b/src/update.rs @@ -32,7 +32,12 @@ pub enum UpdateError { MetadataError(String), } -pub fn perform_update(url: &str, base_dir: &Path, auth_token: Option<&str>, verbose: bool) -> Result<(), UpdateError> { +pub fn perform_update( + url: &str, + base_dir: &Path, + auth_token: Option<&str>, + verbose: bool, +) -> Result<(), UpdateError> { let url = url.trim_end_matches('/'); // 1. Load the local trust anchor @@ -337,9 +342,7 @@ fn verify_delegation_hash( let actual_hash = sha256_hex(raw_json.as_bytes()); let hashes = meta_entry.hashes.as_ref().ok_or_else(|| { - UpdateError::MetadataError(format!( - "No hashes in snapshot.json for '{role_path}'" - )) + UpdateError::MetadataError(format!("No hashes in snapshot.json for '{role_path}'")) })?; let expected_hash = hex_encode(hashes.sha256.as_ref()); if actual_hash != expected_hash { diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index 2bb6182..4e2962c 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1 +1,628 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> ()\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> ()\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> ()\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + CommandFailed(Option), + ConfigurationError(Option), + ExtensionNotFound(Option), + MergeFailed(Option), + UnmergeFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::CommandFailed(v) => { + write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) + } + ErrorKind::ConfigurationError(v) => { + write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) + } + ErrorKind::ExtensionNotFound(v) => { + write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) + } + ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), + ErrorKind::UnmergeFailed(v) => { + write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.CommandFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::CommandFailed(v), + Err(_) => ErrorKind::CommandFailed(None), + }, + _ => ErrorKind::CommandFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ConfigurationError" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ConfigurationError(v), + Err(_) => ErrorKind::ConfigurationError(None), + }, + _ => ErrorKind::ConfigurationError(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ExtensionNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ExtensionNotFound(v), + Err(_) => ErrorKind::ExtensionNotFound(None), + }, + _ => ErrorKind::ExtensionNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MergeFailed(v), + Err(_) => ErrorKind::MergeFailed(None), + }, + _ => ErrorKind::MergeFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.UnmergeFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmergeFailed(v), + Err(_) => ErrorKind::UnmergeFailed(None), + }, + _ => ErrorKind::UnmergeFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_command_failed( + &mut self, + r#command: String, + r#message: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.CommandFailed", + Some( + serde_json::to_value(CommandFailed_Args { + r#command, + r#message, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ConfigurationError", + Some( + serde_json::to_value(ConfigurationError_Args { r#message }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ExtensionNotFound", + Some( + serde_json::to_value(ExtensionNotFound_Args { r#name }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.MergeFailed", + Some( + serde_json::to_value(MergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.UnmergeFailed", + Some( + serde_json::to_value(UnmergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Extension { + pub r#name: String, + pub r#version: Option, + pub r#path: String, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isDirectory: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ExtensionStatus { + pub r#name: String, + pub r#version: Option, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isMerged: bool, + pub r#origin: Option, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct CommandFailed_Args { + pub r#command: String, + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ConfigurationError_Args { + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ExtensionNotFound_Args { + pub r#name: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Reply { + pub r#disabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Disable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#extensions: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#all: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Disable: VarlinkCallError { + fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Disable_Reply { + r#disabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Disable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Reply { + pub r#enabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Enable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Args { + pub r#extensions: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Enable: VarlinkCallError { + fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Enable_Reply { + r#enabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Enable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#extensions }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Reply {} +impl varlink::VarlinkReply for Merge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Args {} +#[allow(dead_code)] +pub trait Call_Merge: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Merge for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Reply {} +impl varlink::VarlinkReply for Refresh_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Args {} +#[allow(dead_code)] +pub trait Call_Refresh: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Refresh for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for Status_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Args {} +#[allow(dead_code)] +pub trait Call_Status: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(Status_Reply { r#extensions }.into()) + } +} +impl Call_Status for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Reply {} +impl varlink::VarlinkReply for Unmerge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#unmount: Option, +} +#[allow(dead_code)] +pub trait Call_Unmerge: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Unmerge for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn disable( + &self, + call: &mut dyn Call_Disable, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn enable( + &self, + call: &mut dyn Call_Enable, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; + fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; + fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; + fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn merge(&mut self) -> varlink::MethodCall; + fn refresh(&mut self) -> varlink::MethodCall; + fn status(&mut self) -> varlink::MethodCall; + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Disable", + Disable_Args { + r#extensions, + r#all, + r#osRelease, + }, + ) + } + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Enable", + Enable_Args { + r#extensions, + r#osRelease, + }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.List", + List_Args {}, + ) + } + fn merge(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Merge", + Merge_Args {}, + ) + } + fn refresh(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Refresh", + Refresh_Args {}, + ) + } + fn status(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Status", + Status_Args {}, + ) + } + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Unmerge", + Unmerge_Args { r#unmount }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> ()\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> ()\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> ()\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Extensions" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Extensions.Disable" => { + if let Some(args) = req.parameters.clone() { + let args: Disable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.disable( + call as &mut dyn Call_Disable, + args.r#extensions, + args.r#all, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.Enable" => { + if let Some(args) = req.parameters.clone() { + let args: Enable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.enable( + call as &mut dyn Call_Enable, + args.r#extensions, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), + "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), + "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), + "org.avocado.Extensions.Unmerge" => { + if let Some(args) = req.parameters.clone() { + let args: Unmerge_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 7720a1d..59a04ea 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1 +1,346 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + MountFailed(Option), + UnmountFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), + ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e + { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MountFailed(v), + Err(_) => ErrorKind::MountFailed(None), + }, + _ => ErrorKind::MountFailed(None), + }, + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmountFailed(v), + Err(_) => ErrorKind::UnmountFailed(None), + }, + _ => ErrorKind::UnmountFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.MountFailed", + Some( + serde_json::to_value(MountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmount_failed( + &mut self, + r#extension: String, + r#reason: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.UnmountFailed", + Some( + serde_json::to_value(UnmountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Reply {} +impl varlink::VarlinkReply for Mount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Args { + pub r#serverIp: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#serverPort: Option, + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Mount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Mount for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Reply {} +impl varlink::VarlinkReply for Unmount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Args { + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Unmount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Unmount for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn mount( + &self, + call: &mut dyn Call_Mount, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn unmount( + &self, + call: &mut dyn Call_Unmount, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall; + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Mount", + Mount_Args { + r#serverIp, + r#serverPort, + r#extensions, + }, + ) + } + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Unmount", + Unmount_Args { r#extensions }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Hitl" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Hitl.Mount" => { + if let Some(args) = req.parameters.clone() { + let args: Mount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.mount( + call as &mut dyn Call_Mount, + args.r#serverIp, + args.r#serverPort, + args.r#extensions, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Hitl.Unmount" => { + if let Some(args) = req.parameters.clone() { + let args: Unmount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmount(call as &mut dyn Call_Unmount, args.r#extensions) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index 029ad69..c8d4a18 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1 +1,260 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + NoRootAuthority(Option), + ParseFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::NoRootAuthority(v) => { + write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) + } + ErrorKind::ParseFailed(v) => { + write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.NoRootAuthority" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::NoRootAuthority(v), + Err(_) => ErrorKind::NoRootAuthority(None), + }, + _ => ErrorKind::NoRootAuthority(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.ParseFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ParseFailed(v), + Err(_) => ErrorKind::ParseFailed(None), + }, + _ => ErrorKind::ParseFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_no_root_authority(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.NoRootAuthority", + None, + )) + } + fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.ParseFailed", + Some( + serde_json::to_value(ParseFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RootAuthorityInfo { + pub r#version: i64, + pub r#expires: String, + pub r#keys: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#TrustedKey { + pub r#keyId: String, + pub r#keyType: String, + pub r#roles: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct NoRootAuthority_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ParseFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Reply { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authority: Option, +} +impl varlink::VarlinkReply for Show_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Args {} +#[allow(dead_code)] +pub trait Call_Show: VarlinkCallError { + fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { + self.reply_struct(Show_Reply { r#authority }.into()) + } +} +impl Call_Show for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn show(&mut self) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn show(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.RootAuthority.Show", + Show_Args {}, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.RootAuthority" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index 1baf5c4..4cfb6bd 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1 +1,590 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> ()\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> ()\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> ()\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + AmbiguousRuntimeId(Option), + RemoveActiveRuntime(Option), + RuntimeNotFound(Option), + StagingFailed(Option), + UpdateFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::AmbiguousRuntimeId(v) => { + write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) + } + ErrorKind::RemoveActiveRuntime(v) => { + write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) + } + ErrorKind::RuntimeNotFound(v) => { + write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) + } + ErrorKind::StagingFailed(v) => { + write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) + } + ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::AmbiguousRuntimeId(v), + Err(_) => ErrorKind::AmbiguousRuntimeId(None), + }, + _ => ErrorKind::AmbiguousRuntimeId(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RemoveActiveRuntime" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RemoveActiveRuntime(v), + Err(_) => ErrorKind::RemoveActiveRuntime(None), + }, + _ => ErrorKind::RemoveActiveRuntime(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RuntimeNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RuntimeNotFound(v), + Err(_) => ErrorKind::RuntimeNotFound(None), + }, + _ => ErrorKind::RuntimeNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::StagingFailed(v), + Err(_) => ErrorKind::StagingFailed(None), + }, + _ => ErrorKind::StagingFailed(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UpdateFailed(v), + Err(_) => ErrorKind::UpdateFailed(None), + }, + _ => ErrorKind::UpdateFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_ambiguous_runtime_id( + &mut self, + r#id: String, + r#candidates: Vec, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.AmbiguousRuntimeId", + Some( + serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RemoveActiveRuntime", + None, + )) + } + fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RuntimeNotFound", + Some( + serde_json::to_value(RuntimeNotFound_Args { r#id }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.StagingFailed", + Some( + serde_json::to_value(StagingFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.UpdateFailed", + Some( + serde_json::to_value(UpdateFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ManifestExtension { + pub r#name: String, + pub r#version: String, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Runtime { + pub r#id: String, + pub r#manifestVersion: i64, + pub r#builtAt: String, + pub r#runtime: RuntimeInfo, + pub r#extensions: Vec, + pub r#active: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RuntimeInfo { + pub r#name: String, + pub r#version: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AmbiguousRuntimeId_Args { + pub r#id: String, + pub r#candidates: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RemoveActiveRuntime_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RuntimeNotFound_Args { + pub r#id: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct StagingFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UpdateFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Reply {} +impl varlink::VarlinkReply for Activate_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Activate: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Activate for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Reply {} +impl varlink::VarlinkReply for AddFromManifest_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Args { + pub r#manifestPath: String, +} +#[allow(dead_code)] +pub trait Call_AddFromManifest: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_AddFromManifest for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Reply {} +impl varlink::VarlinkReply for AddFromUrl_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Args { + pub r#url: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authToken: Option, +} +#[allow(dead_code)] +pub trait Call_AddFromUrl: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_AddFromUrl for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Reply { + pub r#runtime: Runtime, +} +impl varlink::VarlinkReply for Inspect_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Inspect: VarlinkCallError { + fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { + self.reply_struct(Inspect_Reply { r#runtime }.into()) + } +} +impl Call_Inspect for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#runtimes: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#runtimes }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Reply {} +impl varlink::VarlinkReply for Remove_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Remove: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Remove for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; + fn add_from_manifest( + &self, + call: &mut dyn Call_AddFromManifest, + r#manifestPath: String, + ) -> varlink::Result<()>; + fn add_from_url( + &self, + call: &mut dyn Call_AddFromUrl, + r#url: String, + r#authToken: Option, + ) -> varlink::Result<()>; + fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall; + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall; + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + ) -> varlink::MethodCall; + fn inspect(&mut self, r#id: String) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn remove(&mut self, r#id: String) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Activate", + Activate_Args { r#id }, + ) + } + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromManifest", + AddFromManifest_Args { r#manifestPath }, + ) + } + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromUrl", + AddFromUrl_Args { r#url, r#authToken }, + ) + } + fn inspect(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Inspect", + Inspect_Args { r#id }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.List", + List_Args {}, + ) + } + fn remove(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Remove", + Remove_Args { r#id }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> ()\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> ()\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> ()\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Runtimes" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Runtimes.Activate" => { + if let Some(args) = req.parameters.clone() { + let args: Activate_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .activate(call as &mut dyn Call_Activate, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromManifest" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromManifest_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_manifest( + call as &mut dyn Call_AddFromManifest, + args.r#manifestPath, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromUrl" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromUrl_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_url( + call as &mut dyn Call_AddFromUrl, + args.r#url, + args.r#authToken, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.Inspect" => { + if let Some(args) = req.parameters.clone() { + let args: Inspect_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Runtimes.Remove" => { + if let Some(args) = req.parameters.clone() { + let args: Remove_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.remove(call as &mut dyn Call_Remove, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink_client.rs b/src/varlink_client.rs index 4c1b42f..eb1612c 100644 --- a/src/varlink_client.rs +++ b/src/varlink_client.rs @@ -30,7 +30,10 @@ pub fn connect_or_exit(address: &str, output: &OutputManager) -> Arc ! { +pub fn exit_with_rpc_error( + err: impl std::fmt::Display + std::fmt::Debug, + output: &OutputManager, +) -> ! { if output.is_verbose() { output.error("RPC Error", &format!("{err:?}")); } else { @@ -60,24 +63,12 @@ pub fn print_extensions(extensions: &[vl_ext::Extension], output: &OutputManager let name_width = extensions .iter() - .map(|e| { - e.name.len() - + e.version - .as_ref() - .map(|v| v.len() + 1) - .unwrap_or(0) - }) + .map(|e| e.name.len() + e.version.as_ref().map(|v| v.len() + 1).unwrap_or(0)) .max() .unwrap_or(9) .max(9); - println!( - "{: Date: Fri, 6 Mar 2026 22:52:20 -0500 Subject: [PATCH 13/27] fix: restore DefaultDependencies=no on service to allow early socket activation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With DefaultDependencies=yes, avocadoctl.service implicitly gets After=sysinit.target. When socket-activated by avocado-extension-initrd.service (which runs Before=sysinit.target), systemd cannot start the daemon until sysinit completes — a deadlock that causes the extension service to time out. Removing DefaultDependencies avoids the implicit ordering constraint, allowing socket activation to start the daemon immediately in early boot. The Before= declarations are intentionally absent (removed in a prior commit) to prevent the separate ordering cycle that was present previously. --- systemd/avocadoctl.service | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index 5b9f8ab..f6e0786 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -1,7 +1,8 @@ [Unit] Description=Avocado Control Daemon (Varlink) +DefaultDependencies=no Requires=avocadoctl.socket -After=avocadoctl.socket +After=local-fs.target avocadoctl.socket [Service] Type=simple From 02bf307f669013e18e4f571efefa32376a8927f8 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 23:30:39 -0500 Subject: [PATCH 14/27] fix: remove ProtectSystem=full and PrivateTmp=yes from daemon service These sandboxing directives create a private mount namespace for the daemon. Loop mounts for extensions created inside the daemon are invisible to the host, causing systemd-sysext merge to see empty directories and fail silently. --- docs/features/varlink-ipc-interface.md | 2 -- systemd/avocadoctl.service | 2 -- 2 files changed, 4 deletions(-) diff --git a/docs/features/varlink-ipc-interface.md b/docs/features/varlink-ipc-interface.md index f8d4745..3f2696e 100644 --- a/docs/features/varlink-ipc-interface.md +++ b/docs/features/varlink-ipc-interface.md @@ -173,8 +173,6 @@ After=avocadoctl.socket Type=simple ExecStart=/usr/bin/avocadoctl serve ProtectHome=yes -ProtectSystem=full -PrivateTmp=yes NoNewPrivileges=yes [Install] diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index f6e0786..7f485f9 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -8,8 +8,6 @@ After=local-fs.target avocadoctl.socket Type=simple ExecStart=/usr/bin/avocadoctl serve ProtectHome=yes -ProtectSystem=full -PrivateTmp=yes NoNewPrivileges=yes [Install] From 64dd0645d76d7104d489090b39dc86303fbc6d03 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Fri, 6 Mar 2026 23:43:28 -0500 Subject: [PATCH 15/27] fix: remove ProtectHome=yes which also creates a private mount namespace ProtectHome=yes makes /home, /root, /run/user inaccessible by creating a mount namespace as a side effect. Loop mounts created by the daemon for extensions remain trapped in this namespace and are invisible to the host, so systemd-sysext still sees empty directories. --- docs/features/varlink-ipc-interface.md | 1 - systemd/avocadoctl.service | 1 - 2 files changed, 2 deletions(-) diff --git a/docs/features/varlink-ipc-interface.md b/docs/features/varlink-ipc-interface.md index 3f2696e..7e7f224 100644 --- a/docs/features/varlink-ipc-interface.md +++ b/docs/features/varlink-ipc-interface.md @@ -172,7 +172,6 @@ After=avocadoctl.socket [Service] Type=simple ExecStart=/usr/bin/avocadoctl serve -ProtectHome=yes NoNewPrivileges=yes [Install] diff --git a/systemd/avocadoctl.service b/systemd/avocadoctl.service index 7f485f9..282ead8 100644 --- a/systemd/avocadoctl.service +++ b/systemd/avocadoctl.service @@ -7,7 +7,6 @@ After=local-fs.target avocadoctl.socket [Service] Type=simple ExecStart=/usr/bin/avocadoctl serve -ProtectHome=yes NoNewPrivileges=yes [Install] From 2956b98eeb755df50ed9dbf12ff0044b2743ca91 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 13:43:01 -0400 Subject: [PATCH 16/27] fix: return extension status data over varlink instead of printing to daemon stdout status_extensions() was calling show_enhanced_status() which printed directly to stdout (captured by systemd journal) and returned an empty vector. The CLI client received no data and displayed "No extensions currently merged." regardless of actual state. Add collect_extension_status() that gathers the same data but returns structured ExtensionStatus values through the varlink reply. --- src/commands/ext.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/service/ext.rs | 4 +- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/commands/ext.rs b/src/commands/ext.rs index f2e34f0..3f59fca 100644 --- a/src/commands/ext.rs +++ b/src/commands/ext.rs @@ -1007,6 +1007,96 @@ pub fn status_extensions(config: &Config, output: &OutputManager) { } } +/// Collect extension status data for the varlink Status RPC. +/// +/// This gathers the same data as `show_enhanced_status` but returns it as +/// structured `ExtensionStatus` values instead of printing to stdout. +pub(crate) fn collect_extension_status( + config: &Config, +) -> Result, SystemdError> { + use crate::varlink::org_avocado_Extensions::ExtensionStatus; + + let base_dir = config.get_avocado_base_dir(); + let base_path = std::path::Path::new(&base_dir); + let active_manifest = crate::manifest::RuntimeManifest::load_active(base_path); + let manifest_extensions = active_manifest + .as_ref() + .map(|m| m.extensions.as_slice()) + .unwrap_or(&[]); + + let available_extensions = scan_extensions_from_all_sources_with_verbosity(false)?; + let mounted_sysext = get_mounted_systemd_extensions("systemd-sysext")?; + let mounted_confext = get_mounted_systemd_extensions("systemd-confext")?; + + // Collect all unique extension names (with versions if present) + let mut all_names = std::collections::HashSet::new(); + for ext in &available_extensions { + if let Some(ver) = &ext.version { + all_names.insert(format!("{}-{}", ext.name, ver)); + } else { + all_names.insert(ext.name.clone()); + } + } + for ext in &mounted_sysext { + all_names.insert(ext.name.clone()); + } + for ext in &mounted_confext { + all_names.insert(ext.name.clone()); + } + + let mut result: Vec = all_names + .into_iter() + .map(|ext_name| { + let available_ext = available_extensions.iter().find(|e| { + if let Some(ver) = &e.version { + format!("{}-{}", e.name, ver) == ext_name + } else { + e.name == ext_name + } + }); + + let is_sysext_mounted = mounted_sysext.iter().any(|e| e.name == ext_name); + let is_confext_mounted = mounted_confext.iter().any(|e| e.name == ext_name); + let is_merged = is_sysext_mounted || is_confext_mounted; + + let (is_sysext, is_confext) = if let Some(ext) = available_ext { + (ext.is_sysext, ext.is_confext) + } else { + (is_sysext_mounted, is_confext_mounted) + }; + + let origin = available_ext.map(get_extension_origin_short); + + let image_id_str = lookup_extension_short_id(&ext_name, manifest_extensions); + let image_id = if image_id_str == "-" { + None + } else { + Some(image_id_str) + }; + + let (name, version) = if let Some(ext) = available_ext { + (ext.name.clone(), ext.version.clone()) + } else { + (ext_name, None) + }; + + ExtensionStatus { + name, + version, + isSysext: is_sysext, + isConfext: is_confext, + isMerged: is_merged, + origin, + imageId: image_id, + } + }) + .collect(); + + result.sort_by(|a, b| a.name.cmp(&b.name)); + + Ok(result) +} + /// Show enhanced status with extension origins and HITL information pub(crate) fn show_enhanced_status( config: &Config, diff --git a/src/service/ext.rs b/src/service/ext.rs index 848ddb2..e35fadc 100644 --- a/src/service/ext.rs +++ b/src/service/ext.rs @@ -272,7 +272,5 @@ pub fn disable_extensions( pub fn status_extensions( config: &Config, ) -> Result, AvocadoError> { - let output = quiet_output(); - ext::show_enhanced_status(config, &output).map_err(AvocadoError::from)?; - Ok(vec![]) + ext::collect_extension_status(config).map_err(AvocadoError::from) } From 6735767c5431d3c418797c7cfa03db465570958e Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 14:24:46 -0400 Subject: [PATCH 17/27] fix: refresh extensions after runtime add/activate via varlink daemon The service layer functions (add_from_url, add_from_manifest, activate_runtime) did not call refresh_extensions after activating a runtime. The CLI direct path did this in commands/runtime.rs, but the varlink daemon path skipped it, leaving old extensions merged after a deploy. --- src/service/runtime.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service/runtime.rs b/src/service/runtime.rs index 4ba79ea..d2fad45 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -47,6 +47,7 @@ pub fn add_from_url( let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); update::perform_update(url, base_path, auth_token, false)?; + super::ext::refresh_extensions(config)?; Ok(()) } @@ -68,6 +69,7 @@ pub fn add_from_manifest(manifest_path: &str, config: &Config) -> Result<(), Avo staging::validate_manifest_images(&manifest, base_path)?; staging::stage_manifest(&manifest, &manifest_content, base_path, false)?; staging::activate_runtime(&manifest.id, base_path)?; + super::ext::refresh_extensions(config)?; Ok(()) } @@ -95,6 +97,7 @@ pub fn activate_runtime(id_prefix: &str, config: &Config) -> Result<(), AvocadoE } staging::activate_runtime(&matched.id, base_path)?; + super::ext::refresh_extensions(config)?; Ok(()) } From 4dd87715b790cfb30ac7e646accb5c28d272f636 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 14:36:49 -0400 Subject: [PATCH 18/27] fix: unmerge extensions before unmounting HITL NFS shares in daemon path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The service layer unmounted NFS shares while extensions were still merged as sysext/confext overlays, leaving broken overlay state. Match the CLI path ordering: unmerge → cleanup dropins → reload → unmount → merge remaining. --- src/service/hitl.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/service/hitl.rs b/src/service/hitl.rs index fcd7d1a..52ca3e7 100644 --- a/src/service/hitl.rs +++ b/src/service/hitl.rs @@ -120,12 +120,22 @@ pub fn unmount(extensions: &[String]) -> Result<(), AvocadoError> { } } - // Step 2: Clean up service drop-ins + // Step 2: Unmerge extensions before unmounting NFS shares. + // Extensions must be unmerged first so the sysext/confext overlay no longer + // references the HITL mount points we are about to remove. + let _ = crate::service::ext::unmerge_extensions(false); + + // Step 3: Clean up service drop-ins for (extension, services) in &extension_services { let _ = hitl::cleanup_service_dropins(extension, services, &output); } - // Step 3: Unmount each extension + // Step 4: Reload systemd to apply drop-in removals + if !extension_services.is_empty() { + let _ = hitl::systemd_daemon_reload(&output); + } + + // Step 5: Unmount each extension for extension in extensions { let mount_point = format!("{extensions_base_dir}/{extension}"); @@ -160,12 +170,9 @@ pub fn unmount(extensions: &[String]) -> Result<(), AvocadoError> { } } - // Reload systemd - let _ = hitl::systemd_daemon_reload(&output); - - // Refresh extensions + // Step 6: Merge remaining extensions (without the removed HITL ones) let config = Config::default(); - let _ = crate::service::ext::refresh_extensions(&config); + let _ = crate::service::ext::merge_extensions(&config); Ok(()) } From aa5603da7a05c280085cb49978c1bbaa24a5c7ea Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 15:10:47 -0400 Subject: [PATCH 19/27] fix: forward daemon log messages (merge/unmerge/refresh) back to CLI caller Thread OutputManager through the post-merge and pre-unmerge command chains so that log messages are captured in daemon mode and returned via varlink replies instead of being printed to the daemon's journal. Updated varlink interfaces to return log vectors from merge, unmerge, refresh, and runtime add/activate operations. --- src/commands/ext.rs | 91 ++- src/main.rs | 45 +- src/output.rs | 95 +++- src/service/ext.rs | 28 +- src/service/runtime.rs | 24 +- src/varlink/org.avocado.Extensions.varlink | 6 +- src/varlink/org.avocado.Runtimes.varlink | 6 +- src/varlink/org_avocado_Extensions.rs | 629 +-------------------- src/varlink/org_avocado_Hitl.rs | 347 +----------- src/varlink/org_avocado_RootAuthority.rs | 261 +-------- src/varlink/org_avocado_Runtimes.rs | 591 +------------------ src/varlink_client.rs | 9 + src/varlink_server.rs | 12 +- 13 files changed, 200 insertions(+), 1944 deletions(-) diff --git a/src/commands/ext.rs b/src/commands/ext.rs index 3f59fca..baec140 100644 --- a/src/commands/ext.rs +++ b/src/commands/ext.rs @@ -24,30 +24,6 @@ struct Extension { merge_index: Option, } -/// Print a colored success message -fn print_colored_success(message: &str) { - // Use auto-detection but fallback gracefully - let color_choice = - if std::env::var("NO_COLOR").is_ok() || std::env::var("AVOCADO_TEST_MODE").is_ok() { - ColorChoice::Never - } else { - ColorChoice::Auto - }; - - let mut stdout = StandardStream::stdout(color_choice); - let mut color_spec = ColorSpec::new(); - color_spec.set_fg(Some(Color::Green)).set_bold(true); - - if stdout.set_color(&color_spec).is_ok() && color_choice != ColorChoice::Never { - let _ = write!(&mut stdout, "[SUCCESS]"); - let _ = stdout.reset(); - println!(" {message}"); - } else { - // Fallback for environments without color support - println!("[SUCCESS] {message}"); - } -} - /// Print a colored info message fn print_colored_info(message: &str) { // Use auto-detection but fallback gracefully @@ -402,7 +378,7 @@ pub(crate) fn merge_extensions_internal( handle_systemd_output("systemd-confext merge", &confext_result, output)?; // Process post-merge tasks only for enabled extensions - process_post_merge_tasks_for_extensions(&enabled_extensions)?; + process_post_merge_tasks_for_extensions(&enabled_extensions, output)?; Ok(()) } @@ -455,7 +431,7 @@ pub(crate) fn unmerge_extensions_internal_with_options( // Execute AVOCADO_ON_UNMERGE commands before unmerging extensions // These commands are executed while extensions are still merged - if let Err(e) = process_pre_unmerge_tasks() { + if let Err(e) = process_pre_unmerge_tasks(output) { output.progress(&format!( "Warning: Failed to process pre-unmerge tasks: {e}" )); @@ -479,7 +455,7 @@ pub(crate) fn unmerge_extensions_internal_with_options( // Run depmod after unmerge if requested if call_depmod { - run_depmod()?; + run_depmod(output)?; } // Unmount persistent loops if requested @@ -3527,6 +3503,7 @@ fn scan_directory_for_release_files( /// Process post-merge tasks for only the enabled extensions fn process_post_merge_tasks_for_extensions( enabled_extensions: &[Extension], + output: &OutputManager, ) -> Result<(), SystemdError> { let (on_merge_commands, modprobe_modules) = scan_release_files_for_enabled_extensions(enabled_extensions)?; @@ -3541,12 +3518,12 @@ fn process_post_merge_tasks_for_extensions( // Execute accumulated AVOCADO_ON_MERGE commands if !unique_commands.is_empty() { - run_avocado_on_merge_commands(&unique_commands)?; + run_avocado_on_merge_commands(&unique_commands, output)?; } // Call modprobe for each module after commands complete if !modprobe_modules.is_empty() { - run_modprobe(&modprobe_modules)?; + run_modprobe(&modprobe_modules, output)?; } Ok(()) @@ -3722,7 +3699,7 @@ fn scan_directory_for_on_unmerge_commands( } /// Process pre-unmerge tasks: execute AVOCADO_ON_UNMERGE commands -fn process_pre_unmerge_tasks() -> Result<(), SystemdError> { +fn process_pre_unmerge_tasks(output: &OutputManager) -> Result<(), SystemdError> { let on_unmerge_commands = scan_merged_extensions_for_on_unmerge_commands()?; // Remove duplicates while preserving order @@ -3735,7 +3712,7 @@ fn process_pre_unmerge_tasks() -> Result<(), SystemdError> { // Execute accumulated AVOCADO_ON_UNMERGE commands if !unique_commands.is_empty() { - run_avocado_on_unmerge_commands(&unique_commands)?; + run_avocado_on_unmerge_commands(&unique_commands, output)?; } Ok(()) @@ -3796,8 +3773,8 @@ pub fn parse_avocado_enable_services(content: &str) -> Vec { } /// Run the depmod command -fn run_depmod() -> Result<(), SystemdError> { - print_colored_info("Running depmod to update kernel module dependencies..."); +fn run_depmod(out: &OutputManager) -> Result<(), SystemdError> { + out.log_info("Running depmod to update kernel module dependencies..."); // Check if we're in test mode and should use mock commands let command_name = if std::env::var("AVOCADO_TEST_MODE").is_ok() { @@ -3824,17 +3801,17 @@ fn run_depmod() -> Result<(), SystemdError> { }); } - print_colored_success("depmod completed successfully."); + out.log_success("depmod completed successfully."); Ok(()) } /// Run modprobe for a list of modules -fn run_modprobe(modules: &[String]) -> Result<(), SystemdError> { +fn run_modprobe(modules: &[String], out: &OutputManager) -> Result<(), SystemdError> { if modules.is_empty() { return Ok(()); } - print_colored_info(&format!("Loading kernel modules: {}", modules.join(", "))); + out.log_info(&format!("Loading kernel modules: {}", modules.join(", "))); for module in modules { // Check if we're in test mode and should use mock commands @@ -3860,16 +3837,16 @@ fn run_modprobe(modules: &[String]) -> Result<(), SystemdError> { // Don't fail the entire operation for individual module failures // Just log the warning and continue with other modules } else { - print_colored_success(&format!("Module {module} loaded successfully.")); + out.log_success(&format!("Module {module} loaded successfully.")); } } - print_colored_success("Module loading completed."); + out.log_success("Module loading completed."); Ok(()) } /// Execute a single command with its arguments -fn execute_single_command(command_str: &str) -> Result<(), SystemdError> { +fn execute_single_command(command_str: &str, out: &OutputManager) -> Result<(), SystemdError> { // Parse the command string to handle commands with arguments // Commands may be quoted or contain spaces let parts: Vec<&str> = if command_str.starts_with('"') && command_str.ends_with('"') { @@ -3924,22 +3901,25 @@ fn execute_single_command(command_str: &str) -> Result<(), SystemdError> { // Log warning but don't fail the entire operation // This matches the behavior of modprobe failures } else { - print_colored_success(&format!("Command '{command_str}' completed successfully")); + out.log_success(&format!("Command '{command_str}' completed successfully")); } Ok(()) } /// Run accumulated AVOCADO_ON_MERGE commands -fn run_avocado_on_merge_commands(commands: &[String]) -> Result<(), SystemdError> { +fn run_avocado_on_merge_commands( + commands: &[String], + out: &OutputManager, +) -> Result<(), SystemdError> { if commands.is_empty() { return Ok(()); } - print_colored_info(&format!("Executing {} post-merge commands", commands.len())); + out.log_info(&format!("Executing {} post-merge commands", commands.len())); for command_str in commands { - print_colored_info(&format!("Running command: {command_str}")); + out.log_info(&format!("Running command: {command_str}")); // Check if the command contains shell operators like semicolons if command_str.contains(';') { @@ -3948,33 +3928,36 @@ fn run_avocado_on_merge_commands(commands: &[String]) -> Result<(), SystemdError for sub_command in sub_commands { if !sub_command.is_empty() { - print_colored_info(&format!("Running sub-command: {sub_command}")); - execute_single_command(sub_command)?; + out.log_info(&format!("Running sub-command: {sub_command}")); + execute_single_command(sub_command, out)?; } } } else { // Execute as a single command - execute_single_command(command_str)?; + execute_single_command(command_str, out)?; } } - print_colored_success("Post-merge command execution completed."); + out.log_success("Post-merge command execution completed."); Ok(()) } /// Run accumulated AVOCADO_ON_UNMERGE commands -fn run_avocado_on_unmerge_commands(commands: &[String]) -> Result<(), SystemdError> { +fn run_avocado_on_unmerge_commands( + commands: &[String], + out: &OutputManager, +) -> Result<(), SystemdError> { if commands.is_empty() { return Ok(()); } - print_colored_info(&format!( + out.log_info(&format!( "Executing {} pre-unmerge commands", commands.len() )); for command_str in commands { - print_colored_info(&format!("Running command: {command_str}")); + out.log_info(&format!("Running command: {command_str}")); // Check if the command contains shell operators like semicolons if command_str.contains(';') { @@ -3983,17 +3966,17 @@ fn run_avocado_on_unmerge_commands(commands: &[String]) -> Result<(), SystemdErr for sub_command in sub_commands { if !sub_command.is_empty() { - print_colored_info(&format!("Running sub-command: {sub_command}")); - execute_single_command(sub_command)?; + out.log_info(&format!("Running sub-command: {sub_command}")); + execute_single_command(sub_command, out)?; } } } else { // Execute as a single command - execute_single_command(command_str)?; + execute_single_command(command_str, out)?; } } - print_colored_success("Pre-unmerge command execution completed."); + out.log_success("Pre-unmerge command execution completed."); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 7b284d9..182e331 100644 --- a/src/main.rs +++ b/src/main.rs @@ -188,7 +188,10 @@ fn main() { Some(("merge", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); match client.merge().call() { - Ok(_) => output.success("Merge", "Extensions merged successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Merge", "Extensions merged successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -197,7 +200,10 @@ fn main() { let unmount = unmerge_matches.get_flag("unmount"); let mut client = vl_ext::VarlinkClient::new(conn); match client.unmerge(Some(unmount)).call() { - Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Unmerge", "Extensions unmerged successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -205,7 +211,10 @@ fn main() { Some(("refresh", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); match client.refresh().call() { - Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Refresh", "Extensions refreshed successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -294,13 +303,19 @@ fn main() { let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); let mut client = vl_rt::VarlinkClient::new(conn); match client.add_from_url(url.clone(), auth_token).call() { - Ok(_) => output.success("Runtime Add", "Runtime added successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Runtime Add", "Runtime added successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } } else if let Some(manifest) = add_matches.get_one::("manifest") { let mut client = vl_rt::VarlinkClient::new(conn); match client.add_from_manifest(manifest.clone()).call() { - Ok(_) => output.success("Runtime Add", "Runtime added successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Runtime Add", "Runtime added successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } } @@ -325,8 +340,9 @@ fn main() { .clone(); let mut client = vl_rt::VarlinkClient::new(conn); match client.activate(id).call() { - Ok(_) => { - output.success("Runtime Activate", "Runtime activated successfully") + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Runtime Activate", "Runtime activated successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } @@ -379,7 +395,10 @@ fn main() { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); match client.merge().call() { - Ok(_) => output.success("Merge", "Extensions merged successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Merge", "Extensions merged successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -389,7 +408,10 @@ fn main() { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); match client.unmerge(Some(unmount)).call() { - Ok(_) => output.success("Unmerge", "Extensions unmerged successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Unmerge", "Extensions unmerged successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); @@ -398,7 +420,10 @@ fn main() { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); match client.refresh().call() { - Ok(_) => output.success("Refresh", "Extensions refreshed successfully"), + Ok(reply) => { + varlink_client::print_log(&reply.log); + output.success("Refresh", "Extensions refreshed successfully"); + } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } json_ok(&output); diff --git a/src/output.rs b/src/output.rs index f4326cf..3f5a31d 100644 --- a/src/output.rs +++ b/src/output.rs @@ -3,6 +3,7 @@ //! This module provides a consistent interface for all output in the CLI, //! handling verbosity levels and formatting consistently across all commands. +use std::cell::RefCell; use std::io::Write; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -10,12 +11,50 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; pub struct OutputManager { verbose: bool, json: bool, + /// When set, messages are captured into this buffer instead of printed. + /// Used by the service layer so the daemon can return log messages to + /// varlink callers rather than printing to its own stdout. + captured: Option>>, } impl OutputManager { /// Create a new output manager with the specified verbosity and format level pub fn new(verbose: bool, json: bool) -> Self { - Self { verbose, json } + Self { + verbose, + json, + captured: None, + } + } + + /// Create an output manager that captures messages instead of printing them. + /// Use `take_messages()` to retrieve the collected messages. + pub fn new_capturing() -> Self { + Self { + verbose: false, + json: false, + captured: Some(RefCell::new(Vec::new())), + } + } + + /// Whether this output manager is in capture mode. + fn is_capturing(&self) -> bool { + self.captured.is_some() + } + + /// Push a message to the capture buffer. + fn capture(&self, message: String) { + if let Some(ref buf) = self.captured { + buf.borrow_mut().push(message); + } + } + + /// Take all captured messages, leaving the buffer empty. + pub fn take_messages(&self) -> Vec { + match self.captured { + Some(ref buf) => std::mem::take(&mut *buf.borrow_mut()), + None => Vec::new(), + } } /// Whether output should be machine-readable JSON @@ -23,14 +62,18 @@ impl OutputManager { self.json } + /// Determine the color choice for terminal output + fn color_choice() -> ColorChoice { + if std::env::var("NO_COLOR").is_ok() || std::env::var("AVOCADO_TEST_MODE").is_ok() { + ColorChoice::Never + } else { + ColorChoice::Auto + } + } + /// Print a colored prefix with message fn print_colored_prefix(&self, prefix: &str, color: Color, message: &str) { - let color_choice = - if std::env::var("NO_COLOR").is_ok() || std::env::var("AVOCADO_TEST_MODE").is_ok() { - ColorChoice::Never - } else { - ColorChoice::Auto - }; + let color_choice = Self::color_choice(); let mut stdout = StandardStream::stdout(color_choice); let mut color_spec = ColorSpec::new(); @@ -54,12 +97,7 @@ impl OutputManager { operation: &str, message: &str, ) { - let color_choice = - if std::env::var("NO_COLOR").is_ok() || std::env::var("AVOCADO_TEST_MODE").is_ok() { - ColorChoice::Never - } else { - ColorChoice::Auto - }; + let color_choice = Self::color_choice(); let mut stdout = StandardStream::stdout(color_choice); let mut color_spec = ColorSpec::new(); @@ -93,12 +131,7 @@ impl OutputManager { /// Print an error message /// Always shows detailed error information for developers pub fn error(&self, operation: &str, message: &str) { - let color_choice = - if std::env::var("NO_COLOR").is_ok() || std::env::var("AVOCADO_TEST_MODE").is_ok() { - ColorChoice::Never - } else { - ColorChoice::Auto - }; + let color_choice = Self::color_choice(); let mut stderr = StandardStream::stderr(color_choice); let mut color_spec = ColorSpec::new(); @@ -184,4 +217,28 @@ impl OutputManager { } println!("{message}"); } + + /// Log an informational message. + /// + /// In normal mode: prints to stdout with color (always, regardless of verbosity). + /// In capture mode: captures to the message buffer for returning via varlink. + pub fn log_info(&self, message: &str) { + if self.is_capturing() { + self.capture(format!("[INFO] {message}")); + } else if !self.json { + self.print_colored_prefix("INFO", Color::Blue, message); + } + } + + /// Log a success message. + /// + /// In normal mode: prints to stdout with color (always, regardless of verbosity). + /// In capture mode: captures to the message buffer for returning via varlink. + pub fn log_success(&self, message: &str) { + if self.is_capturing() { + self.capture(format!("[SUCCESS] {message}")); + } else if !self.json { + self.print_colored_prefix("SUCCESS", Color::Green, message); + } + } } diff --git a/src/service/ext.rs b/src/service/ext.rs index e35fadc..25f4d85 100644 --- a/src/service/ext.rs +++ b/src/service/ext.rs @@ -7,11 +7,6 @@ use std::fs; use std::os::unix::fs as unix_fs; use std::path::Path; -/// A quiet OutputManager for service-layer calls (no terminal output). -fn quiet_output() -> OutputManager { - OutputManager::new(false, false) -} - /// List all available extensions from the extensions directory. pub fn list_extensions(config: &Config) -> Result, AvocadoError> { let extensions_path = config.get_extensions_dir(); @@ -57,21 +52,26 @@ pub fn list_extensions(config: &Config) -> Result, AvocadoErr } /// Merge extensions using systemd-sysext and systemd-confext. -pub fn merge_extensions(config: &Config) -> Result<(), AvocadoError> { - let output = quiet_output(); - ext::merge_extensions_internal(config, &output).map_err(AvocadoError::from) +/// Returns log messages produced during the operation. +pub fn merge_extensions(config: &Config) -> Result, AvocadoError> { + let output = OutputManager::new_capturing(); + ext::merge_extensions_internal(config, &output).map_err(AvocadoError::from)?; + Ok(output.take_messages()) } /// Unmerge extensions using systemd-sysext and systemd-confext. -pub fn unmerge_extensions(unmount: bool) -> Result<(), AvocadoError> { - let output = quiet_output(); +/// Returns log messages produced during the operation. +pub fn unmerge_extensions(unmount: bool) -> Result, AvocadoError> { + let output = OutputManager::new_capturing(); ext::unmerge_extensions_internal_with_options(true, unmount, &output) - .map_err(AvocadoError::from) + .map_err(AvocadoError::from)?; + Ok(output.take_messages()) } /// Refresh extensions (unmerge then merge). -pub fn refresh_extensions(config: &Config) -> Result<(), AvocadoError> { - let output = quiet_output(); +/// Returns log messages produced during the operation. +pub fn refresh_extensions(config: &Config) -> Result, AvocadoError> { + let output = OutputManager::new_capturing(); // First unmerge (skip depmod since we'll call it after merge, don't unmount loops) ext::unmerge_extensions_internal_with_options(false, false, &output) @@ -83,7 +83,7 @@ pub fn refresh_extensions(config: &Config) -> Result<(), AvocadoError> { // Then merge (this will call depmod via post-merge processing) ext::merge_extensions_internal(config, &output).map_err(AvocadoError::from)?; - Ok(()) + Ok(output.take_messages()) } /// Enable extensions for a specific OS release version. diff --git a/src/service/runtime.rs b/src/service/runtime.rs index d2fad45..75bd78c 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -39,20 +39,24 @@ pub fn list_runtimes(config: &Config) -> Result, AvocadoError> } /// Add a runtime from a TUF repository URL. +/// Returns log messages from the refresh operation. pub fn add_from_url( url: &str, auth_token: Option<&str>, config: &Config, -) -> Result<(), AvocadoError> { +) -> Result, AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); update::perform_update(url, base_path, auth_token, false)?; - super::ext::refresh_extensions(config)?; - Ok(()) + super::ext::refresh_extensions(config) } /// Add a runtime from a local manifest file. -pub fn add_from_manifest(manifest_path: &str, config: &Config) -> Result<(), AvocadoError> { +/// Returns log messages from the refresh operation. +pub fn add_from_manifest( + manifest_path: &str, + config: &Config, +) -> Result, AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); @@ -69,9 +73,7 @@ pub fn add_from_manifest(manifest_path: &str, config: &Config) -> Result<(), Avo staging::validate_manifest_images(&manifest, base_path)?; staging::stage_manifest(&manifest, &manifest_content, base_path, false)?; staging::activate_runtime(&manifest.id, base_path)?; - super::ext::refresh_extensions(config)?; - - Ok(()) + super::ext::refresh_extensions(config) } /// Remove a staged runtime by ID (or prefix). @@ -86,19 +88,19 @@ pub fn remove_runtime(id_prefix: &str, config: &Config) -> Result<(), AvocadoErr } /// Activate a staged runtime by ID (or prefix). -pub fn activate_runtime(id_prefix: &str, config: &Config) -> Result<(), AvocadoError> { +/// Returns log messages from the refresh operation. +pub fn activate_runtime(id_prefix: &str, config: &Config) -> Result, AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); let runtimes = RuntimeManifest::list_all(base_path); let (matched, is_active) = resolve_runtime_with_active(id_prefix, &runtimes)?; if is_active { - return Ok(()); // Already active, nothing to do + return Ok(Vec::new()); // Already active, nothing to do } staging::activate_runtime(&matched.id, base_path)?; - super::ext::refresh_extensions(config)?; - Ok(()) + super::ext::refresh_extensions(config) } /// Inspect a runtime's details by ID (or prefix). diff --git a/src/varlink/org.avocado.Extensions.varlink b/src/varlink/org.avocado.Extensions.varlink index 66b3fe2..5023f7f 100644 --- a/src/varlink/org.avocado.Extensions.varlink +++ b/src/varlink/org.avocado.Extensions.varlink @@ -24,13 +24,13 @@ type ExtensionStatus ( method List() -> (extensions: []Extension) # Merge extensions using systemd-sysext and systemd-confext -method Merge() -> () +method Merge() -> (log: []string) # Unmerge extensions -method Unmerge(unmount: ?bool) -> () +method Unmerge(unmount: ?bool) -> (log: []string) # Refresh extensions (unmerge then merge) -method Refresh() -> () +method Refresh() -> (log: []string) # Enable extensions for a specific OS release version method Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int) diff --git a/src/varlink/org.avocado.Runtimes.varlink b/src/varlink/org.avocado.Runtimes.varlink index d8597ab..5ae05fd 100644 --- a/src/varlink/org.avocado.Runtimes.varlink +++ b/src/varlink/org.avocado.Runtimes.varlink @@ -25,16 +25,16 @@ type Runtime ( method List() -> (runtimes: []Runtime) # Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints) -method AddFromUrl(url: string, authToken: ?string) -> () +method AddFromUrl(url: string, authToken: ?string) -> (log: []string) # Add a runtime from a local manifest file -method AddFromManifest(manifestPath: string) -> () +method AddFromManifest(manifestPath: string) -> (log: []string) # Remove a staged runtime by ID (or prefix) method Remove(id: string) -> () # Activate a staged runtime by ID (or prefix) -method Activate(id: string) -> () +method Activate(id: string) -> (log: []string) # Inspect a runtime's details method Inspect(id: string) -> (runtime: Runtime) diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index 4e2962c..a6fa698 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1,628 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - CommandFailed(Option), - ConfigurationError(Option), - ExtensionNotFound(Option), - MergeFailed(Option), - UnmergeFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::CommandFailed(v) => { - write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) - } - ErrorKind::ConfigurationError(v) => { - write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) - } - ErrorKind::ExtensionNotFound(v) => { - write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) - } - ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), - ErrorKind::UnmergeFailed(v) => { - write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.CommandFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::CommandFailed(v), - Err(_) => ErrorKind::CommandFailed(None), - }, - _ => ErrorKind::CommandFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ConfigurationError" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ConfigurationError(v), - Err(_) => ErrorKind::ConfigurationError(None), - }, - _ => ErrorKind::ConfigurationError(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ExtensionNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ExtensionNotFound(v), - Err(_) => ErrorKind::ExtensionNotFound(None), - }, - _ => ErrorKind::ExtensionNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MergeFailed(v), - Err(_) => ErrorKind::MergeFailed(None), - }, - _ => ErrorKind::MergeFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.UnmergeFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmergeFailed(v), - Err(_) => ErrorKind::UnmergeFailed(None), - }, - _ => ErrorKind::UnmergeFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_command_failed( - &mut self, - r#command: String, - r#message: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.CommandFailed", - Some( - serde_json::to_value(CommandFailed_Args { - r#command, - r#message, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ConfigurationError", - Some( - serde_json::to_value(ConfigurationError_Args { r#message }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ExtensionNotFound", - Some( - serde_json::to_value(ExtensionNotFound_Args { r#name }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.MergeFailed", - Some( - serde_json::to_value(MergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.UnmergeFailed", - Some( - serde_json::to_value(UnmergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Extension { - pub r#name: String, - pub r#version: Option, - pub r#path: String, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isDirectory: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ExtensionStatus { - pub r#name: String, - pub r#version: Option, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isMerged: bool, - pub r#origin: Option, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct CommandFailed_Args { - pub r#command: String, - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ConfigurationError_Args { - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ExtensionNotFound_Args { - pub r#name: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Reply { - pub r#disabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Disable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#extensions: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#all: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Disable: VarlinkCallError { - fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Disable_Reply { - r#disabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Disable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Reply { - pub r#enabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Enable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Args { - pub r#extensions: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Enable: VarlinkCallError { - fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Enable_Reply { - r#enabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Enable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#extensions }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Reply {} -impl varlink::VarlinkReply for Merge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Args {} -#[allow(dead_code)] -pub trait Call_Merge: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Merge for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Reply {} -impl varlink::VarlinkReply for Refresh_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Args {} -#[allow(dead_code)] -pub trait Call_Refresh: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Refresh for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for Status_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Args {} -#[allow(dead_code)] -pub trait Call_Status: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(Status_Reply { r#extensions }.into()) - } -} -impl Call_Status for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Reply {} -impl varlink::VarlinkReply for Unmerge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#unmount: Option, -} -#[allow(dead_code)] -pub trait Call_Unmerge: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Unmerge for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn disable( - &self, - call: &mut dyn Call_Disable, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn enable( - &self, - call: &mut dyn Call_Enable, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; - fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; - fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; - fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn merge(&mut self) -> varlink::MethodCall; - fn refresh(&mut self) -> varlink::MethodCall; - fn status(&mut self) -> varlink::MethodCall; - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Disable", - Disable_Args { - r#extensions, - r#all, - r#osRelease, - }, - ) - } - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Enable", - Enable_Args { - r#extensions, - r#osRelease, - }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.List", - List_Args {}, - ) - } - fn merge(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Merge", - Merge_Args {}, - ) - } - fn refresh(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Refresh", - Refresh_Args {}, - ) - } - fn status(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Status", - Status_Args {}, - ) - } - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Unmerge", - Unmerge_Args { r#unmount }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> ()\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> ()\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> ()\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Extensions" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Extensions.Disable" => { - if let Some(args) = req.parameters.clone() { - let args: Disable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.disable( - call as &mut dyn Call_Disable, - args.r#extensions, - args.r#all, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.Enable" => { - if let Some(args) = req.parameters.clone() { - let args: Enable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.enable( - call as &mut dyn Call_Enable, - args.r#extensions, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), - "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), - "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), - "org.avocado.Extensions.Unmerge" => { - if let Some(args) = req.parameters.clone() { - let args: Unmerge_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Merge_Reply { r#log } . into ()) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Refresh_Reply { r#log } . into ()) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Unmerge_Reply { r#log } . into ()) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> (log: []string)\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> (log: []string)\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> (log: []string)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 59a04ea..7720a1d 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1,346 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - MountFailed(Option), - UnmountFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), - ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e - { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MountFailed(v), - Err(_) => ErrorKind::MountFailed(None), - }, - _ => ErrorKind::MountFailed(None), - }, - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmountFailed(v), - Err(_) => ErrorKind::UnmountFailed(None), - }, - _ => ErrorKind::UnmountFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.MountFailed", - Some( - serde_json::to_value(MountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmount_failed( - &mut self, - r#extension: String, - r#reason: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.UnmountFailed", - Some( - serde_json::to_value(UnmountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Reply {} -impl varlink::VarlinkReply for Mount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Args { - pub r#serverIp: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#serverPort: Option, - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Mount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Mount for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Reply {} -impl varlink::VarlinkReply for Unmount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Args { - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Unmount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Unmount for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn mount( - &self, - call: &mut dyn Call_Mount, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn unmount( - &self, - call: &mut dyn Call_Unmount, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall; - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Mount", - Mount_Args { - r#serverIp, - r#serverPort, - r#extensions, - }, - ) - } - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Unmount", - Unmount_Args { r#extensions }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Hitl" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Hitl.Mount" => { - if let Some(args) = req.parameters.clone() { - let args: Mount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.mount( - call as &mut dyn Call_Mount, - args.r#serverIp, - args.r#serverPort, - args.r#extensions, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Hitl.Unmount" => { - if let Some(args) = req.parameters.clone() { - let args: Unmount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmount(call as &mut dyn Call_Unmount, args.r#extensions) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index c8d4a18..029ad69 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1,260 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - NoRootAuthority(Option), - ParseFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::NoRootAuthority(v) => { - write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) - } - ErrorKind::ParseFailed(v) => { - write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.NoRootAuthority" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::NoRootAuthority(v), - Err(_) => ErrorKind::NoRootAuthority(None), - }, - _ => ErrorKind::NoRootAuthority(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.ParseFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ParseFailed(v), - Err(_) => ErrorKind::ParseFailed(None), - }, - _ => ErrorKind::ParseFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_no_root_authority(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.NoRootAuthority", - None, - )) - } - fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.ParseFailed", - Some( - serde_json::to_value(ParseFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RootAuthorityInfo { - pub r#version: i64, - pub r#expires: String, - pub r#keys: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#TrustedKey { - pub r#keyId: String, - pub r#keyType: String, - pub r#roles: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct NoRootAuthority_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ParseFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Reply { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#authority: Option, -} -impl varlink::VarlinkReply for Show_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Args {} -#[allow(dead_code)] -pub trait Call_Show: VarlinkCallError { - fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { - self.reply_struct(Show_Reply { r#authority }.into()) - } -} -impl Call_Show for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn show(&mut self) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn show(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.RootAuthority.Show", - Show_Args {}, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.RootAuthority" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index 4cfb6bd..e7a559c 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1,590 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - AmbiguousRuntimeId(Option), - RemoveActiveRuntime(Option), - RuntimeNotFound(Option), - StagingFailed(Option), - UpdateFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::AmbiguousRuntimeId(v) => { - write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) - } - ErrorKind::RemoveActiveRuntime(v) => { - write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) - } - ErrorKind::RuntimeNotFound(v) => { - write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) - } - ErrorKind::StagingFailed(v) => { - write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) - } - ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::AmbiguousRuntimeId(v), - Err(_) => ErrorKind::AmbiguousRuntimeId(None), - }, - _ => ErrorKind::AmbiguousRuntimeId(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RemoveActiveRuntime" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RemoveActiveRuntime(v), - Err(_) => ErrorKind::RemoveActiveRuntime(None), - }, - _ => ErrorKind::RemoveActiveRuntime(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RuntimeNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RuntimeNotFound(v), - Err(_) => ErrorKind::RuntimeNotFound(None), - }, - _ => ErrorKind::RuntimeNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::StagingFailed(v), - Err(_) => ErrorKind::StagingFailed(None), - }, - _ => ErrorKind::StagingFailed(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UpdateFailed(v), - Err(_) => ErrorKind::UpdateFailed(None), - }, - _ => ErrorKind::UpdateFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_ambiguous_runtime_id( - &mut self, - r#id: String, - r#candidates: Vec, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.AmbiguousRuntimeId", - Some( - serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RemoveActiveRuntime", - None, - )) - } - fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RuntimeNotFound", - Some( - serde_json::to_value(RuntimeNotFound_Args { r#id }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.StagingFailed", - Some( - serde_json::to_value(StagingFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.UpdateFailed", - Some( - serde_json::to_value(UpdateFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ManifestExtension { - pub r#name: String, - pub r#version: String, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Runtime { - pub r#id: String, - pub r#manifestVersion: i64, - pub r#builtAt: String, - pub r#runtime: RuntimeInfo, - pub r#extensions: Vec, - pub r#active: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RuntimeInfo { - pub r#name: String, - pub r#version: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AmbiguousRuntimeId_Args { - pub r#id: String, - pub r#candidates: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RemoveActiveRuntime_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RuntimeNotFound_Args { - pub r#id: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct StagingFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UpdateFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Reply {} -impl varlink::VarlinkReply for Activate_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Activate: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Activate for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Reply {} -impl varlink::VarlinkReply for AddFromManifest_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Args { - pub r#manifestPath: String, -} -#[allow(dead_code)] -pub trait Call_AddFromManifest: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_AddFromManifest for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Reply {} -impl varlink::VarlinkReply for AddFromUrl_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Args { - pub r#url: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#authToken: Option, -} -#[allow(dead_code)] -pub trait Call_AddFromUrl: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_AddFromUrl for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Reply { - pub r#runtime: Runtime, -} -impl varlink::VarlinkReply for Inspect_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Inspect: VarlinkCallError { - fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { - self.reply_struct(Inspect_Reply { r#runtime }.into()) - } -} -impl Call_Inspect for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#runtimes: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#runtimes }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Reply {} -impl varlink::VarlinkReply for Remove_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Remove: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Remove for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; - fn add_from_manifest( - &self, - call: &mut dyn Call_AddFromManifest, - r#manifestPath: String, - ) -> varlink::Result<()>; - fn add_from_url( - &self, - call: &mut dyn Call_AddFromUrl, - r#url: String, - r#authToken: Option, - ) -> varlink::Result<()>; - fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall; - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall; - fn add_from_url( - &mut self, - r#url: String, - r#authToken: Option, - ) -> varlink::MethodCall; - fn inspect(&mut self, r#id: String) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn remove(&mut self, r#id: String) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Activate", - Activate_Args { r#id }, - ) - } - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromManifest", - AddFromManifest_Args { r#manifestPath }, - ) - } - fn add_from_url( - &mut self, - r#url: String, - r#authToken: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromUrl", - AddFromUrl_Args { r#url, r#authToken }, - ) - } - fn inspect(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Inspect", - Inspect_Args { r#id }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.List", - List_Args {}, - ) - } - fn remove(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Remove", - Remove_Args { r#id }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> ()\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> ()\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> ()\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Runtimes" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Runtimes.Activate" => { - if let Some(args) = req.parameters.clone() { - let args: Activate_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .activate(call as &mut dyn Call_Activate, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromManifest" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromManifest_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.add_from_manifest( - call as &mut dyn Call_AddFromManifest, - args.r#manifestPath, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromUrl" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromUrl_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.add_from_url( - call as &mut dyn Call_AddFromUrl, - args.r#url, - args.r#authToken, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.Inspect" => { - if let Some(args) = req.parameters.clone() { - let args: Inspect_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Runtimes.Remove" => { - if let Some(args) = req.parameters.clone() { - let args: Remove_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.remove(call as &mut dyn Call_Remove, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Activate_Reply { r#log } . into ()) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (AddFromManifest_Reply { r#log } . into ()) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (AddFromUrl_Reply { r#log } . into ()) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> (log: []string)\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> (log: []string)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> (log: []string)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink_client.rs b/src/varlink_client.rs index eb1612c..fb71d80 100644 --- a/src/varlink_client.rs +++ b/src/varlink_client.rs @@ -42,6 +42,15 @@ pub fn exit_with_rpc_error( std::process::exit(1); } +// ── Log output helper ──────────────────────────────────────────────────────── + +/// Print log messages returned from the daemon via varlink replies. +pub fn print_log(messages: &[String]) { + for msg in messages { + println!("{msg}"); + } +} + // ── Extension output helpers ───────────────────────────────────────────────── pub fn print_extensions(extensions: &[vl_ext::Extension], output: &OutputManager) { diff --git a/src/varlink_server.rs b/src/varlink_server.rs index 4279d68..931bb09 100644 --- a/src/varlink_server.rs +++ b/src/varlink_server.rs @@ -51,7 +51,7 @@ impl vl_ext::VarlinkInterface for ExtensionsHandler { fn merge(&self, call: &mut dyn vl_ext::Call_Merge) -> varlink::Result<()> { match service::ext::merge_extensions(&self.config) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_ext_error!(call, e), } } @@ -62,14 +62,14 @@ impl vl_ext::VarlinkInterface for ExtensionsHandler { r#unmount: Option, ) -> varlink::Result<()> { match service::ext::unmerge_extensions(unmount.unwrap_or(false)) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_ext_error!(call, e), } } fn refresh(&self, call: &mut dyn vl_ext::Call_Refresh) -> varlink::Result<()> { match service::ext::refresh_extensions(&self.config) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_ext_error!(call, e), } } @@ -177,7 +177,7 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { r#authToken: Option, ) -> varlink::Result<()> { match service::runtime::add_from_url(&url, authToken.as_deref(), &self.config) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_rt_error!(call, e), } } @@ -188,7 +188,7 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { r#manifestPath: String, ) -> varlink::Result<()> { match service::runtime::add_from_manifest(&manifestPath, &self.config) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_rt_error!(call, e), } } @@ -202,7 +202,7 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { fn activate(&self, call: &mut dyn vl_rt::Call_Activate, r#id: String) -> varlink::Result<()> { match service::runtime::activate_runtime(&id, &self.config) { - Ok(()) => call.reply(), + Ok(log) => call.reply(log), Err(e) => map_rt_error!(call, e), } } From 0133d782fd8f92c4936698f0a8ff4153d440e437 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 16:00:37 -0400 Subject: [PATCH 20/27] feat: stream daemon log messages progressively via varlink more/continues Replace batch log buffering with channel-based streaming so that lifecycle events (on_merge, on_unmerge, depmod, etc.) are sent to the CLI caller as they happen rather than all at once after completion. - Add OutputManager::new_streaming(SyncSender) mode that sends each log message through an mpsc channel immediately - Add _streaming() service functions that spawn work on a thread and return (Receiver, JoinHandle) for the caller to drain - Use varlink's native more/continues protocol: server calls set_continues(true) and sends per-message replies, client iterates with .more() - Re-colorize [INFO]/[SUCCESS] prefixes on the client side via print_single_log() - Backward-compatible: wants_more() check falls back to batch mode for non-streaming clients - Remove unused capture mode (RefCell buffer) from OutputManager --- src/main.rs | 126 +++- src/output.rs | 50 +- src/service/ext.rs | 109 +++- src/service/runtime.rs | 69 +++ src/varlink/org.avocado.Extensions.varlink | 9 +- src/varlink/org.avocado.Runtimes.varlink | 9 +- src/varlink/org_avocado_Extensions.rs | 638 ++++++++++++++++++++- src/varlink/org_avocado_Hitl.rs | 347 ++++++++++- src/varlink/org_avocado_RootAuthority.rs | 261 ++++++++- src/varlink/org_avocado_Runtimes.rs | 600 ++++++++++++++++++- src/varlink_client.rs | 18 +- src/varlink_server.rs | 161 +++++- 12 files changed, 2282 insertions(+), 115 deletions(-) diff --git a/src/main.rs b/src/main.rs index 182e331..235bee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -187,9 +187,17 @@ fn main() { } Some(("merge", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.merge().call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.merge().more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Merge", "Extensions merged successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -199,9 +207,17 @@ fn main() { Some(("unmerge", unmerge_matches)) => { let unmount = unmerge_matches.get_flag("unmount"); let mut client = vl_ext::VarlinkClient::new(conn); - match client.unmerge(Some(unmount)).call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.unmerge(Some(unmount)).more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Unmerge", "Extensions unmerged successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -210,9 +226,17 @@ fn main() { } Some(("refresh", _)) => { let mut client = vl_ext::VarlinkClient::new(conn); - match client.refresh().call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.refresh().more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Refresh", "Extensions refreshed successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -302,18 +326,34 @@ fn main() { if let Some(url) = add_matches.get_one::("url") { let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.add_from_url(url.clone(), auth_token).call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.add_from_url(url.clone(), auth_token).more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Runtime Add", "Runtime added successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), } } else if let Some(manifest) = add_matches.get_one::("manifest") { let mut client = vl_rt::VarlinkClient::new(conn); - match client.add_from_manifest(manifest.clone()).call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.add_from_manifest(manifest.clone()).more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Runtime Add", "Runtime added successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -339,9 +379,17 @@ fn main() { .expect("id is required") .clone(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.activate(id).call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.activate(id).more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Runtime Activate", "Runtime activated successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -394,9 +442,17 @@ fn main() { Some(("merge", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.merge().call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.merge().more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Merge", "Extensions merged successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -407,9 +463,17 @@ fn main() { let unmount = unmerge_matches.get_flag("unmount"); let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.unmerge(Some(unmount)).call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.unmerge(Some(unmount)).more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Unmerge", "Extensions unmerged successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), @@ -419,9 +483,17 @@ fn main() { Some(("refresh", _)) => { let conn = varlink_client::connect_or_exit(&socket_address, &output); let mut client = vl_ext::VarlinkClient::new(conn); - match client.refresh().call() { - Ok(reply) => { - varlink_client::print_log(&reply.log); + match client.refresh().more() { + Ok(iter) => { + for reply in iter { + match reply { + Ok(r) if !r.done => { + varlink_client::print_single_log(&r.message, &output) + } + Ok(_) => {} + Err(e) => varlink_client::exit_with_rpc_error(e, &output), + } + } output.success("Refresh", "Extensions refreshed successfully"); } Err(e) => varlink_client::exit_with_rpc_error(e, &output), diff --git a/src/output.rs b/src/output.rs index 3f5a31d..7bc9dcf 100644 --- a/src/output.rs +++ b/src/output.rs @@ -3,18 +3,17 @@ //! This module provides a consistent interface for all output in the CLI, //! handling verbosity levels and formatting consistently across all commands. -use std::cell::RefCell; use std::io::Write; +use std::sync::mpsc::SyncSender; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; /// Output manager that handles verbosity and formatting consistently pub struct OutputManager { verbose: bool, json: bool, - /// When set, messages are captured into this buffer instead of printed. - /// Used by the service layer so the daemon can return log messages to - /// varlink callers rather than printing to its own stdout. - captured: Option>>, + /// When set, messages are streamed through this channel as they are produced. + /// Used by the varlink streaming handlers for real-time progress. + sender: Option>, } impl OutputManager { @@ -23,37 +22,17 @@ impl OutputManager { Self { verbose, json, - captured: None, + sender: None, } } - /// Create an output manager that captures messages instead of printing them. - /// Use `take_messages()` to retrieve the collected messages. - pub fn new_capturing() -> Self { + /// Create an output manager that streams messages through a channel. + /// Each `log_info` / `log_success` call sends a message immediately. + pub fn new_streaming(sender: SyncSender) -> Self { Self { verbose: false, json: false, - captured: Some(RefCell::new(Vec::new())), - } - } - - /// Whether this output manager is in capture mode. - fn is_capturing(&self) -> bool { - self.captured.is_some() - } - - /// Push a message to the capture buffer. - fn capture(&self, message: String) { - if let Some(ref buf) = self.captured { - buf.borrow_mut().push(message); - } - } - - /// Take all captured messages, leaving the buffer empty. - pub fn take_messages(&self) -> Vec { - match self.captured { - Some(ref buf) => std::mem::take(&mut *buf.borrow_mut()), - None => Vec::new(), + sender: Some(sender), } } @@ -221,10 +200,11 @@ impl OutputManager { /// Log an informational message. /// /// In normal mode: prints to stdout with color (always, regardless of verbosity). + /// In streaming mode: sends through channel immediately. /// In capture mode: captures to the message buffer for returning via varlink. pub fn log_info(&self, message: &str) { - if self.is_capturing() { - self.capture(format!("[INFO] {message}")); + if let Some(ref tx) = self.sender { + let _ = tx.send(format!("[INFO] {message}")); } else if !self.json { self.print_colored_prefix("INFO", Color::Blue, message); } @@ -233,10 +213,10 @@ impl OutputManager { /// Log a success message. /// /// In normal mode: prints to stdout with color (always, regardless of verbosity). - /// In capture mode: captures to the message buffer for returning via varlink. + /// In streaming mode: sends through channel immediately. pub fn log_success(&self, message: &str) { - if self.is_capturing() { - self.capture(format!("[SUCCESS] {message}")); + if let Some(ref tx) = self.sender { + let _ = tx.send(format!("[SUCCESS] {message}")); } else if !self.json { self.print_colored_prefix("SUCCESS", Color::Green, message); } diff --git a/src/service/ext.rs b/src/service/ext.rs index 25f4d85..c1df3d4 100644 --- a/src/service/ext.rs +++ b/src/service/ext.rs @@ -6,6 +6,8 @@ use crate::service::types::{DisableResult, EnableResult, ExtensionInfo}; use std::fs; use std::os::unix::fs as unix_fs; use std::path::Path; +use std::sync::mpsc; +use std::thread; /// List all available extensions from the extensions directory. pub fn list_extensions(config: &Config) -> Result, AvocadoError> { @@ -51,39 +53,106 @@ pub fn list_extensions(config: &Config) -> Result, AvocadoErr Ok(result) } +// ── Streaming service functions ────────────────────────────────────────────── + +/// Merge extensions with streaming output. +/// Returns a receiver that yields log messages as they are produced, +/// and a join handle for the worker thread. +pub fn merge_extensions_streaming( + config: &Config, +) -> ( + mpsc::Receiver, + thread::JoinHandle>, +) { + let (tx, rx) = mpsc::sync_channel(4); + let config = config.clone(); + let handle = thread::spawn(move || { + let output = OutputManager::new_streaming(tx); + ext::merge_extensions_internal(&config, &output).map_err(AvocadoError::from) + }); + (rx, handle) +} + +/// Unmerge extensions with streaming output. +pub fn unmerge_extensions_streaming( + unmount: bool, +) -> ( + mpsc::Receiver, + thread::JoinHandle>, +) { + let (tx, rx) = mpsc::sync_channel(4); + let handle = thread::spawn(move || { + let output = OutputManager::new_streaming(tx); + ext::unmerge_extensions_internal_with_options(true, unmount, &output) + .map_err(AvocadoError::from) + }); + (rx, handle) +} + +/// Refresh extensions (unmerge then merge) with streaming output. +pub fn refresh_extensions_streaming( + config: &Config, +) -> ( + mpsc::Receiver, + thread::JoinHandle>, +) { + let (tx, rx) = mpsc::sync_channel(4); + let config = config.clone(); + let handle = thread::spawn(move || { + let output = OutputManager::new_streaming(tx); + + // First unmerge (skip depmod since we'll call it after merge, don't unmount loops) + ext::unmerge_extensions_internal_with_options(false, false, &output) + .map_err(AvocadoError::from)?; + + // Invalidate NFS caches for any HITL-mounted extensions + ext::invalidate_hitl_caches(&output); + + // Then merge (this will call depmod via post-merge processing) + ext::merge_extensions_internal(&config, &output).map_err(AvocadoError::from) + }); + (rx, handle) +} + +// ── Batch service functions (used by non-streaming clients and tests) ──────── + /// Merge extensions using systemd-sysext and systemd-confext. /// Returns log messages produced during the operation. pub fn merge_extensions(config: &Config) -> Result, AvocadoError> { - let output = OutputManager::new_capturing(); - ext::merge_extensions_internal(config, &output).map_err(AvocadoError::from)?; - Ok(output.take_messages()) + let (rx, handle) = merge_extensions_streaming(config); + let messages: Vec = rx.into_iter().collect(); + handle.join().unwrap_or_else(|_| { + Err(AvocadoError::MergeFailed { + reason: "internal panic".into(), + }) + })?; + Ok(messages) } /// Unmerge extensions using systemd-sysext and systemd-confext. /// Returns log messages produced during the operation. pub fn unmerge_extensions(unmount: bool) -> Result, AvocadoError> { - let output = OutputManager::new_capturing(); - ext::unmerge_extensions_internal_with_options(true, unmount, &output) - .map_err(AvocadoError::from)?; - Ok(output.take_messages()) + let (rx, handle) = unmerge_extensions_streaming(unmount); + let messages: Vec = rx.into_iter().collect(); + handle.join().unwrap_or_else(|_| { + Err(AvocadoError::UnmergeFailed { + reason: "internal panic".into(), + }) + })?; + Ok(messages) } /// Refresh extensions (unmerge then merge). /// Returns log messages produced during the operation. pub fn refresh_extensions(config: &Config) -> Result, AvocadoError> { - let output = OutputManager::new_capturing(); - - // First unmerge (skip depmod since we'll call it after merge, don't unmount loops) - ext::unmerge_extensions_internal_with_options(false, false, &output) - .map_err(AvocadoError::from)?; - - // Invalidate NFS caches for any HITL-mounted extensions - ext::invalidate_hitl_caches(&output); - - // Then merge (this will call depmod via post-merge processing) - ext::merge_extensions_internal(config, &output).map_err(AvocadoError::from)?; - - Ok(output.take_messages()) + let (rx, handle) = refresh_extensions_streaming(config); + let messages: Vec = rx.into_iter().collect(); + handle.join().unwrap_or_else(|_| { + Err(AvocadoError::MergeFailed { + reason: "internal panic".into(), + }) + })?; + Ok(messages) } /// Enable extensions for a specific OS release version. diff --git a/src/service/runtime.rs b/src/service/runtime.rs index 75bd78c..8f45d47 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -4,6 +4,14 @@ use crate::service::error::AvocadoError; use crate::service::types::{RuntimeEntry, RuntimeExtensionInfo}; use crate::{staging, update}; use std::path::Path; +use std::sync::mpsc; +use std::thread; + +/// A streaming operation: a channel receiver for log messages and a join handle for the result. +type StreamHandle = ( + mpsc::Receiver, + thread::JoinHandle>, +); /// Convert a RuntimeManifest + active flag to a RuntimeEntry. fn manifest_to_entry(manifest: &RuntimeManifest, active: bool) -> RuntimeEntry { @@ -38,6 +46,67 @@ pub fn list_runtimes(config: &Config) -> Result, AvocadoError> .collect()) } +// ── Streaming service functions ────────────────────────────────────────────── + +/// Add a runtime from a TUF repository URL with streaming output. +/// Performs the TUF update synchronously, then streams the refresh operation. +pub fn add_from_url_streaming( + url: &str, + auth_token: Option<&str>, + config: &Config, +) -> Result { + let base_dir = config.get_avocado_base_dir(); + let base_path = Path::new(&base_dir); + update::perform_update(url, base_path, auth_token, false)?; + Ok(super::ext::refresh_extensions_streaming(config)) +} + +/// Add a runtime from a local manifest file with streaming output. +/// Performs staging synchronously, then streams the refresh operation. +pub fn add_from_manifest_streaming( + manifest_path: &str, + config: &Config, +) -> Result { + let base_dir = config.get_avocado_base_dir(); + let base_path = Path::new(&base_dir); + + let manifest_content = + std::fs::read_to_string(manifest_path).map_err(|e| AvocadoError::StagingFailed { + reason: format!("Failed to read manifest: {e}"), + })?; + + let manifest: RuntimeManifest = + serde_json::from_str(&manifest_content).map_err(|e| AvocadoError::StagingFailed { + reason: format!("Invalid manifest.json: {e}"), + })?; + + staging::validate_manifest_images(&manifest, base_path)?; + staging::stage_manifest(&manifest, &manifest_content, base_path, false)?; + staging::activate_runtime(&manifest.id, base_path)?; + Ok(super::ext::refresh_extensions_streaming(config)) +} + +/// Activate a staged runtime by ID (or prefix) with streaming output. +/// Performs activation synchronously, then streams the refresh operation. +pub fn activate_runtime_streaming( + id_prefix: &str, + config: &Config, +) -> Result, AvocadoError> { + let base_dir = config.get_avocado_base_dir(); + let base_path = Path::new(&base_dir); + let runtimes = RuntimeManifest::list_all(base_path); + + let (matched, is_active) = resolve_runtime_with_active(id_prefix, &runtimes)?; + if is_active { + return Ok(None); // Already active, nothing to do + } + + staging::activate_runtime(&matched.id, base_path)?; + Ok(Some(super::ext::refresh_extensions_streaming(config))) +} + +// ── Batch service functions ────────────────────────────────────────────────── + /// Add a runtime from a TUF repository URL. /// Returns log messages from the refresh operation. pub fn add_from_url( diff --git a/src/varlink/org.avocado.Extensions.varlink b/src/varlink/org.avocado.Extensions.varlink index 5023f7f..89ffabb 100644 --- a/src/varlink/org.avocado.Extensions.varlink +++ b/src/varlink/org.avocado.Extensions.varlink @@ -24,13 +24,16 @@ type ExtensionStatus ( method List() -> (extensions: []Extension) # Merge extensions using systemd-sysext and systemd-confext -method Merge() -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method Merge() -> (message: string, done: bool) # Unmerge extensions -method Unmerge(unmount: ?bool) -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method Unmerge(unmount: ?bool) -> (message: string, done: bool) # Refresh extensions (unmerge then merge) -method Refresh() -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method Refresh() -> (message: string, done: bool) # Enable extensions for a specific OS release version method Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int) diff --git a/src/varlink/org.avocado.Runtimes.varlink b/src/varlink/org.avocado.Runtimes.varlink index 5ae05fd..2a638a3 100644 --- a/src/varlink/org.avocado.Runtimes.varlink +++ b/src/varlink/org.avocado.Runtimes.varlink @@ -25,16 +25,19 @@ type Runtime ( method List() -> (runtimes: []Runtime) # Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints) -method AddFromUrl(url: string, authToken: ?string) -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method AddFromUrl(url: string, authToken: ?string) -> (message: string, done: bool) # Add a runtime from a local manifest file -method AddFromManifest(manifestPath: string) -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method AddFromManifest(manifestPath: string) -> (message: string, done: bool) # Remove a staged runtime by ID (or prefix) method Remove(id: string) -> () # Activate a staged runtime by ID (or prefix) -method Activate(id: string) -> (log: []string) +# Supports streaming: client may set more=true to receive per-message progress +method Activate(id: string) -> (message: string, done: bool) # Inspect a runtime's details method Inspect(id: string) -> (runtime: Runtime) diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index a6fa698..16a4e7f 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1 +1,637 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Merge_Reply { r#log } . into ()) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Refresh_Reply { r#log } . into ()) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Unmerge_Reply { r#log } . into ()) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\nmethod Merge() -> (log: []string)\n\n# Unmerge extensions\nmethod Unmerge(unmount: ?bool) -> (log: []string)\n\n# Refresh extensions (unmerge then merge)\nmethod Refresh() -> (log: []string)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + CommandFailed(Option), + ConfigurationError(Option), + ExtensionNotFound(Option), + MergeFailed(Option), + UnmergeFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::CommandFailed(v) => { + write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) + } + ErrorKind::ConfigurationError(v) => { + write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) + } + ErrorKind::ExtensionNotFound(v) => { + write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) + } + ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), + ErrorKind::UnmergeFailed(v) => { + write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.CommandFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::CommandFailed(v), + Err(_) => ErrorKind::CommandFailed(None), + }, + _ => ErrorKind::CommandFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ConfigurationError" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ConfigurationError(v), + Err(_) => ErrorKind::ConfigurationError(None), + }, + _ => ErrorKind::ConfigurationError(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ExtensionNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ExtensionNotFound(v), + Err(_) => ErrorKind::ExtensionNotFound(None), + }, + _ => ErrorKind::ExtensionNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MergeFailed(v), + Err(_) => ErrorKind::MergeFailed(None), + }, + _ => ErrorKind::MergeFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.UnmergeFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmergeFailed(v), + Err(_) => ErrorKind::UnmergeFailed(None), + }, + _ => ErrorKind::UnmergeFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_command_failed( + &mut self, + r#command: String, + r#message: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.CommandFailed", + Some( + serde_json::to_value(CommandFailed_Args { + r#command, + r#message, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ConfigurationError", + Some( + serde_json::to_value(ConfigurationError_Args { r#message }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ExtensionNotFound", + Some( + serde_json::to_value(ExtensionNotFound_Args { r#name }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.MergeFailed", + Some( + serde_json::to_value(MergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.UnmergeFailed", + Some( + serde_json::to_value(UnmergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Extension { + pub r#name: String, + pub r#version: Option, + pub r#path: String, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isDirectory: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ExtensionStatus { + pub r#name: String, + pub r#version: Option, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isMerged: bool, + pub r#origin: Option, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct CommandFailed_Args { + pub r#command: String, + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ConfigurationError_Args { + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ExtensionNotFound_Args { + pub r#name: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Reply { + pub r#disabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Disable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#extensions: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#all: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Disable: VarlinkCallError { + fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Disable_Reply { + r#disabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Disable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Reply { + pub r#enabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Enable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Args { + pub r#extensions: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Enable: VarlinkCallError { + fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Enable_Reply { + r#enabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Enable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#extensions }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Merge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Args {} +#[allow(dead_code)] +pub trait Call_Merge: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Merge_Reply { r#message, r#done }.into()) + } +} +impl Call_Merge for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Refresh_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Args {} +#[allow(dead_code)] +pub trait Call_Refresh: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Refresh_Reply { r#message, r#done }.into()) + } +} +impl Call_Refresh for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for Status_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Args {} +#[allow(dead_code)] +pub trait Call_Status: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(Status_Reply { r#extensions }.into()) + } +} +impl Call_Status for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Unmerge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#unmount: Option, +} +#[allow(dead_code)] +pub trait Call_Unmerge: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Unmerge_Reply { r#message, r#done }.into()) + } +} +impl Call_Unmerge for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn disable( + &self, + call: &mut dyn Call_Disable, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn enable( + &self, + call: &mut dyn Call_Enable, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; + fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; + fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; + fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn merge(&mut self) -> varlink::MethodCall; + fn refresh(&mut self) -> varlink::MethodCall; + fn status(&mut self) -> varlink::MethodCall; + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Disable", + Disable_Args { + r#extensions, + r#all, + r#osRelease, + }, + ) + } + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Enable", + Enable_Args { + r#extensions, + r#osRelease, + }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.List", + List_Args {}, + ) + } + fn merge(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Merge", + Merge_Args {}, + ) + } + fn refresh(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Refresh", + Refresh_Args {}, + ) + } + fn status(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Status", + Status_Args {}, + ) + } + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Unmerge", + Unmerge_Args { r#unmount }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Merge() -> (message: string, done: bool)\n\n# Unmerge extensions\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Unmerge(unmount: ?bool) -> (message: string, done: bool)\n\n# Refresh extensions (unmerge then merge)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Refresh() -> (message: string, done: bool)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Extensions" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Extensions.Disable" => { + if let Some(args) = req.parameters.clone() { + let args: Disable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.disable( + call as &mut dyn Call_Disable, + args.r#extensions, + args.r#all, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.Enable" => { + if let Some(args) = req.parameters.clone() { + let args: Enable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.enable( + call as &mut dyn Call_Enable, + args.r#extensions, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), + "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), + "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), + "org.avocado.Extensions.Unmerge" => { + if let Some(args) = req.parameters.clone() { + let args: Unmerge_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 7720a1d..59a04ea 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1 +1,346 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + MountFailed(Option), + UnmountFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), + ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e + { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MountFailed(v), + Err(_) => ErrorKind::MountFailed(None), + }, + _ => ErrorKind::MountFailed(None), + }, + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmountFailed(v), + Err(_) => ErrorKind::UnmountFailed(None), + }, + _ => ErrorKind::UnmountFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.MountFailed", + Some( + serde_json::to_value(MountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmount_failed( + &mut self, + r#extension: String, + r#reason: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.UnmountFailed", + Some( + serde_json::to_value(UnmountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Reply {} +impl varlink::VarlinkReply for Mount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Args { + pub r#serverIp: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#serverPort: Option, + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Mount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Mount for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Reply {} +impl varlink::VarlinkReply for Unmount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Args { + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Unmount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Unmount for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn mount( + &self, + call: &mut dyn Call_Mount, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn unmount( + &self, + call: &mut dyn Call_Unmount, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall; + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Mount", + Mount_Args { + r#serverIp, + r#serverPort, + r#extensions, + }, + ) + } + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Unmount", + Unmount_Args { r#extensions }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Hitl" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Hitl.Mount" => { + if let Some(args) = req.parameters.clone() { + let args: Mount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.mount( + call as &mut dyn Call_Mount, + args.r#serverIp, + args.r#serverPort, + args.r#extensions, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Hitl.Unmount" => { + if let Some(args) = req.parameters.clone() { + let args: Unmount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmount(call as &mut dyn Call_Unmount, args.r#extensions) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index 029ad69..c8d4a18 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1 +1,260 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + NoRootAuthority(Option), + ParseFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::NoRootAuthority(v) => { + write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) + } + ErrorKind::ParseFailed(v) => { + write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.NoRootAuthority" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::NoRootAuthority(v), + Err(_) => ErrorKind::NoRootAuthority(None), + }, + _ => ErrorKind::NoRootAuthority(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.ParseFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ParseFailed(v), + Err(_) => ErrorKind::ParseFailed(None), + }, + _ => ErrorKind::ParseFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_no_root_authority(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.NoRootAuthority", + None, + )) + } + fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.ParseFailed", + Some( + serde_json::to_value(ParseFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RootAuthorityInfo { + pub r#version: i64, + pub r#expires: String, + pub r#keys: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#TrustedKey { + pub r#keyId: String, + pub r#keyType: String, + pub r#roles: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct NoRootAuthority_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ParseFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Reply { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authority: Option, +} +impl varlink::VarlinkReply for Show_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Args {} +#[allow(dead_code)] +pub trait Call_Show: VarlinkCallError { + fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { + self.reply_struct(Show_Reply { r#authority }.into()) + } +} +impl Call_Show for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn show(&mut self) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn show(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.RootAuthority.Show", + Show_Args {}, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.RootAuthority" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index e7a559c..df96120 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1 +1,599 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (Activate_Reply { r#log } . into ()) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (AddFromManifest_Reply { r#log } . into ()) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { pub r#log : Vec < String > , } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self , r#log : Vec < String >) -> varlink :: Result < () > { self . reply_struct (AddFromUrl_Reply { r#log } . into ()) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\nmethod AddFromUrl(url: string, authToken: ?string) -> (log: []string)\n\n# Add a runtime from a local manifest file\nmethod AddFromManifest(manifestPath: string) -> (log: []string)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\nmethod Activate(id: string) -> (log: []string)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + AmbiguousRuntimeId(Option), + RemoveActiveRuntime(Option), + RuntimeNotFound(Option), + StagingFailed(Option), + UpdateFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::AmbiguousRuntimeId(v) => { + write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) + } + ErrorKind::RemoveActiveRuntime(v) => { + write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) + } + ErrorKind::RuntimeNotFound(v) => { + write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) + } + ErrorKind::StagingFailed(v) => { + write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) + } + ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::AmbiguousRuntimeId(v), + Err(_) => ErrorKind::AmbiguousRuntimeId(None), + }, + _ => ErrorKind::AmbiguousRuntimeId(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RemoveActiveRuntime" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RemoveActiveRuntime(v), + Err(_) => ErrorKind::RemoveActiveRuntime(None), + }, + _ => ErrorKind::RemoveActiveRuntime(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RuntimeNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RuntimeNotFound(v), + Err(_) => ErrorKind::RuntimeNotFound(None), + }, + _ => ErrorKind::RuntimeNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::StagingFailed(v), + Err(_) => ErrorKind::StagingFailed(None), + }, + _ => ErrorKind::StagingFailed(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UpdateFailed(v), + Err(_) => ErrorKind::UpdateFailed(None), + }, + _ => ErrorKind::UpdateFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_ambiguous_runtime_id( + &mut self, + r#id: String, + r#candidates: Vec, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.AmbiguousRuntimeId", + Some( + serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RemoveActiveRuntime", + None, + )) + } + fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RuntimeNotFound", + Some( + serde_json::to_value(RuntimeNotFound_Args { r#id }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.StagingFailed", + Some( + serde_json::to_value(StagingFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.UpdateFailed", + Some( + serde_json::to_value(UpdateFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ManifestExtension { + pub r#name: String, + pub r#version: String, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Runtime { + pub r#id: String, + pub r#manifestVersion: i64, + pub r#builtAt: String, + pub r#runtime: RuntimeInfo, + pub r#extensions: Vec, + pub r#active: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RuntimeInfo { + pub r#name: String, + pub r#version: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AmbiguousRuntimeId_Args { + pub r#id: String, + pub r#candidates: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RemoveActiveRuntime_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RuntimeNotFound_Args { + pub r#id: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct StagingFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UpdateFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Activate_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Activate: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Activate_Reply { r#message, r#done }.into()) + } +} +impl Call_Activate for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for AddFromManifest_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Args { + pub r#manifestPath: String, +} +#[allow(dead_code)] +pub trait Call_AddFromManifest: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(AddFromManifest_Reply { r#message, r#done }.into()) + } +} +impl Call_AddFromManifest for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for AddFromUrl_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Args { + pub r#url: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authToken: Option, +} +#[allow(dead_code)] +pub trait Call_AddFromUrl: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(AddFromUrl_Reply { r#message, r#done }.into()) + } +} +impl Call_AddFromUrl for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Reply { + pub r#runtime: Runtime, +} +impl varlink::VarlinkReply for Inspect_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Inspect: VarlinkCallError { + fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { + self.reply_struct(Inspect_Reply { r#runtime }.into()) + } +} +impl Call_Inspect for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#runtimes: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#runtimes }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Reply {} +impl varlink::VarlinkReply for Remove_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Remove: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Remove for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; + fn add_from_manifest( + &self, + call: &mut dyn Call_AddFromManifest, + r#manifestPath: String, + ) -> varlink::Result<()>; + fn add_from_url( + &self, + call: &mut dyn Call_AddFromUrl, + r#url: String, + r#authToken: Option, + ) -> varlink::Result<()>; + fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall; + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall; + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + ) -> varlink::MethodCall; + fn inspect(&mut self, r#id: String) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn remove(&mut self, r#id: String) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Activate", + Activate_Args { r#id }, + ) + } + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromManifest", + AddFromManifest_Args { r#manifestPath }, + ) + } + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromUrl", + AddFromUrl_Args { r#url, r#authToken }, + ) + } + fn inspect(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Inspect", + Inspect_Args { r#id }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.List", + List_Args {}, + ) + } + fn remove(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Remove", + Remove_Args { r#id }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromUrl(url: string, authToken: ?string) -> (message: string, done: bool)\n\n# Add a runtime from a local manifest file\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromManifest(manifestPath: string) -> (message: string, done: bool)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Activate(id: string) -> (message: string, done: bool)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Runtimes" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Runtimes.Activate" => { + if let Some(args) = req.parameters.clone() { + let args: Activate_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .activate(call as &mut dyn Call_Activate, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromManifest" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromManifest_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_manifest( + call as &mut dyn Call_AddFromManifest, + args.r#manifestPath, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromUrl" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromUrl_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_url( + call as &mut dyn Call_AddFromUrl, + args.r#url, + args.r#authToken, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.Inspect" => { + if let Some(args) = req.parameters.clone() { + let args: Inspect_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Runtimes.Remove" => { + if let Some(args) = req.parameters.clone() { + let args: Remove_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.remove(call as &mut dyn Call_Remove, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink_client.rs b/src/varlink_client.rs index fb71d80..5f92a04 100644 --- a/src/varlink_client.rs +++ b/src/varlink_client.rs @@ -42,12 +42,20 @@ pub fn exit_with_rpc_error( std::process::exit(1); } -// ── Log output helper ──────────────────────────────────────────────────────── +// ── Log output helpers ─────────────────────────────────────────────────────── -/// Print log messages returned from the daemon via varlink replies. -pub fn print_log(messages: &[String]) { - for msg in messages { - println!("{msg}"); +/// Print a single log message from a streaming varlink reply. +/// Re-colorizes `[INFO]` and `[SUCCESS]` prefixes for the caller's terminal. +pub fn print_single_log(message: &str, output: &OutputManager) { + if message.is_empty() { + return; + } + if let Some(rest) = message.strip_prefix("[INFO] ") { + output.log_info(rest); + } else if let Some(rest) = message.strip_prefix("[SUCCESS] ") { + output.log_success(rest); + } else { + println!("{message}"); } } diff --git a/src/varlink_server.rs b/src/varlink_server.rs index 931bb09..7160fd6 100644 --- a/src/varlink_server.rs +++ b/src/varlink_server.rs @@ -7,6 +7,48 @@ use crate::varlink::{ org_avocado_Extensions as vl_ext, org_avocado_Hitl as vl_hitl, org_avocado_RootAuthority as vl_ra, org_avocado_Runtimes as vl_rt, }; +use std::sync::mpsc; +use std::thread; +use varlink::CallTrait; + +// ── Streaming helper ─────────────────────────────────────────────── + +/// Drain a streaming channel, sending each message as a varlink reply with +/// `continues: true`. After the channel closes, join the worker thread and +/// send a final reply (success or error). +/// +/// The `reply_fn` sends one intermediate message. The `done_fn` sends the +/// final success reply. The `error_fn` sends an error reply. +fn drain_stream( + call: &mut C, + rx: mpsc::Receiver, + handle: thread::JoinHandle>, + reply_fn: R, + done_fn: D, + error_fn: E, +) -> varlink::Result<()> +where + C: CallTrait + ?Sized, + R: Fn(&mut C, String) -> varlink::Result<()>, + D: Fn(&mut C) -> varlink::Result<()>, + E: Fn(&mut C, AvocadoError) -> varlink::Result<()>, +{ + call.set_continues(true); + for message in rx { + reply_fn(call, message)?; + } + // Channel closed — worker thread is done + let result = handle.join().unwrap_or_else(|_| { + Err(AvocadoError::MergeFailed { + reason: "internal panic".into(), + }) + }); + call.set_continues(false); + match result { + Ok(()) => done_fn(call), + Err(e) => error_fn(call, e), + } +} // ── Extensions handler ────────────────────────────────────────────── @@ -50,9 +92,21 @@ impl vl_ext::VarlinkInterface for ExtensionsHandler { } fn merge(&self, call: &mut dyn vl_ext::Call_Merge) -> varlink::Result<()> { - match service::ext::merge_extensions(&self.config) { - Ok(log) => call.reply(log), - Err(e) => map_ext_error!(call, e), + if call.wants_more() { + let (rx, handle) = service::ext::merge_extensions_streaming(&self.config); + drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_ext_error!(c, e), + ) + } else { + match service::ext::merge_extensions(&self.config) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_ext_error!(call, e), + } } } @@ -61,16 +115,40 @@ impl vl_ext::VarlinkInterface for ExtensionsHandler { call: &mut dyn vl_ext::Call_Unmerge, r#unmount: Option, ) -> varlink::Result<()> { - match service::ext::unmerge_extensions(unmount.unwrap_or(false)) { - Ok(log) => call.reply(log), - Err(e) => map_ext_error!(call, e), + if call.wants_more() { + let (rx, handle) = service::ext::unmerge_extensions_streaming(unmount.unwrap_or(false)); + drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_ext_error!(c, e), + ) + } else { + match service::ext::unmerge_extensions(unmount.unwrap_or(false)) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_ext_error!(call, e), + } } } fn refresh(&self, call: &mut dyn vl_ext::Call_Refresh) -> varlink::Result<()> { - match service::ext::refresh_extensions(&self.config) { - Ok(log) => call.reply(log), - Err(e) => map_ext_error!(call, e), + if call.wants_more() { + let (rx, handle) = service::ext::refresh_extensions_streaming(&self.config); + drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_ext_error!(c, e), + ) + } else { + match service::ext::refresh_extensions(&self.config) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_ext_error!(call, e), + } } } @@ -176,9 +254,24 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { r#url: String, r#authToken: Option, ) -> varlink::Result<()> { - match service::runtime::add_from_url(&url, authToken.as_deref(), &self.config) { - Ok(log) => call.reply(log), - Err(e) => map_rt_error!(call, e), + if call.wants_more() { + match service::runtime::add_from_url_streaming(&url, authToken.as_deref(), &self.config) + { + Ok((rx, handle)) => drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_rt_error!(c, e), + ), + Err(e) => map_rt_error!(call, e), + } + } else { + match service::runtime::add_from_url(&url, authToken.as_deref(), &self.config) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_rt_error!(call, e), + } } } @@ -187,9 +280,23 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { call: &mut dyn vl_rt::Call_AddFromManifest, r#manifestPath: String, ) -> varlink::Result<()> { - match service::runtime::add_from_manifest(&manifestPath, &self.config) { - Ok(log) => call.reply(log), - Err(e) => map_rt_error!(call, e), + if call.wants_more() { + match service::runtime::add_from_manifest_streaming(&manifestPath, &self.config) { + Ok((rx, handle)) => drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_rt_error!(c, e), + ), + Err(e) => map_rt_error!(call, e), + } + } else { + match service::runtime::add_from_manifest(&manifestPath, &self.config) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_rt_error!(call, e), + } } } @@ -201,9 +308,27 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { } fn activate(&self, call: &mut dyn vl_rt::Call_Activate, r#id: String) -> varlink::Result<()> { - match service::runtime::activate_runtime(&id, &self.config) { - Ok(log) => call.reply(log), - Err(e) => map_rt_error!(call, e), + if call.wants_more() { + match service::runtime::activate_runtime_streaming(&id, &self.config) { + Ok(Some((rx, handle))) => drain_stream( + call, + rx, + handle, + |c, msg| c.reply(msg, false), + |c| c.reply(String::new(), true), + |c, e| map_rt_error!(c, e), + ), + Ok(None) => { + // Already active, nothing to stream + call.reply(String::new(), true) + } + Err(e) => map_rt_error!(call, e), + } + } else { + match service::runtime::activate_runtime(&id, &self.config) { + Ok(log) => call.reply(log.join("\n"), true), + Err(e) => map_rt_error!(call, e), + } } } From 295cecfa6162957d1d801cf5c8799cecbd8b8000 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 17:04:33 -0400 Subject: [PATCH 21/27] feat: unify runtime version display as `name version (short_id)` Use consistent `{name} {version} ({8-char-id})` format everywhere: runtime list, inspect, activate, remove, add, status, and ambiguous match messages. Removes the `v` prefix and matches the web UI's display_version format. --- src/commands/ext.rs | 10 +++--- src/commands/runtime.rs | 70 +++++++++++++++++------------------------ src/staging.rs | 6 ++-- src/update.rs | 14 ++++----- src/varlink_client.rs | 36 ++++++--------------- 5 files changed, 54 insertions(+), 82 deletions(-) diff --git a/src/commands/ext.rs b/src/commands/ext.rs index baec140..f7db682 100644 --- a/src/commands/ext.rs +++ b/src/commands/ext.rs @@ -1152,7 +1152,7 @@ fn display_active_runtime(config: &Config, output: &OutputManager) { }; println!("Active Runtime:"); println!( - " {} v{} (build {short_id})", + " {} {} ({short_id})", manifest.runtime.name, manifest.runtime.version ); println!(" Built: {}", manifest.built_at); @@ -1161,7 +1161,7 @@ fn display_active_runtime(config: &Config, output: &OutputManager) { println!(" Build ID: {}", manifest.id); for ext in &manifest.extensions { let id_display = ext.image_id.as_deref().unwrap_or("?"); - println!(" - {} v{} ({})", ext.name, ext.version, id_display); + println!(" - {} {} ({})", ext.name, ext.version, id_display); } } println!(); @@ -1939,8 +1939,10 @@ fn scan_extensions_from_all_sources_with_verbosity( let used_manifest = if let Some(ref manifest) = active_manifest { if verbose { println!( - "Found active runtime manifest: {} v{} (build {})", - manifest.runtime.name, manifest.runtime.version, manifest.id + "Found active runtime manifest: {} {} ({})", + manifest.runtime.name, + manifest.runtime.version, + &manifest.id[..8.min(manifest.id.len())] ); } diff --git a/src/commands/runtime.rs b/src/commands/runtime.rs index d8a430c..1592ea9 100644 --- a/src/commands/runtime.rs +++ b/src/commands/runtime.rs @@ -139,11 +139,10 @@ fn handle_add(matches: &ArgMatches, config: &Config, output: &OutputManager) { std::process::exit(1); } + let short_id = &manifest.id[..8.min(manifest.id.len())]; println!( - " Activated runtime: {} v{} ({})", - manifest.runtime.name, - manifest.runtime.version, - &manifest.id[..8.min(manifest.id.len())] + " Activated runtime: {} {} ({short_id})", + manifest.runtime.name, manifest.runtime.version, ); crate::commands::ext::refresh_extensions(config, output); @@ -168,14 +167,13 @@ fn handle_remove(matches: &ArgMatches, config: &Config, output: &OutputManager) std::process::exit(1); } + let short_id = &matched.id[..8.min(matched.id.len())]; println!(); output.success( "Runtime Remove", &format!( - "Removed runtime: {} v{} ({})", - matched.runtime.name, - matched.runtime.version, - &matched.id[..8.min(matched.id.len())] + "Removed runtime: {} {} ({short_id})", + matched.runtime.name, matched.runtime.version, ), ); } @@ -191,14 +189,14 @@ fn handle_activate(matches: &ArgMatches, config: &Config, output: &OutputManager None => return, }; + let short_id = &matched.id[..8.min(matched.id.len())]; + if is_active { output.info( "Runtime Activate", &format!( - "Runtime {} v{} ({}) is already active.", - matched.runtime.name, - matched.runtime.version, - &matched.id[..8.min(matched.id.len())] + "Runtime {} {} ({short_id}) is already active.", + matched.runtime.name, matched.runtime.version, ), ); return; @@ -210,10 +208,8 @@ fn handle_activate(matches: &ArgMatches, config: &Config, output: &OutputManager } println!( - " Activated runtime: {} v{} ({})", - matched.runtime.name, - matched.runtime.version, - &matched.id[..8.min(matched.id.len())] + " Activated runtime: {} {} ({short_id})", + matched.runtime.name, matched.runtime.version, ); crate::commands::ext::refresh_extensions(config, output); @@ -221,10 +217,8 @@ fn handle_activate(matches: &ArgMatches, config: &Config, output: &OutputManager output.success( "Runtime Activate", &format!( - "Switched to runtime: {} v{} ({})", - matched.runtime.name, - matched.runtime.version, - &matched.id[..8.min(matched.id.len())] + "Switched to runtime: {} {} ({short_id})", + matched.runtime.name, matched.runtime.version, ), ); } @@ -261,10 +255,10 @@ fn handle_inspect(matches: &ArgMatches, config: &Config, output: &OutputManager) println!(); println!( - " Runtime: {} v{}{active_marker}", + " Runtime: {} {} ({short_id}){active_marker}", matched.runtime.name, matched.runtime.version ); - println!(" Build ID: {} ({short_id})", matched.id); + println!(" Build ID: {}", matched.id); println!(" Built: {}", matched.built_at); println!(" Manifest: v{}", matched.manifest_version); println!(); @@ -310,7 +304,7 @@ fn handle_inspect(matches: &ArgMatches, config: &Config, output: &OutputManager) println!(" Full image IDs:"); for ext in &matched.extensions { let id_display = ext.image_id.as_deref().unwrap_or("-"); - println!(" {} v{}: {}", ext.name, ext.version, id_display); + println!(" {} {}: {}", ext.name, ext.version, id_display); } println!(); } @@ -342,12 +336,10 @@ fn resolve_runtime_id<'a>( .iter() .map(|(m, active)| { let marker = if *active { " (active)" } else { "" }; + let sid = &m.id[..8.min(m.id.len())]; format!( - " {} {} v{}{}", - &m.id[..8.min(m.id.len())], - m.runtime.name, - m.runtime.version, - marker + " {} {} ({sid}){}", + m.runtime.name, m.runtime.version, marker ) }) .collect(); @@ -397,25 +389,21 @@ fn list_runtimes(config: &Config, output: &OutputManager) { } println!(); - println!( - " {:<16} {:<12} {:<10} {:<24} STATUS", - "NAME", "VERSION", "BUILD ID", "BUILT AT" - ); + println!(" {:<32} {:<12} BUILT AT", "RUNTIME", "ACTIVE"); for (manifest, is_active) in &runtimes { - let short_id = if manifest.id.len() >= 8 { - &manifest.id[..8] - } else { - &manifest.id - }; + let short_id = &manifest.id[..8.min(manifest.id.len())]; + let runtime_label = format!( + "{} {} ({short_id})", + manifest.runtime.name, manifest.runtime.version + ); let built_at_display = manifest.built_at.replace('T', " ").replace('Z', ""); - - let status = if *is_active { "active" } else { "" }; + let status = if *is_active { "* active" } else { "" }; println!( - " {:<16} {:<12} {:<10} {:<24} {}", - manifest.runtime.name, manifest.runtime.version, short_id, built_at_display, status + " {:<32} {:<12} {}", + runtime_label, status, built_at_display ); } diff --git a/src/staging.rs b/src/staging.rs index 33d13a2..693e1fe 100644 --- a/src/staging.rs +++ b/src/staging.rs @@ -39,7 +39,7 @@ pub fn validate_manifest_images( None } else { Some(MissingImage { - extension_name: format!("{} v{}", ext.name, ext.version), + extension_name: format!("{} {}", ext.name, ext.version), expected_path: path.display().to_string(), }) } @@ -75,7 +75,7 @@ pub fn stage_manifest( if verbose { println!( - " Staged runtime: {} v{} (build {})", + " Staged runtime: {} {} ({})", manifest.runtime.name, manifest.runtime.version, &manifest.id[..8.min(manifest.id.len())] @@ -216,7 +216,7 @@ mod tests { let result = validate_manifest_images(&manifest, tmp.path()); assert!(result.is_err()); let err = result.unwrap_err().to_string(); - assert!(err.contains("app v0.1.0")); + assert!(err.contains("app 0.1.0")); assert!(err.contains("a1b2c3d4-e5f6-5789-abcd-ef0123456789.raw")); } diff --git a/src/update.rs b/src/update.rs index 79afa19..190a21f 100644 --- a/src/update.rs +++ b/src/update.rs @@ -232,11 +232,10 @@ pub fn perform_update( .map_err(|e| UpdateError::StagingFailed(format!("Invalid manifest.json: {e}")))?; if verbose { + let short_id = &new_manifest.id[..8.min(new_manifest.id.len())]; println!( - " New runtime: {} v{} (build {})", - new_manifest.runtime.name, - new_manifest.runtime.version, - &new_manifest.id[..8.min(new_manifest.id.len())] + " New runtime: {} {} ({short_id})", + new_manifest.runtime.name, new_manifest.runtime.version, ); } @@ -249,11 +248,10 @@ pub fn perform_update( staging::activate_runtime(&new_manifest.id, base_dir) .map_err(|e| UpdateError::StagingFailed(e.to_string()))?; + let short_id = &new_manifest.id[..8.min(new_manifest.id.len())]; println!( - " Activated runtime: {} v{} ({})", - new_manifest.runtime.name, - new_manifest.runtime.version, - &new_manifest.id[..8.min(new_manifest.id.len())] + " Activated runtime: {} {} ({short_id})", + new_manifest.runtime.name, new_manifest.runtime.version, ); // Clean up staging directory diff --git a/src/varlink_client.rs b/src/varlink_client.rs index 5f92a04..00a0760 100644 --- a/src/varlink_client.rs +++ b/src/varlink_client.rs @@ -206,35 +206,15 @@ pub fn print_runtimes(runtimes: &[vl_rt::Runtime], output: &OutputManager) { return; } - let id_width = runtimes - .iter() - .map(|r| r.id.len().min(12)) - .max() - .unwrap_or(8) - .max(8); - - println!( - "{: Date: Sun, 8 Mar 2026 17:20:50 -0400 Subject: [PATCH 22/27] feat: improve TUF update logging and warn on missing images Always log key TUF metadata info (target counts, delegation status, manifest extensions). Warn when delegation has no targets or when extension images are missing after staging. Verbose flag still controls per-item detail logging. --- src/staging.rs | 28 ++++++++++++++-- src/update.rs | 86 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/src/staging.rs b/src/staging.rs index 693e1fe..928ab74 100644 --- a/src/staging.rs +++ b/src/staging.rs @@ -96,12 +96,17 @@ pub fn install_images_from_staging( let images_dir = base_dir.join(IMAGES_DIR_NAME); let _ = fs::create_dir_all(&images_dir); + let mut missing = Vec::new(); + for ext in &manifest.extensions { if let Some(ref image_id) = ext.image_id { let dest = images_dir.join(format!("{image_id}.raw")); if dest.exists() { if verbose { - println!(" Image already present: {} ({})", ext.name, image_id); + println!( + " Image already present: {} {} ({})", + ext.name, ext.version, image_id + ); } continue; } @@ -114,12 +119,31 @@ pub fn install_images_from_staging( )) })?; if verbose { - println!(" Installed image: {} -> {}.raw", ext.name, image_id); + println!( + " Installed image: {} {} -> {}.raw", + ext.name, ext.version, image_id + ); } + } else { + println!( + " WARNING: Image not in staging and not on disk: {} {} ({})", + ext.name, ext.version, image_id + ); + missing.push(format!("{} {} ({})", ext.name, ext.version, image_id)); } } } + if !missing.is_empty() { + println!( + " WARNING: {} extension image(s) missing after staging:", + missing.len() + ); + for m in &missing { + println!(" - {m}"); + } + } + Ok(()) } diff --git a/src/update.rs b/src/update.rs index 190a21f..43f02e7 100644 --- a/src/update.rs +++ b/src/update.rs @@ -52,13 +52,11 @@ pub fn perform_update( let root = &signed_root.signed; let trusted_keys = extract_trusted_keys(root)?; - if verbose { - println!( - " Loaded trust anchor: version {}, {} trusted key(s)", - root.version, - trusted_keys.len() - ); - } + println!( + " Trust anchor: version {}, {} trusted key(s)", + root.version, + trusted_keys.len() + ); // 2. Fetch and verify remote metadata (TUF order: timestamp -> snapshot -> targets) println!(" Fetching update metadata..."); @@ -76,12 +74,10 @@ pub fn perform_update( &tough::schema::RoleType::Timestamp, )?; - if verbose { - println!( - " Verified timestamp.json (version {})", - timestamp.signed.version - ); - } + println!( + " Verified timestamp.json (version {})", + timestamp.signed.version + ); let snapshot_url = format!("{url}/metadata/snapshot.json"); let snapshot_raw = fetch_url(&snapshot_url, auth_token)?; @@ -96,12 +92,10 @@ pub fn perform_update( &tough::schema::RoleType::Snapshot, )?; - if verbose { - println!( - " Verified snapshot.json (version {})", - snapshot.signed.version - ); - } + println!( + " Verified snapshot.json (version {})", + snapshot.signed.version + ); let targets_url = format!("{url}/metadata/targets.json"); let targets_raw = fetch_url(&targets_url, auth_token)?; @@ -116,20 +110,29 @@ pub fn perform_update( &tough::schema::RoleType::Targets, )?; + let inline_count = targets.signed.targets.len(); + println!( + " Verified targets.json (version {}, {} inline target(s))", + targets.signed.version, inline_count + ); if verbose { - println!( - " Verified targets.json (version {})", - targets.signed.version - ); + for (name, _) in targets.signed.targets.iter() { + println!(" inline target: {}", name.raw()); + } } // 3a. Walk delegations if present — collect delegated targets let mut delegated_targets: Vec<(String, tough::schema::Target)> = Vec::new(); if let Some(delegations) = &targets.signed.delegations { + println!( + " Found {} delegation(s) in targets.json", + delegations.roles.len() + ); for role in &delegations.roles { let role_path = format!("delegations/{}.json", role.name); let delegation_url = format!("{url}/metadata/{role_path}"); + println!(" Fetching delegation: {}", role.name); let delegation_raw = fetch_url(&delegation_url, auth_token)?; // Verify hash + length against snapshot meta entry @@ -147,18 +150,26 @@ pub fn perform_update( role.threshold, )?; + println!( + " Verified delegation {} ({} target(s))", + role.name, + delegation.signed.targets.len() + ); if verbose { - println!( - " Verified delegation {} ({} target(s))", - role.name, - delegation.signed.targets.len() - ); + for (name, _) in delegation.signed.targets.iter() { + println!(" delegated target: {}", name.raw()); + } + } + if delegation.signed.targets.is_empty() { + println!(" WARNING: Delegation '{}' has no targets — extension images will not be downloaded!", role.name); } for (name, info) in &delegation.signed.targets { delegated_targets.push((name.raw().to_string(), info.clone())); } } + } else { + println!(" No delegations found in targets.json"); } // 3b. Enumerate and download targets (inline + delegated) @@ -231,12 +242,18 @@ pub fn perform_update( let new_manifest: RuntimeManifest = serde_json::from_str(&manifest_content) .map_err(|e| UpdateError::StagingFailed(format!("Invalid manifest.json: {e}")))?; - if verbose { - let short_id = &new_manifest.id[..8.min(new_manifest.id.len())]; - println!( - " New runtime: {} {} ({short_id})", - new_manifest.runtime.name, new_manifest.runtime.version, - ); + let short_id = &new_manifest.id[..8.min(new_manifest.id.len())]; + println!( + " New runtime: {} {} ({short_id})", + new_manifest.runtime.name, new_manifest.runtime.version, + ); + println!( + " Manifest lists {} extension(s):", + new_manifest.extensions.len() + ); + for ext in &new_manifest.extensions { + let img = ext.image_id.as_deref().unwrap_or("none"); + println!(" {} {} (image: {})", ext.name, ext.version, img); } staging::install_images_from_staging(&new_manifest, &staging_dir, base_dir, verbose) @@ -282,7 +299,6 @@ fn download_target( } let target_url = format!("{url}/targets/{name_str}"); - if verbose { println!(" Downloading {name_str}..."); } From 6c0f2502b9de49bb07579f3ec892c23818ddfcd5 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 17:46:19 -0400 Subject: [PATCH 23/27] feat: download extension images from artifacts URL during TUF update Route .raw TUF targets to the artifacts CDN URL when available, falling back to the TUF repo targets/ path for local deploy. Always send auth token for artifact downloads. Fail activation when extension images are missing instead of warning. --- src/commands/runtime.rs | 8 +- src/main.rs | 2 +- src/service/runtime.rs | 6 +- src/staging.rs | 10 +- src/update.rs | 20 +- src/varlink/org.avocado.Runtimes.varlink | 2 +- src/varlink/org_avocado_Extensions.rs | 638 +---------------------- src/varlink/org_avocado_Hitl.rs | 347 +----------- src/varlink/org_avocado_RootAuthority.rs | 261 +--------- src/varlink/org_avocado_Runtimes.rs | 600 +-------------------- src/varlink_server.rs | 16 +- 11 files changed, 52 insertions(+), 1858 deletions(-) diff --git a/src/commands/runtime.rs b/src/commands/runtime.rs index 1592ea9..dee711a 100644 --- a/src/commands/runtime.rs +++ b/src/commands/runtime.rs @@ -89,7 +89,13 @@ fn handle_add(matches: &ArgMatches, config: &Config, output: &OutputManager) { println!(); let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); - match update::perform_update(url, base_path, auth_token.as_deref(), output.is_verbose()) { + match update::perform_update( + url, + base_path, + auth_token.as_deref(), + None, + output.is_verbose(), + ) { Ok(()) => { crate::commands::ext::refresh_extensions(config, output); println!(); diff --git a/src/main.rs b/src/main.rs index 235bee4..b595e61 100644 --- a/src/main.rs +++ b/src/main.rs @@ -326,7 +326,7 @@ fn main() { if let Some(url) = add_matches.get_one::("url") { let auth_token = std::env::var("AVOCADO_TUF_AUTH_TOKEN").ok(); let mut client = vl_rt::VarlinkClient::new(conn); - match client.add_from_url(url.clone(), auth_token).more() { + match client.add_from_url(url.clone(), auth_token, None).more() { Ok(iter) => { for reply in iter { match reply { diff --git a/src/service/runtime.rs b/src/service/runtime.rs index 8f45d47..5b74d61 100644 --- a/src/service/runtime.rs +++ b/src/service/runtime.rs @@ -53,11 +53,12 @@ pub fn list_runtimes(config: &Config) -> Result, AvocadoError> pub fn add_from_url_streaming( url: &str, auth_token: Option<&str>, + artifacts_url: Option<&str>, config: &Config, ) -> Result { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); - update::perform_update(url, base_path, auth_token, false)?; + update::perform_update(url, base_path, auth_token, artifacts_url, false)?; Ok(super::ext::refresh_extensions_streaming(config)) } @@ -112,11 +113,12 @@ pub fn activate_runtime_streaming( pub fn add_from_url( url: &str, auth_token: Option<&str>, + artifacts_url: Option<&str>, config: &Config, ) -> Result, AvocadoError> { let base_dir = config.get_avocado_base_dir(); let base_path = Path::new(&base_dir); - update::perform_update(url, base_path, auth_token, false)?; + update::perform_update(url, base_path, auth_token, artifacts_url, false)?; super::ext::refresh_extensions(config) } diff --git a/src/staging.rs b/src/staging.rs index 928ab74..48d352f 100644 --- a/src/staging.rs +++ b/src/staging.rs @@ -135,13 +135,11 @@ pub fn install_images_from_staging( } if !missing.is_empty() { - println!( - " WARNING: {} extension image(s) missing after staging:", + let details = missing.join(", "); + return Err(StagingError::StagingFailed(format!( + "{} extension image(s) missing after staging: {details}", missing.len() - ); - for m in &missing { - println!(" - {m}"); - } + ))); } Ok(()) diff --git a/src/update.rs b/src/update.rs index 43f02e7..ca2f7e7 100644 --- a/src/update.rs +++ b/src/update.rs @@ -36,6 +36,7 @@ pub fn perform_update( url: &str, base_dir: &Path, auth_token: Option<&str>, + artifacts_url: Option<&str>, verbose: bool, ) -> Result<(), UpdateError> { let url = url.trim_end_matches('/'); @@ -214,6 +215,7 @@ pub fn perform_update( &staging_dir, &existing_images, auth_token, + artifacts_url, verbose, )?; } @@ -227,6 +229,7 @@ pub fn perform_update( &staging_dir, &existing_images, auth_token, + artifacts_url, verbose, )?; } @@ -280,6 +283,7 @@ pub fn perform_update( /// Download a single target file into the staging directory, verifying hash and length. /// Skips content-addressable image files that already exist on disk. +#[allow(clippy::too_many_arguments)] fn download_target( url: &str, name_str: &str, @@ -287,6 +291,7 @@ fn download_target( staging_dir: &Path, existing_images: &std::collections::HashSet, auth_token: Option<&str>, + artifacts_url: Option<&str>, verbose: bool, ) -> Result<(), UpdateError> { // Content-addressable skip: if this target is an image that already @@ -298,7 +303,18 @@ fn download_target( return Ok(()); } - let target_url = format!("{url}/targets/{name_str}"); + // .raw image files are fetched from the artifacts URL (shared blob storage) + // rather than the per-device TUF repo, but still verified against TUF hashes. + let target_url = if name_str.ends_with(".raw") { + if let Some(art_url) = artifacts_url { + let art_url = art_url.trim_end_matches('/'); + format!("{art_url}/{name_str}") + } else { + format!("{url}/targets/{name_str}") + } + } else { + format!("{url}/targets/{name_str}") + }; if verbose { println!(" Downloading {name_str}..."); } @@ -707,7 +723,7 @@ mod tests { #[test] fn test_no_trust_anchor() { let tmp = tempfile::TempDir::new().unwrap(); - let result = perform_update("http://localhost:9999", tmp.path(), None, false); + let result = perform_update("http://localhost:9999", tmp.path(), None, None, false); assert!(matches!(result, Err(UpdateError::NoTrustAnchor))); } diff --git a/src/varlink/org.avocado.Runtimes.varlink b/src/varlink/org.avocado.Runtimes.varlink index 2a638a3..98b7957 100644 --- a/src/varlink/org.avocado.Runtimes.varlink +++ b/src/varlink/org.avocado.Runtimes.varlink @@ -26,7 +26,7 @@ method List() -> (runtimes: []Runtime) # Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints) # Supports streaming: client may set more=true to receive per-message progress -method AddFromUrl(url: string, authToken: ?string) -> (message: string, done: bool) +method AddFromUrl(url: string, authToken: ?string, artifactsUrl: ?string) -> (message: string, done: bool) # Add a runtime from a local manifest file # Supports streaming: client may set more=true to receive per-message progress diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index 16a4e7f..8880893 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1,637 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - CommandFailed(Option), - ConfigurationError(Option), - ExtensionNotFound(Option), - MergeFailed(Option), - UnmergeFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::CommandFailed(v) => { - write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) - } - ErrorKind::ConfigurationError(v) => { - write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) - } - ErrorKind::ExtensionNotFound(v) => { - write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) - } - ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), - ErrorKind::UnmergeFailed(v) => { - write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.CommandFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::CommandFailed(v), - Err(_) => ErrorKind::CommandFailed(None), - }, - _ => ErrorKind::CommandFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ConfigurationError" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ConfigurationError(v), - Err(_) => ErrorKind::ConfigurationError(None), - }, - _ => ErrorKind::ConfigurationError(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.ExtensionNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ExtensionNotFound(v), - Err(_) => ErrorKind::ExtensionNotFound(None), - }, - _ => ErrorKind::ExtensionNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MergeFailed(v), - Err(_) => ErrorKind::MergeFailed(None), - }, - _ => ErrorKind::MergeFailed(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Extensions.UnmergeFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmergeFailed(v), - Err(_) => ErrorKind::UnmergeFailed(None), - }, - _ => ErrorKind::UnmergeFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_command_failed( - &mut self, - r#command: String, - r#message: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.CommandFailed", - Some( - serde_json::to_value(CommandFailed_Args { - r#command, - r#message, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ConfigurationError", - Some( - serde_json::to_value(ConfigurationError_Args { r#message }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.ExtensionNotFound", - Some( - serde_json::to_value(ExtensionNotFound_Args { r#name }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.MergeFailed", - Some( - serde_json::to_value(MergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Extensions.UnmergeFailed", - Some( - serde_json::to_value(UnmergeFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Extension { - pub r#name: String, - pub r#version: Option, - pub r#path: String, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isDirectory: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ExtensionStatus { - pub r#name: String, - pub r#version: Option, - pub r#isSysext: bool, - pub r#isConfext: bool, - pub r#isMerged: bool, - pub r#origin: Option, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct CommandFailed_Args { - pub r#command: String, - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ConfigurationError_Args { - pub r#message: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ExtensionNotFound_Args { - pub r#name: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmergeFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Reply { - pub r#disabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Disable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Disable_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#extensions: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#all: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Disable: VarlinkCallError { - fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Disable_Reply { - r#disabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Disable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Reply { - pub r#enabled: i64, - pub r#failed: i64, -} -impl varlink::VarlinkReply for Enable_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Enable_Args { - pub r#extensions: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#osRelease: Option, -} -#[allow(dead_code)] -pub trait Call_Enable: VarlinkCallError { - fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { - self.reply_struct( - Enable_Reply { - r#enabled, - r#failed, - } - .into(), - ) - } -} -impl Call_Enable for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#extensions }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for Merge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Merge_Args {} -#[allow(dead_code)] -pub trait Call_Merge: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(Merge_Reply { r#message, r#done }.into()) - } -} -impl Call_Merge for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for Refresh_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Refresh_Args {} -#[allow(dead_code)] -pub trait Call_Refresh: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(Refresh_Reply { r#message, r#done }.into()) - } -} -impl Call_Refresh for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Reply { - pub r#extensions: Vec, -} -impl varlink::VarlinkReply for Status_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Status_Args {} -#[allow(dead_code)] -pub trait Call_Status: VarlinkCallError { - fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { - self.reply_struct(Status_Reply { r#extensions }.into()) - } -} -impl Call_Status for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for Unmerge_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmerge_Args { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#unmount: Option, -} -#[allow(dead_code)] -pub trait Call_Unmerge: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(Unmerge_Reply { r#message, r#done }.into()) - } -} -impl Call_Unmerge for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn disable( - &self, - call: &mut dyn Call_Disable, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn enable( - &self, - call: &mut dyn Call_Enable, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; - fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; - fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; - fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn merge(&mut self) -> varlink::MethodCall; - fn refresh(&mut self) -> varlink::MethodCall; - fn status(&mut self) -> varlink::MethodCall; - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn disable( - &mut self, - r#extensions: Option>, - r#all: Option, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Disable", - Disable_Args { - r#extensions, - r#all, - r#osRelease, - }, - ) - } - fn enable( - &mut self, - r#extensions: Vec, - r#osRelease: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Enable", - Enable_Args { - r#extensions, - r#osRelease, - }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.List", - List_Args {}, - ) - } - fn merge(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Merge", - Merge_Args {}, - ) - } - fn refresh(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Refresh", - Refresh_Args {}, - ) - } - fn status(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Status", - Status_Args {}, - ) - } - fn unmerge( - &mut self, - r#unmount: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Extensions.Unmerge", - Unmerge_Args { r#unmount }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Merge() -> (message: string, done: bool)\n\n# Unmerge extensions\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Unmerge(unmount: ?bool) -> (message: string, done: bool)\n\n# Refresh extensions (unmerge then merge)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Refresh() -> (message: string, done: bool)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Extensions" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Extensions.Disable" => { - if let Some(args) = req.parameters.clone() { - let args: Disable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.disable( - call as &mut dyn Call_Disable, - args.r#extensions, - args.r#all, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.Enable" => { - if let Some(args) = req.parameters.clone() { - let args: Enable_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.enable( - call as &mut dyn Call_Enable, - args.r#extensions, - args.r#osRelease, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), - "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), - "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), - "org.avocado.Extensions.Unmerge" => { - if let Some(args) = req.parameters.clone() { - let args: Unmerge_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Merge_Reply { r#message , r#done } . into ()) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Refresh_Reply { r#message , r#done } . into ()) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Unmerge_Reply { r#message , r#done } . into ()) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Merge() -> (message: string, done: bool)\n\n# Unmerge extensions\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Unmerge(unmount: ?bool) -> (message: string, done: bool)\n\n# Refresh extensions (unmerge then merge)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Refresh() -> (message: string, done: bool)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 59a04ea..7720a1d 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1,346 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - MountFailed(Option), - UnmountFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), - ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e - { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::MountFailed(v), - Err(_) => ErrorKind::MountFailed(None), - }, - _ => ErrorKind::MountFailed(None), - }, - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UnmountFailed(v), - Err(_) => ErrorKind::UnmountFailed(None), - }, - _ => ErrorKind::UnmountFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.MountFailed", - Some( - serde_json::to_value(MountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_unmount_failed( - &mut self, - r#extension: String, - r#reason: String, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Hitl.UnmountFailed", - Some( - serde_json::to_value(UnmountFailed_Args { - r#extension, - r#reason, - }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct MountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UnmountFailed_Args { - pub r#extension: String, - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Reply {} -impl varlink::VarlinkReply for Mount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Mount_Args { - pub r#serverIp: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#serverPort: Option, - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Mount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Mount for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Reply {} -impl varlink::VarlinkReply for Unmount_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Unmount_Args { - pub r#extensions: Vec, -} -#[allow(dead_code)] -pub trait Call_Unmount: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Unmount for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn mount( - &self, - call: &mut dyn Call_Mount, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn unmount( - &self, - call: &mut dyn Call_Unmount, - r#extensions: Vec, - ) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall; - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn mount( - &mut self, - r#serverIp: String, - r#serverPort: Option, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Mount", - Mount_Args { - r#serverIp, - r#serverPort, - r#extensions, - }, - ) - } - fn unmount( - &mut self, - r#extensions: Vec, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Hitl.Unmount", - Unmount_Args { r#extensions }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Hitl" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Hitl.Mount" => { - if let Some(args) = req.parameters.clone() { - let args: Mount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.mount( - call as &mut dyn Call_Mount, - args.r#serverIp, - args.r#serverPort, - args.r#extensions, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Hitl.Unmount" => { - if let Some(args) = req.parameters.clone() { - let args: Unmount_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .unmount(call as &mut dyn Call_Unmount, args.r#extensions) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index c8d4a18..029ad69 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1,260 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - NoRootAuthority(Option), - ParseFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::NoRootAuthority(v) => { - write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) - } - ErrorKind::ParseFailed(v) => { - write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) - } - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.NoRootAuthority" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::NoRootAuthority(v), - Err(_) => ErrorKind::NoRootAuthority(None), - }, - _ => ErrorKind::NoRootAuthority(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.RootAuthority.ParseFailed" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::ParseFailed(v), - Err(_) => ErrorKind::ParseFailed(None), - }, - _ => ErrorKind::ParseFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_no_root_authority(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.NoRootAuthority", - None, - )) - } - fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.RootAuthority.ParseFailed", - Some( - serde_json::to_value(ParseFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RootAuthorityInfo { - pub r#version: i64, - pub r#expires: String, - pub r#keys: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#TrustedKey { - pub r#keyId: String, - pub r#keyType: String, - pub r#roles: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct NoRootAuthority_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct ParseFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Reply { - #[serde(skip_serializing_if = "Option::is_none")] - pub r#authority: Option, -} -impl varlink::VarlinkReply for Show_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Show_Args {} -#[allow(dead_code)] -pub trait Call_Show: VarlinkCallError { - fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { - self.reply_struct(Show_Reply { r#authority }.into()) - } -} -impl Call_Show for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn show(&mut self) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn show(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.RootAuthority.Show", - Show_Args {}, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.RootAuthority" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index df96120..aeeb3e7 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1,599 +1 @@ -#![doc = "This file was automatically generated by the varlink rust generator"] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -use serde_derive::{Deserialize, Serialize}; -use std::io::BufRead; -use std::sync::{Arc, RwLock}; -use varlink::{self, CallTrait}; -#[allow(dead_code)] -#[derive(Clone, PartialEq, Debug)] -#[allow(clippy::enum_variant_names)] -pub enum ErrorKind { - Varlink_Error, - VarlinkReply_Error, - AmbiguousRuntimeId(Option), - RemoveActiveRuntime(Option), - RuntimeNotFound(Option), - StagingFailed(Option), - UpdateFailed(Option), -} -impl ::std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match self { - ErrorKind::Varlink_Error => write!(f, "Varlink Error"), - ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), - ErrorKind::AmbiguousRuntimeId(v) => { - write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) - } - ErrorKind::RemoveActiveRuntime(v) => { - write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) - } - ErrorKind::RuntimeNotFound(v) => { - write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) - } - ErrorKind::StagingFailed(v) => { - write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) - } - ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), - } - } -} -pub struct Error( - pub ErrorKind, - pub Option>, - pub Option<&'static str>, -); -impl Error { - #[allow(dead_code)] - pub fn kind(&self) -> &ErrorKind { - &self.0 - } -} -impl From for Error { - fn from(e: ErrorKind) -> Self { - Error(e, None, None) - } -} -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.1 - .as_ref() - .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) - } -} -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} -impl std::fmt::Debug for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use std::error::Error as StdError; - if let Some(ref o) = self.2 { - std::fmt::Display::fmt(o, f)?; - } - std::fmt::Debug::fmt(&self.0, f)?; - if let Some(e) = self.source() { - std::fmt::Display::fmt("\nCaused by:\n", f)?; - std::fmt::Debug::fmt(&e, f)?; - } - Ok(()) - } -} -#[allow(dead_code)] -pub type Result = std::result::Result; -impl From for Error { - fn from(e: varlink::Error) -> Self { - match e.kind() { - varlink::ErrorKind::VarlinkErrorReply(r) => Error( - ErrorKind::from(r), - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - _ => Error( - ErrorKind::Varlink_Error, - Some(Box::from(e)), - Some(concat!(file!(), ":", line!(), ": ")), - ), - } - } -} -#[allow(dead_code)] -impl Error { - pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { - use std::error::Error as StdError; - let mut s: &dyn StdError = self; - while let Some(c) = s.source() { - let k = self - .source() - .and_then(|e| e.downcast_ref::()) - .map(|e| e.kind()); - if k.is_some() { - return k; - } - s = c; - } - None - } -} -impl From<&varlink::Reply> for ErrorKind { - #[allow(unused_variables)] - fn from(e: &varlink::Reply) -> Self { - match e { - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::AmbiguousRuntimeId(v), - Err(_) => ErrorKind::AmbiguousRuntimeId(None), - }, - _ => ErrorKind::AmbiguousRuntimeId(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RemoveActiveRuntime" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RemoveActiveRuntime(v), - Err(_) => ErrorKind::RemoveActiveRuntime(None), - }, - _ => ErrorKind::RemoveActiveRuntime(None), - } - } - varlink::Reply { error: Some(t), .. } - if t == "org.avocado.Runtimes.RuntimeNotFound" => - { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::RuntimeNotFound(v), - Err(_) => ErrorKind::RuntimeNotFound(None), - }, - _ => ErrorKind::RuntimeNotFound(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::StagingFailed(v), - Err(_) => ErrorKind::StagingFailed(None), - }, - _ => ErrorKind::StagingFailed(None), - } - } - varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { - match e { - varlink::Reply { - parameters: Some(p), - .. - } => match serde_json::from_value(p.clone()) { - Ok(v) => ErrorKind::UpdateFailed(v), - Err(_) => ErrorKind::UpdateFailed(None), - }, - _ => ErrorKind::UpdateFailed(None), - } - } - _ => ErrorKind::VarlinkReply_Error, - } - } -} -#[allow(dead_code)] -pub trait VarlinkCallError: varlink::CallTrait { - fn reply_ambiguous_runtime_id( - &mut self, - r#id: String, - r#candidates: Vec, - ) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.AmbiguousRuntimeId", - Some( - serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RemoveActiveRuntime", - None, - )) - } - fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.RuntimeNotFound", - Some( - serde_json::to_value(RuntimeNotFound_Args { r#id }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.StagingFailed", - Some( - serde_json::to_value(StagingFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } - fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::error( - "org.avocado.Runtimes.UpdateFailed", - Some( - serde_json::to_value(UpdateFailed_Args { r#reason }) - .map_err(varlink::map_context!())?, - ), - )) - } -} -impl VarlinkCallError for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#ManifestExtension { - pub r#name: String, - pub r#version: String, - pub r#imageId: Option, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#Runtime { - pub r#id: String, - pub r#manifestVersion: i64, - pub r#builtAt: String, - pub r#runtime: RuntimeInfo, - pub r#extensions: Vec, - pub r#active: bool, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct r#RuntimeInfo { - pub r#name: String, - pub r#version: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AmbiguousRuntimeId_Args { - pub r#id: String, - pub r#candidates: Vec, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RemoveActiveRuntime_Args {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct RuntimeNotFound_Args { - pub r#id: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct StagingFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UpdateFailed_Args { - pub r#reason: String, -} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for Activate_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Activate_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Activate: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(Activate_Reply { r#message, r#done }.into()) - } -} -impl Call_Activate for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for AddFromManifest_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromManifest_Args { - pub r#manifestPath: String, -} -#[allow(dead_code)] -pub trait Call_AddFromManifest: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(AddFromManifest_Reply { r#message, r#done }.into()) - } -} -impl Call_AddFromManifest for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Reply { - pub r#message: String, - pub r#done: bool, -} -impl varlink::VarlinkReply for AddFromUrl_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct AddFromUrl_Args { - pub r#url: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub r#authToken: Option, -} -#[allow(dead_code)] -pub trait Call_AddFromUrl: VarlinkCallError { - fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { - self.reply_struct(AddFromUrl_Reply { r#message, r#done }.into()) - } -} -impl Call_AddFromUrl for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Reply { - pub r#runtime: Runtime, -} -impl varlink::VarlinkReply for Inspect_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Inspect_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Inspect: VarlinkCallError { - fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { - self.reply_struct(Inspect_Reply { r#runtime }.into()) - } -} -impl Call_Inspect for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Reply { - pub r#runtimes: Vec, -} -impl varlink::VarlinkReply for List_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct List_Args {} -#[allow(dead_code)] -pub trait Call_List: VarlinkCallError { - fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { - self.reply_struct(List_Reply { r#runtimes }.into()) - } -} -impl Call_List for varlink::Call<'_> {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Reply {} -impl varlink::VarlinkReply for Remove_Reply {} -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct Remove_Args { - pub r#id: String, -} -#[allow(dead_code)] -pub trait Call_Remove: VarlinkCallError { - fn reply(&mut self) -> varlink::Result<()> { - self.reply_struct(varlink::Reply::parameters(None)) - } -} -impl Call_Remove for varlink::Call<'_> {} -#[allow(dead_code)] -pub trait VarlinkInterface { - fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; - fn add_from_manifest( - &self, - call: &mut dyn Call_AddFromManifest, - r#manifestPath: String, - ) -> varlink::Result<()>; - fn add_from_url( - &self, - call: &mut dyn Call_AddFromUrl, - r#url: String, - r#authToken: Option, - ) -> varlink::Result<()>; - fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; - fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; - fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; - fn call_upgraded( - &self, - _call: &mut varlink::Call, - _bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - Ok(Vec::new()) - } -} -#[allow(dead_code)] -pub trait VarlinkClientInterface { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall; - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall; - fn add_from_url( - &mut self, - r#url: String, - r#authToken: Option, - ) -> varlink::MethodCall; - fn inspect(&mut self, r#id: String) -> varlink::MethodCall; - fn list(&mut self) -> varlink::MethodCall; - fn remove(&mut self, r#id: String) -> varlink::MethodCall; -} -#[allow(dead_code)] -pub struct VarlinkClient { - connection: Arc>, -} -impl VarlinkClient { - #[allow(dead_code)] - pub fn new(connection: Arc>) -> Self { - VarlinkClient { connection } - } -} -impl VarlinkClientInterface for VarlinkClient { - fn activate( - &mut self, - r#id: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Activate", - Activate_Args { r#id }, - ) - } - fn add_from_manifest( - &mut self, - r#manifestPath: String, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromManifest", - AddFromManifest_Args { r#manifestPath }, - ) - } - fn add_from_url( - &mut self, - r#url: String, - r#authToken: Option, - ) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.AddFromUrl", - AddFromUrl_Args { r#url, r#authToken }, - ) - } - fn inspect(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Inspect", - Inspect_Args { r#id }, - ) - } - fn list(&mut self) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.List", - List_Args {}, - ) - } - fn remove(&mut self, r#id: String) -> varlink::MethodCall { - varlink::MethodCall::::new( - self.connection.clone(), - "org.avocado.Runtimes.Remove", - Remove_Args { r#id }, - ) - } -} -#[allow(dead_code)] -pub struct VarlinkInterfaceProxy { - inner: Box, -} -#[allow(dead_code)] -pub fn new(inner: Box) -> VarlinkInterfaceProxy { - VarlinkInterfaceProxy { inner } -} -impl varlink::Interface for VarlinkInterfaceProxy { - fn get_description(&self) -> &'static str { - "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromUrl(url: string, authToken: ?string) -> (message: string, done: bool)\n\n# Add a runtime from a local manifest file\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromManifest(manifestPath: string) -> (message: string, done: bool)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Activate(id: string) -> (message: string, done: bool)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" - } - fn get_name(&self) -> &'static str { - "org.avocado.Runtimes" - } - fn call_upgraded( - &self, - call: &mut varlink::Call, - bufreader: &mut dyn BufRead, - ) -> varlink::Result> { - self.inner.call_upgraded(call, bufreader) - } - fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { - let req = call.request.unwrap(); - match req.method.as_ref() { - "org.avocado.Runtimes.Activate" => { - if let Some(args) = req.parameters.clone() { - let args: Activate_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner - .activate(call as &mut dyn Call_Activate, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromManifest" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromManifest_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.add_from_manifest( - call as &mut dyn Call_AddFromManifest, - args.r#manifestPath, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.AddFromUrl" => { - if let Some(args) = req.parameters.clone() { - let args: AddFromUrl_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.add_from_url( - call as &mut dyn Call_AddFromUrl, - args.r#url, - args.r#authToken, - ) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.Inspect" => { - if let Some(args) = req.parameters.clone() { - let args: Inspect_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), - "org.avocado.Runtimes.Remove" => { - if let Some(args) = req.parameters.clone() { - let args: Remove_Args = match serde_json::from_value(args) { - Ok(v) => v, - Err(e) => { - let es = format!("{}", e); - let _ = call.reply_invalid_parameter(es.clone()); - return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); - } - }; - self.inner.remove(call as &mut dyn Call_Remove, args.r#id) - } else { - call.reply_invalid_parameter("parameters".into()) - } - } - m => call.reply_method_not_found(String::from(m)), - } - } -} +# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Activate_Reply { r#message , r#done } . into ()) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (AddFromManifest_Reply { r#message , r#done } . into ()) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#artifactsUrl : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (AddFromUrl_Reply { r#message , r#done } . into ()) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken , r#artifactsUrl }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromUrl(url: string, authToken: ?string, artifactsUrl: ?string) -> (message: string, done: bool)\n\n# Add a runtime from a local manifest file\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromManifest(manifestPath: string) -> (message: string, done: bool)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Activate(id: string) -> (message: string, done: bool)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken , args . r#artifactsUrl) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file diff --git a/src/varlink_server.rs b/src/varlink_server.rs index 7160fd6..a248d40 100644 --- a/src/varlink_server.rs +++ b/src/varlink_server.rs @@ -253,10 +253,15 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { call: &mut dyn vl_rt::Call_AddFromUrl, r#url: String, r#authToken: Option, + r#artifactsUrl: Option, ) -> varlink::Result<()> { if call.wants_more() { - match service::runtime::add_from_url_streaming(&url, authToken.as_deref(), &self.config) - { + match service::runtime::add_from_url_streaming( + &url, + authToken.as_deref(), + artifactsUrl.as_deref(), + &self.config, + ) { Ok((rx, handle)) => drain_stream( call, rx, @@ -268,7 +273,12 @@ impl vl_rt::VarlinkInterface for RuntimesHandler { Err(e) => map_rt_error!(call, e), } } else { - match service::runtime::add_from_url(&url, authToken.as_deref(), &self.config) { + match service::runtime::add_from_url( + &url, + authToken.as_deref(), + artifactsUrl.as_deref(), + &self.config, + ) { Ok(log) => call.reply(log.join("\n"), true), Err(e) => map_rt_error!(call, e), } From a1ee055616a8c2fbf88e9b0c4a60901000051e93 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 18:50:18 -0400 Subject: [PATCH 24/27] fix: log varlink errors to stderr so they appear in journal output Download failures and other runtime errors were silently returned via varlink without logging, making them invisible in avocadoctl's journal. Now drain_stream() and map_rt_error!() print errors to stderr before sending the varlink error reply. --- src/varlink_server.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/varlink_server.rs b/src/varlink_server.rs index a248d40..3ef52c3 100644 --- a/src/varlink_server.rs +++ b/src/varlink_server.rs @@ -46,7 +46,10 @@ where call.set_continues(false); match result { Ok(()) => done_fn(call), - Err(e) => error_fn(call, e), + Err(e) => { + eprintln!(" Error: {e}"); + error_fn(call, e) + } } } @@ -200,7 +203,8 @@ pub struct RuntimesHandler { } macro_rules! map_rt_error { - ($call:expr, $err:expr) => { + ($call:expr, $err:expr) => {{ + eprintln!(" Error: {}", $err); match $err { AvocadoError::RuntimeNotFound { id } => $call.reply_runtime_not_found(id), AvocadoError::AmbiguousRuntimeId { id, candidates } => { @@ -211,7 +215,7 @@ macro_rules! map_rt_error { AvocadoError::UpdateFailed { reason } => $call.reply_update_failed(reason), e => $call.reply_staging_failed(e.to_string()), } - }; + }}; } fn runtime_entry_to_varlink(entry: crate::service::types::RuntimeEntry) -> vl_rt::Runtime { From c02996c41e0611748cd1b1c7237d7c8b1156a0c6 Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 19:08:40 -0400 Subject: [PATCH 25/27] style: reformat generated varlink interface files --- src/varlink/org_avocado_Extensions.rs | 638 ++++++++++++++++++++++- src/varlink/org_avocado_Hitl.rs | 347 +++++++++++- src/varlink/org_avocado_RootAuthority.rs | 261 +++++++++- src/varlink/org_avocado_Runtimes.rs | 610 +++++++++++++++++++++- 4 files changed, 1852 insertions(+), 4 deletions(-) diff --git a/src/varlink/org_avocado_Extensions.rs b/src/varlink/org_avocado_Extensions.rs index 8880893..16a4e7f 100644 --- a/src/varlink/org_avocado_Extensions.rs +++ b/src/varlink/org_avocado_Extensions.rs @@ -1 +1,637 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , CommandFailed (Option < CommandFailed_Args >) , ConfigurationError (Option < ConfigurationError_Args >) , ExtensionNotFound (Option < ExtensionNotFound_Args >) , MergeFailed (Option < MergeFailed_Args >) , UnmergeFailed (Option < UnmergeFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: CommandFailed (v) => write ! (f , "org.avocado.Extensions.CommandFailed: {:#?}" , v) , ErrorKind :: ConfigurationError (v) => write ! (f , "org.avocado.Extensions.ConfigurationError: {:#?}" , v) , ErrorKind :: ExtensionNotFound (v) => write ! (f , "org.avocado.Extensions.ExtensionNotFound: {:#?}" , v) , ErrorKind :: MergeFailed (v) => write ! (f , "org.avocado.Extensions.MergeFailed: {:#?}" , v) , ErrorKind :: UnmergeFailed (v) => write ! (f , "org.avocado.Extensions.UnmergeFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.CommandFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: CommandFailed (v) , Err (_) => ErrorKind :: CommandFailed (None) , } , _ => ErrorKind :: CommandFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ConfigurationError" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ConfigurationError (v) , Err (_) => ErrorKind :: ConfigurationError (None) , } , _ => ErrorKind :: ConfigurationError (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.ExtensionNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ExtensionNotFound (v) , Err (_) => ErrorKind :: ExtensionNotFound (None) , } , _ => ErrorKind :: ExtensionNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.MergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MergeFailed (v) , Err (_) => ErrorKind :: MergeFailed (None) , } , _ => ErrorKind :: MergeFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Extensions.UnmergeFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmergeFailed (v) , Err (_) => ErrorKind :: UnmergeFailed (None) , } , _ => ErrorKind :: UnmergeFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_command_failed (& mut self , r#command : String , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.CommandFailed" , Some (serde_json :: to_value (CommandFailed_Args { r#command , r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_configuration_error (& mut self , r#message : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ConfigurationError" , Some (serde_json :: to_value (ConfigurationError_Args { r#message }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_extension_not_found (& mut self , r#name : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.ExtensionNotFound" , Some (serde_json :: to_value (ExtensionNotFound_Args { r#name }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_merge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.MergeFailed" , Some (serde_json :: to_value (MergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmerge_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Extensions.UnmergeFailed" , Some (serde_json :: to_value (UnmergeFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Extension { pub r#name : String , pub r#version : Option < String > , pub r#path : String , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isDirectory : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ExtensionStatus { pub r#name : String , pub r#version : Option < String > , pub r#isSysext : bool , pub r#isConfext : bool , pub r#isMerged : bool , pub r#origin : Option < String > , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct CommandFailed_Args { pub r#command : String , pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ConfigurationError_Args { pub r#message : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ExtensionNotFound_Args { pub r#name : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmergeFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Reply { pub r#disabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Disable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Disable_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#extensions : Option < Vec < String >> , # [serde (skip_serializing_if = "Option::is_none")] pub r#all : Option < bool > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Disable : VarlinkCallError { fn reply (& mut self , r#disabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Disable_Reply { r#disabled , r#failed } . into ()) } } impl Call_Disable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Reply { pub r#enabled : i64 , pub r#failed : i64 , } impl varlink :: VarlinkReply for Enable_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Enable_Args { pub r#extensions : Vec < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#osRelease : Option < String > , } # [allow (dead_code)] pub trait Call_Enable : VarlinkCallError { fn reply (& mut self , r#enabled : i64 , r#failed : i64) -> varlink :: Result < () > { self . reply_struct (Enable_Reply { r#enabled , r#failed } . into ()) } } impl Call_Enable for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#extensions : Vec < Extension > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < Extension >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#extensions } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Merge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Merge_Args { } # [allow (dead_code)] pub trait Call_Merge : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Merge_Reply { r#message , r#done } . into ()) } } impl Call_Merge for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Refresh_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Refresh_Args { } # [allow (dead_code)] pub trait Call_Refresh : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Refresh_Reply { r#message , r#done } . into ()) } } impl Call_Refresh for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Reply { pub r#extensions : Vec < ExtensionStatus > , } impl varlink :: VarlinkReply for Status_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Status_Args { } # [allow (dead_code)] pub trait Call_Status : VarlinkCallError { fn reply (& mut self , r#extensions : Vec < ExtensionStatus >) -> varlink :: Result < () > { self . reply_struct (Status_Reply { r#extensions } . into ()) } } impl Call_Status for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Unmerge_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmerge_Args { # [serde (skip_serializing_if = "Option::is_none")] pub r#unmount : Option < bool > , } # [allow (dead_code)] pub trait Call_Unmerge : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Unmerge_Reply { r#message , r#done } . into ()) } } impl Call_Unmerge for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn disable (& self , call : & mut dyn Call_Disable , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn enable (& self , call : & mut dyn Call_Enable , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn merge (& self , call : & mut dyn Call_Merge ,) -> varlink :: Result < () > ; fn refresh (& self , call : & mut dyn Call_Refresh ,) -> varlink :: Result < () > ; fn status (& self , call : & mut dyn Call_Status ,) -> varlink :: Result < () > ; fn unmerge (& self , call : & mut dyn Call_Unmerge , r#unmount : Option < bool >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > ; fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > ; fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > ; fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > ; fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn disable (& mut self , r#extensions : Option < Vec < String >> , r#all : Option < bool > , r#osRelease : Option < String >) -> varlink :: MethodCall < Disable_Args , Disable_Reply , Error > { varlink :: MethodCall :: < Disable_Args , Disable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Disable" , Disable_Args { r#extensions , r#all , r#osRelease }) } fn enable (& mut self , r#extensions : Vec < String > , r#osRelease : Option < String >) -> varlink :: MethodCall < Enable_Args , Enable_Reply , Error > { varlink :: MethodCall :: < Enable_Args , Enable_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Enable" , Enable_Args { r#extensions , r#osRelease }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.List" , List_Args { }) } fn merge (& mut self ,) -> varlink :: MethodCall < Merge_Args , Merge_Reply , Error > { varlink :: MethodCall :: < Merge_Args , Merge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Merge" , Merge_Args { }) } fn refresh (& mut self ,) -> varlink :: MethodCall < Refresh_Args , Refresh_Reply , Error > { varlink :: MethodCall :: < Refresh_Args , Refresh_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Refresh" , Refresh_Args { }) } fn status (& mut self ,) -> varlink :: MethodCall < Status_Args , Status_Reply , Error > { varlink :: MethodCall :: < Status_Args , Status_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Status" , Status_Args { }) } fn unmerge (& mut self , r#unmount : Option < bool >) -> varlink :: MethodCall < Unmerge_Args , Unmerge_Reply , Error > { varlink :: MethodCall :: < Unmerge_Args , Unmerge_Reply , Error > :: new (self . connection . clone () , "org.avocado.Extensions.Unmerge" , Unmerge_Args { r#unmount }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Merge() -> (message: string, done: bool)\n\n# Unmerge extensions\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Unmerge(unmount: ?bool) -> (message: string, done: bool)\n\n# Refresh extensions (unmerge then merge)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Refresh() -> (message: string, done: bool)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Extensions" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Extensions.Disable" => { if let Some (args) = req . parameters . clone () { let args : Disable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . disable (call as & mut dyn Call_Disable , args . r#extensions , args . r#all , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.Enable" => { if let Some (args) = req . parameters . clone () { let args : Enable_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . enable (call as & mut dyn Call_Enable , args . r#extensions , args . r#osRelease) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Extensions.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Extensions.Merge" => self . inner . merge (call as & mut dyn Call_Merge) , "org.avocado.Extensions.Refresh" => self . inner . refresh (call as & mut dyn Call_Refresh) , "org.avocado.Extensions.Status" => self . inner . status (call as & mut dyn Call_Status) , "org.avocado.Extensions.Unmerge" => { if let Some (args) = req . parameters . clone () { let args : Unmerge_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmerge (call as & mut dyn Call_Unmerge , args . r#unmount) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + CommandFailed(Option), + ConfigurationError(Option), + ExtensionNotFound(Option), + MergeFailed(Option), + UnmergeFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::CommandFailed(v) => { + write!(f, "org.avocado.Extensions.CommandFailed: {:#?}", v) + } + ErrorKind::ConfigurationError(v) => { + write!(f, "org.avocado.Extensions.ConfigurationError: {:#?}", v) + } + ErrorKind::ExtensionNotFound(v) => { + write!(f, "org.avocado.Extensions.ExtensionNotFound: {:#?}", v) + } + ErrorKind::MergeFailed(v) => write!(f, "org.avocado.Extensions.MergeFailed: {:#?}", v), + ErrorKind::UnmergeFailed(v) => { + write!(f, "org.avocado.Extensions.UnmergeFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.CommandFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::CommandFailed(v), + Err(_) => ErrorKind::CommandFailed(None), + }, + _ => ErrorKind::CommandFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ConfigurationError" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ConfigurationError(v), + Err(_) => ErrorKind::ConfigurationError(None), + }, + _ => ErrorKind::ConfigurationError(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.ExtensionNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ExtensionNotFound(v), + Err(_) => ErrorKind::ExtensionNotFound(None), + }, + _ => ErrorKind::ExtensionNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Extensions.MergeFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MergeFailed(v), + Err(_) => ErrorKind::MergeFailed(None), + }, + _ => ErrorKind::MergeFailed(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Extensions.UnmergeFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmergeFailed(v), + Err(_) => ErrorKind::UnmergeFailed(None), + }, + _ => ErrorKind::UnmergeFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_command_failed( + &mut self, + r#command: String, + r#message: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.CommandFailed", + Some( + serde_json::to_value(CommandFailed_Args { + r#command, + r#message, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_configuration_error(&mut self, r#message: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ConfigurationError", + Some( + serde_json::to_value(ConfigurationError_Args { r#message }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_extension_not_found(&mut self, r#name: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.ExtensionNotFound", + Some( + serde_json::to_value(ExtensionNotFound_Args { r#name }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_merge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.MergeFailed", + Some( + serde_json::to_value(MergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmerge_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Extensions.UnmergeFailed", + Some( + serde_json::to_value(UnmergeFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Extension { + pub r#name: String, + pub r#version: Option, + pub r#path: String, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isDirectory: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ExtensionStatus { + pub r#name: String, + pub r#version: Option, + pub r#isSysext: bool, + pub r#isConfext: bool, + pub r#isMerged: bool, + pub r#origin: Option, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct CommandFailed_Args { + pub r#command: String, + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ConfigurationError_Args { + pub r#message: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ExtensionNotFound_Args { + pub r#name: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmergeFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Reply { + pub r#disabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Disable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Disable_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#extensions: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#all: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Disable: VarlinkCallError { + fn reply(&mut self, r#disabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Disable_Reply { + r#disabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Disable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Reply { + pub r#enabled: i64, + pub r#failed: i64, +} +impl varlink::VarlinkReply for Enable_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Enable_Args { + pub r#extensions: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#osRelease: Option, +} +#[allow(dead_code)] +pub trait Call_Enable: VarlinkCallError { + fn reply(&mut self, r#enabled: i64, r#failed: i64) -> varlink::Result<()> { + self.reply_struct( + Enable_Reply { + r#enabled, + r#failed, + } + .into(), + ) + } +} +impl Call_Enable for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#extensions }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Merge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Merge_Args {} +#[allow(dead_code)] +pub trait Call_Merge: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Merge_Reply { r#message, r#done }.into()) + } +} +impl Call_Merge for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Refresh_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Refresh_Args {} +#[allow(dead_code)] +pub trait Call_Refresh: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Refresh_Reply { r#message, r#done }.into()) + } +} +impl Call_Refresh for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Reply { + pub r#extensions: Vec, +} +impl varlink::VarlinkReply for Status_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Status_Args {} +#[allow(dead_code)] +pub trait Call_Status: VarlinkCallError { + fn reply(&mut self, r#extensions: Vec) -> varlink::Result<()> { + self.reply_struct(Status_Reply { r#extensions }.into()) + } +} +impl Call_Status for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Unmerge_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmerge_Args { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#unmount: Option, +} +#[allow(dead_code)] +pub trait Call_Unmerge: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Unmerge_Reply { r#message, r#done }.into()) + } +} +impl Call_Unmerge for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn disable( + &self, + call: &mut dyn Call_Disable, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn enable( + &self, + call: &mut dyn Call_Enable, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn merge(&self, call: &mut dyn Call_Merge) -> varlink::Result<()>; + fn refresh(&self, call: &mut dyn Call_Refresh) -> varlink::Result<()>; + fn status(&self, call: &mut dyn Call_Status) -> varlink::Result<()>; + fn unmerge(&self, call: &mut dyn Call_Unmerge, r#unmount: Option) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn merge(&mut self) -> varlink::MethodCall; + fn refresh(&mut self) -> varlink::MethodCall; + fn status(&mut self) -> varlink::MethodCall; + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn disable( + &mut self, + r#extensions: Option>, + r#all: Option, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Disable", + Disable_Args { + r#extensions, + r#all, + r#osRelease, + }, + ) + } + fn enable( + &mut self, + r#extensions: Vec, + r#osRelease: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Enable", + Enable_Args { + r#extensions, + r#osRelease, + }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.List", + List_Args {}, + ) + } + fn merge(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Merge", + Merge_Args {}, + ) + } + fn refresh(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Refresh", + Refresh_Args {}, + ) + } + fn status(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Status", + Status_Args {}, + ) + } + fn unmerge( + &mut self, + r#unmount: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Extensions.Unmerge", + Unmerge_Args { r#unmount }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Extension management for Avocado Linux system extensions\ninterface org.avocado.Extensions\n\ntype Extension (\n name: string,\n version: ?string,\n path: string,\n isSysext: bool,\n isConfext: bool,\n isDirectory: bool\n)\n\ntype ExtensionStatus (\n name: string,\n version: ?string,\n isSysext: bool,\n isConfext: bool,\n isMerged: bool,\n origin: ?string,\n imageId: ?string\n)\n\n# List all available extensions in the extensions directory\nmethod List() -> (extensions: []Extension)\n\n# Merge extensions using systemd-sysext and systemd-confext\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Merge() -> (message: string, done: bool)\n\n# Unmerge extensions\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Unmerge(unmount: ?bool) -> (message: string, done: bool)\n\n# Refresh extensions (unmerge then merge)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Refresh() -> (message: string, done: bool)\n\n# Enable extensions for a specific OS release version\nmethod Enable(extensions: []string, osRelease: ?string) -> (enabled: int, failed: int)\n\n# Disable extensions for a specific OS release version\nmethod Disable(extensions: ?[]string, all: ?bool, osRelease: ?string) -> (disabled: int, failed: int)\n\n# Show status of merged extensions\nmethod Status() -> (extensions: []ExtensionStatus)\n\nerror ExtensionNotFound (name: string)\nerror MergeFailed (reason: string)\nerror UnmergeFailed (reason: string)\nerror ConfigurationError (message: string)\nerror CommandFailed (command: string, message: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Extensions" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Extensions.Disable" => { + if let Some(args) = req.parameters.clone() { + let args: Disable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.disable( + call as &mut dyn Call_Disable, + args.r#extensions, + args.r#all, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.Enable" => { + if let Some(args) = req.parameters.clone() { + let args: Enable_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.enable( + call as &mut dyn Call_Enable, + args.r#extensions, + args.r#osRelease, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Extensions.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Extensions.Merge" => self.inner.merge(call as &mut dyn Call_Merge), + "org.avocado.Extensions.Refresh" => self.inner.refresh(call as &mut dyn Call_Refresh), + "org.avocado.Extensions.Status" => self.inner.status(call as &mut dyn Call_Status), + "org.avocado.Extensions.Unmerge" => { + if let Some(args) = req.parameters.clone() { + let args: Unmerge_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmerge(call as &mut dyn Call_Unmerge, args.r#unmount) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Hitl.rs b/src/varlink/org_avocado_Hitl.rs index 7720a1d..59a04ea 100644 --- a/src/varlink/org_avocado_Hitl.rs +++ b/src/varlink/org_avocado_Hitl.rs @@ -1 +1,346 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , MountFailed (Option < MountFailed_Args >) , UnmountFailed (Option < UnmountFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: MountFailed (v) => write ! (f , "org.avocado.Hitl.MountFailed: {:#?}" , v) , ErrorKind :: UnmountFailed (v) => write ! (f , "org.avocado.Hitl.UnmountFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.MountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: MountFailed (v) , Err (_) => ErrorKind :: MountFailed (None) , } , _ => ErrorKind :: MountFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Hitl.UnmountFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UnmountFailed (v) , Err (_) => ErrorKind :: UnmountFailed (None) , } , _ => ErrorKind :: UnmountFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_mount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.MountFailed" , Some (serde_json :: to_value (MountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_unmount_failed (& mut self , r#extension : String , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Hitl.UnmountFailed" , Some (serde_json :: to_value (UnmountFailed_Args { r#extension , r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct MountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UnmountFailed_Args { pub r#extension : String , pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Reply { } impl varlink :: VarlinkReply for Mount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Mount_Args { pub r#serverIp : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#serverPort : Option < String > , pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Mount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Mount for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Reply { } impl varlink :: VarlinkReply for Unmount_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Unmount_Args { pub r#extensions : Vec < String > , } # [allow (dead_code)] pub trait Call_Unmount : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Unmount for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn mount (& self , call : & mut dyn Call_Mount , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn unmount (& self , call : & mut dyn Call_Unmount , r#extensions : Vec < String >) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > ; fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn mount (& mut self , r#serverIp : String , r#serverPort : Option < String > , r#extensions : Vec < String >) -> varlink :: MethodCall < Mount_Args , Mount_Reply , Error > { varlink :: MethodCall :: < Mount_Args , Mount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Mount" , Mount_Args { r#serverIp , r#serverPort , r#extensions }) } fn unmount (& mut self , r#extensions : Vec < String >) -> varlink :: MethodCall < Unmount_Args , Unmount_Reply , Error > { varlink :: MethodCall :: < Unmount_Args , Unmount_Reply , Error > :: new (self . connection . clone () , "org.avocado.Hitl.Unmount" , Unmount_Args { r#extensions }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Hitl" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Hitl.Mount" => { if let Some (args) = req . parameters . clone () { let args : Mount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . mount (call as & mut dyn Call_Mount , args . r#serverIp , args . r#serverPort , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Hitl.Unmount" => { if let Some (args) = req . parameters . clone () { let args : Unmount_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . unmount (call as & mut dyn Call_Unmount , args . r#extensions) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + MountFailed(Option), + UnmountFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::MountFailed(v) => write!(f, "org.avocado.Hitl.MountFailed: {:#?}", v), + ErrorKind::UnmountFailed(v) => write!(f, "org.avocado.Hitl.UnmountFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.MountFailed" => match e + { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::MountFailed(v), + Err(_) => ErrorKind::MountFailed(None), + }, + _ => ErrorKind::MountFailed(None), + }, + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Hitl.UnmountFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UnmountFailed(v), + Err(_) => ErrorKind::UnmountFailed(None), + }, + _ => ErrorKind::UnmountFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_mount_failed(&mut self, r#extension: String, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.MountFailed", + Some( + serde_json::to_value(MountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_unmount_failed( + &mut self, + r#extension: String, + r#reason: String, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Hitl.UnmountFailed", + Some( + serde_json::to_value(UnmountFailed_Args { + r#extension, + r#reason, + }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct MountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UnmountFailed_Args { + pub r#extension: String, + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Reply {} +impl varlink::VarlinkReply for Mount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Mount_Args { + pub r#serverIp: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#serverPort: Option, + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Mount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Mount for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Reply {} +impl varlink::VarlinkReply for Unmount_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Unmount_Args { + pub r#extensions: Vec, +} +#[allow(dead_code)] +pub trait Call_Unmount: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Unmount for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn mount( + &self, + call: &mut dyn Call_Mount, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn unmount( + &self, + call: &mut dyn Call_Unmount, + r#extensions: Vec, + ) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall; + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn mount( + &mut self, + r#serverIp: String, + r#serverPort: Option, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Mount", + Mount_Args { + r#serverIp, + r#serverPort, + r#extensions, + }, + ) + } + fn unmount( + &mut self, + r#extensions: Vec, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Hitl.Unmount", + Unmount_Args { r#extensions }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Hardware-in-the-loop testing support\ninterface org.avocado.Hitl\n\n# Mount NFS extensions from a remote server\nmethod Mount(serverIp: string, serverPort: ?string, extensions: []string) -> ()\n\n# Unmount NFS extensions\nmethod Unmount(extensions: []string) -> ()\n\nerror MountFailed (extension: string, reason: string)\nerror UnmountFailed (extension: string, reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Hitl" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Hitl.Mount" => { + if let Some(args) = req.parameters.clone() { + let args: Mount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.mount( + call as &mut dyn Call_Mount, + args.r#serverIp, + args.r#serverPort, + args.r#extensions, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Hitl.Unmount" => { + if let Some(args) = req.parameters.clone() { + let args: Unmount_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .unmount(call as &mut dyn Call_Unmount, args.r#extensions) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_RootAuthority.rs b/src/varlink/org_avocado_RootAuthority.rs index 029ad69..c8d4a18 100644 --- a/src/varlink/org_avocado_RootAuthority.rs +++ b/src/varlink/org_avocado_RootAuthority.rs @@ -1 +1,260 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , NoRootAuthority (Option < NoRootAuthority_Args >) , ParseFailed (Option < ParseFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: NoRootAuthority (v) => write ! (f , "org.avocado.RootAuthority.NoRootAuthority: {:#?}" , v) , ErrorKind :: ParseFailed (v) => write ! (f , "org.avocado.RootAuthority.ParseFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.NoRootAuthority" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: NoRootAuthority (v) , Err (_) => ErrorKind :: NoRootAuthority (None) , } , _ => ErrorKind :: NoRootAuthority (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.RootAuthority.ParseFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: ParseFailed (v) , Err (_) => ErrorKind :: ParseFailed (None) , } , _ => ErrorKind :: ParseFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_no_root_authority (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.NoRootAuthority" , None)) } fn reply_parse_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.RootAuthority.ParseFailed" , Some (serde_json :: to_value (ParseFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RootAuthorityInfo { pub r#version : i64 , pub r#expires : String , pub r#keys : Vec < TrustedKey > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#TrustedKey { pub r#keyId : String , pub r#keyType : String , pub r#roles : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct NoRootAuthority_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct ParseFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Reply { # [serde (skip_serializing_if = "Option::is_none")] pub r#authority : Option < RootAuthorityInfo > , } impl varlink :: VarlinkReply for Show_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Show_Args { } # [allow (dead_code)] pub trait Call_Show : VarlinkCallError { fn reply (& mut self , r#authority : Option < RootAuthorityInfo >) -> varlink :: Result < () > { self . reply_struct (Show_Reply { r#authority } . into ()) } } impl Call_Show for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn show (& self , call : & mut dyn Call_Show ,) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn show (& mut self ,) -> varlink :: MethodCall < Show_Args , Show_Reply , Error > { varlink :: MethodCall :: < Show_Args , Show_Reply , Error > :: new (self . connection . clone () , "org.avocado.RootAuthority.Show" , Show_Args { }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.RootAuthority" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.RootAuthority.Show" => self . inner . show (call as & mut dyn Call_Show) , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + NoRootAuthority(Option), + ParseFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::NoRootAuthority(v) => { + write!(f, "org.avocado.RootAuthority.NoRootAuthority: {:#?}", v) + } + ErrorKind::ParseFailed(v) => { + write!(f, "org.avocado.RootAuthority.ParseFailed: {:#?}", v) + } + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.NoRootAuthority" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::NoRootAuthority(v), + Err(_) => ErrorKind::NoRootAuthority(None), + }, + _ => ErrorKind::NoRootAuthority(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.RootAuthority.ParseFailed" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::ParseFailed(v), + Err(_) => ErrorKind::ParseFailed(None), + }, + _ => ErrorKind::ParseFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_no_root_authority(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.NoRootAuthority", + None, + )) + } + fn reply_parse_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.RootAuthority.ParseFailed", + Some( + serde_json::to_value(ParseFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RootAuthorityInfo { + pub r#version: i64, + pub r#expires: String, + pub r#keys: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#TrustedKey { + pub r#keyId: String, + pub r#keyType: String, + pub r#roles: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct NoRootAuthority_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct ParseFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Reply { + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authority: Option, +} +impl varlink::VarlinkReply for Show_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Show_Args {} +#[allow(dead_code)] +pub trait Call_Show: VarlinkCallError { + fn reply(&mut self, r#authority: Option) -> varlink::Result<()> { + self.reply_struct(Show_Reply { r#authority }.into()) + } +} +impl Call_Show for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn show(&self, call: &mut dyn Call_Show) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn show(&mut self) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn show(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.RootAuthority.Show", + Show_Args {}, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Trust anchor / root authority information\ninterface org.avocado.RootAuthority\n\ntype TrustedKey (\n keyId: string,\n keyType: string,\n roles: []string\n)\n\ntype RootAuthorityInfo (\n version: int,\n expires: string,\n keys: []TrustedKey\n)\n\n# Show the trusted signing keys for this device\nmethod Show() -> (authority: ?RootAuthorityInfo)\n\nerror NoRootAuthority ()\nerror ParseFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.RootAuthority" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.RootAuthority.Show" => self.inner.show(call as &mut dyn Call_Show), + m => call.reply_method_not_found(String::from(m)), + } + } +} diff --git a/src/varlink/org_avocado_Runtimes.rs b/src/varlink/org_avocado_Runtimes.rs index aeeb3e7..f97296d 100644 --- a/src/varlink/org_avocado_Runtimes.rs +++ b/src/varlink/org_avocado_Runtimes.rs @@ -1 +1,609 @@ -# ! [doc = "This file was automatically generated by the varlink rust generator"] # ! [allow (non_camel_case_types)] # ! [allow (non_snake_case)] use serde_derive :: { Deserialize , Serialize } ; use std :: io :: BufRead ; use std :: sync :: { Arc , RwLock } ; use varlink :: { self , CallTrait } ; # [allow (dead_code)] # [derive (Clone , PartialEq , Debug)] # [allow (clippy :: enum_variant_names)] pub enum ErrorKind { Varlink_Error , VarlinkReply_Error , AmbiguousRuntimeId (Option < AmbiguousRuntimeId_Args >) , RemoveActiveRuntime (Option < RemoveActiveRuntime_Args >) , RuntimeNotFound (Option < RuntimeNotFound_Args >) , StagingFailed (Option < StagingFailed_Args >) , UpdateFailed (Option < UpdateFailed_Args >) } impl :: std :: fmt :: Display for ErrorKind { fn fmt (& self , f : & mut :: std :: fmt :: Formatter) -> :: std :: fmt :: Result { match self { ErrorKind :: Varlink_Error => write ! (f , "Varlink Error") , ErrorKind :: VarlinkReply_Error => write ! (f , "Varlink error reply") , ErrorKind :: AmbiguousRuntimeId (v) => write ! (f , "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}" , v) , ErrorKind :: RemoveActiveRuntime (v) => write ! (f , "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}" , v) , ErrorKind :: RuntimeNotFound (v) => write ! (f , "org.avocado.Runtimes.RuntimeNotFound: {:#?}" , v) , ErrorKind :: StagingFailed (v) => write ! (f , "org.avocado.Runtimes.StagingFailed: {:#?}" , v) , ErrorKind :: UpdateFailed (v) => write ! (f , "org.avocado.Runtimes.UpdateFailed: {:#?}" , v) } } } pub struct Error (pub ErrorKind , pub Option < Box < dyn std :: error :: Error + 'static + Send + Sync >> , pub Option < & 'static str > ,) ; impl Error { # [allow (dead_code)] pub fn kind (& self) -> & ErrorKind { & self . 0 } } impl From < ErrorKind > for Error { fn from (e : ErrorKind) -> Self { Error (e , None , None) } } impl std :: error :: Error for Error { fn source (& self) -> Option < & (dyn std :: error :: Error + 'static) > { self . 1 . as_ref () . map (| e | e . as_ref () as & (dyn std :: error :: Error + 'static)) } } impl std :: fmt :: Display for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { std :: fmt :: Display :: fmt (& self . 0 , f) } } impl std :: fmt :: Debug for Error { fn fmt (& self , f : & mut std :: fmt :: Formatter) -> std :: fmt :: Result { use std :: error :: Error as StdError ; if let Some (ref o) = self . 2 { std :: fmt :: Display :: fmt (o , f) ? ; } std :: fmt :: Debug :: fmt (& self . 0 , f) ? ; if let Some (e) = self . source () { std :: fmt :: Display :: fmt ("\nCaused by:\n" , f) ? ; std :: fmt :: Debug :: fmt (& e , f) ? ; } Ok (()) } } # [allow (dead_code)] pub type Result < T > = std :: result :: Result < T , Error > ; impl From < varlink :: Error > for Error { fn from (e : varlink :: Error ,) -> Self { match e . kind () { varlink :: ErrorKind :: VarlinkErrorReply (r) => Error (ErrorKind :: from (r) , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) , _ => Error (ErrorKind :: Varlink_Error , Some (Box :: from (e)) , Some (concat ! (file ! () , ":" , line ! () , ": "))) } } } # [allow (dead_code)] impl Error { pub fn source_varlink_kind (& self) -> Option < & varlink :: ErrorKind > { use std :: error :: Error as StdError ; let mut s : & dyn StdError = self ; while let Some (c) = s . source () { let k = self . source () . and_then (| e | e . downcast_ref :: < varlink :: Error > ()) . map (| e | e . kind ()) ; if k . is_some () { return k ; } s = c ; } None } } impl From < & varlink :: Reply > for ErrorKind { # [allow (unused_variables)] fn from (e : & varlink :: Reply) -> Self { match e { varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: AmbiguousRuntimeId (v) , Err (_) => ErrorKind :: AmbiguousRuntimeId (None) , } , _ => ErrorKind :: AmbiguousRuntimeId (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RemoveActiveRuntime" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RemoveActiveRuntime (v) , Err (_) => ErrorKind :: RemoveActiveRuntime (None) , } , _ => ErrorKind :: RemoveActiveRuntime (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.RuntimeNotFound" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: RuntimeNotFound (v) , Err (_) => ErrorKind :: RuntimeNotFound (None) , } , _ => ErrorKind :: RuntimeNotFound (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.StagingFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: StagingFailed (v) , Err (_) => ErrorKind :: StagingFailed (None) , } , _ => ErrorKind :: StagingFailed (None) , } } varlink :: Reply { error : Some (t) , .. } if t == "org.avocado.Runtimes.UpdateFailed" => { match e { varlink :: Reply { parameters : Some (p) , .. } => match serde_json :: from_value (p . clone ()) { Ok (v) => ErrorKind :: UpdateFailed (v) , Err (_) => ErrorKind :: UpdateFailed (None) , } , _ => ErrorKind :: UpdateFailed (None) , } } _ => ErrorKind :: VarlinkReply_Error , } } } # [allow (dead_code)] pub trait VarlinkCallError : varlink :: CallTrait { fn reply_ambiguous_runtime_id (& mut self , r#id : String , r#candidates : Vec < String >) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.AmbiguousRuntimeId" , Some (serde_json :: to_value (AmbiguousRuntimeId_Args { r#id , r#candidates }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_remove_active_runtime (& mut self ,) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RemoveActiveRuntime" , None)) } fn reply_runtime_not_found (& mut self , r#id : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.RuntimeNotFound" , Some (serde_json :: to_value (RuntimeNotFound_Args { r#id }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_staging_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.StagingFailed" , Some (serde_json :: to_value (StagingFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } fn reply_update_failed (& mut self , r#reason : String) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: error ("org.avocado.Runtimes.UpdateFailed" , Some (serde_json :: to_value (UpdateFailed_Args { r#reason }) . map_err (varlink :: map_context ! ()) ?))) } } impl VarlinkCallError for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#ManifestExtension { pub r#name : String , pub r#version : String , pub r#imageId : Option < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#Runtime { pub r#id : String , pub r#manifestVersion : i64 , pub r#builtAt : String , pub r#runtime : RuntimeInfo , pub r#extensions : Vec < ManifestExtension > , pub r#active : bool , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct r#RuntimeInfo { pub r#name : String , pub r#version : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AmbiguousRuntimeId_Args { pub r#id : String , pub r#candidates : Vec < String > , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RemoveActiveRuntime_Args { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct RuntimeNotFound_Args { pub r#id : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct StagingFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct UpdateFailed_Args { pub r#reason : String , } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for Activate_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Activate_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Activate : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (Activate_Reply { r#message , r#done } . into ()) } } impl Call_Activate for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for AddFromManifest_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromManifest_Args { pub r#manifestPath : String , } # [allow (dead_code)] pub trait Call_AddFromManifest : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (AddFromManifest_Reply { r#message , r#done } . into ()) } } impl Call_AddFromManifest for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Reply { pub r#message : String , pub r#done : bool , } impl varlink :: VarlinkReply for AddFromUrl_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct AddFromUrl_Args { pub r#url : String , # [serde (skip_serializing_if = "Option::is_none")] pub r#authToken : Option < String > , # [serde (skip_serializing_if = "Option::is_none")] pub r#artifactsUrl : Option < String > , } # [allow (dead_code)] pub trait Call_AddFromUrl : VarlinkCallError { fn reply (& mut self , r#message : String , r#done : bool) -> varlink :: Result < () > { self . reply_struct (AddFromUrl_Reply { r#message , r#done } . into ()) } } impl Call_AddFromUrl for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Reply { pub r#runtime : Runtime , } impl varlink :: VarlinkReply for Inspect_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Inspect_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Inspect : VarlinkCallError { fn reply (& mut self , r#runtime : Runtime) -> varlink :: Result < () > { self . reply_struct (Inspect_Reply { r#runtime } . into ()) } } impl Call_Inspect for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Reply { pub r#runtimes : Vec < Runtime > , } impl varlink :: VarlinkReply for List_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct List_Args { } # [allow (dead_code)] pub trait Call_List : VarlinkCallError { fn reply (& mut self , r#runtimes : Vec < Runtime >) -> varlink :: Result < () > { self . reply_struct (List_Reply { r#runtimes } . into ()) } } impl Call_List for varlink :: Call < '_ > { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Reply { } impl varlink :: VarlinkReply for Remove_Reply { } # [derive (Serialize , Deserialize , Debug , PartialEq , Clone)] pub struct Remove_Args { pub r#id : String , } # [allow (dead_code)] pub trait Call_Remove : VarlinkCallError { fn reply (& mut self) -> varlink :: Result < () > { self . reply_struct (varlink :: Reply :: parameters (None)) } } impl Call_Remove for varlink :: Call < '_ > { } # [allow (dead_code)] pub trait VarlinkInterface { fn activate (& self , call : & mut dyn Call_Activate , r#id : String) -> varlink :: Result < () > ; fn add_from_manifest (& self , call : & mut dyn Call_AddFromManifest , r#manifestPath : String) -> varlink :: Result < () > ; fn add_from_url (& self , call : & mut dyn Call_AddFromUrl , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: Result < () > ; fn inspect (& self , call : & mut dyn Call_Inspect , r#id : String) -> varlink :: Result < () > ; fn list (& self , call : & mut dyn Call_List ,) -> varlink :: Result < () > ; fn remove (& self , call : & mut dyn Call_Remove , r#id : String) -> varlink :: Result < () > ; fn call_upgraded (& self , _call : & mut varlink :: Call , _bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { Ok (Vec :: new ()) } } # [allow (dead_code)] pub trait VarlinkClientInterface { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > ; fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > ; fn add_from_url (& mut self , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > ; fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > ; fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > ; fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > ; } # [allow (dead_code)] pub struct VarlinkClient { connection : Arc < RwLock < varlink :: Connection >> , } impl VarlinkClient { # [allow (dead_code)] pub fn new (connection : Arc < RwLock < varlink :: Connection >>) -> Self { VarlinkClient { connection , } } } impl VarlinkClientInterface for VarlinkClient { fn activate (& mut self , r#id : String) -> varlink :: MethodCall < Activate_Args , Activate_Reply , Error > { varlink :: MethodCall :: < Activate_Args , Activate_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Activate" , Activate_Args { r#id }) } fn add_from_manifest (& mut self , r#manifestPath : String) -> varlink :: MethodCall < AddFromManifest_Args , AddFromManifest_Reply , Error > { varlink :: MethodCall :: < AddFromManifest_Args , AddFromManifest_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromManifest" , AddFromManifest_Args { r#manifestPath }) } fn add_from_url (& mut self , r#url : String , r#authToken : Option < String > , r#artifactsUrl : Option < String >) -> varlink :: MethodCall < AddFromUrl_Args , AddFromUrl_Reply , Error > { varlink :: MethodCall :: < AddFromUrl_Args , AddFromUrl_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.AddFromUrl" , AddFromUrl_Args { r#url , r#authToken , r#artifactsUrl }) } fn inspect (& mut self , r#id : String) -> varlink :: MethodCall < Inspect_Args , Inspect_Reply , Error > { varlink :: MethodCall :: < Inspect_Args , Inspect_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Inspect" , Inspect_Args { r#id }) } fn list (& mut self ,) -> varlink :: MethodCall < List_Args , List_Reply , Error > { varlink :: MethodCall :: < List_Args , List_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.List" , List_Args { }) } fn remove (& mut self , r#id : String) -> varlink :: MethodCall < Remove_Args , Remove_Reply , Error > { varlink :: MethodCall :: < Remove_Args , Remove_Reply , Error > :: new (self . connection . clone () , "org.avocado.Runtimes.Remove" , Remove_Args { r#id }) } } # [allow (dead_code)] pub struct VarlinkInterfaceProxy { inner : Box < dyn VarlinkInterface + Send + Sync > , } # [allow (dead_code)] pub fn new (inner : Box < dyn VarlinkInterface + Send + Sync >) -> VarlinkInterfaceProxy { VarlinkInterfaceProxy { inner } } impl varlink :: Interface for VarlinkInterfaceProxy { fn get_description (& self) -> & 'static str { "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromUrl(url: string, authToken: ?string, artifactsUrl: ?string) -> (message: string, done: bool)\n\n# Add a runtime from a local manifest file\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromManifest(manifestPath: string) -> (message: string, done: bool)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Activate(id: string) -> (message: string, done: bool)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" } fn get_name (& self) -> & 'static str { "org.avocado.Runtimes" } fn call_upgraded (& self , call : & mut varlink :: Call , bufreader : & mut dyn BufRead) -> varlink :: Result < Vec < u8 >> { self . inner . call_upgraded (call , bufreader) } fn call (& self , call : & mut varlink :: Call) -> varlink :: Result < () > { let req = call . request . unwrap () ; match req . method . as_ref () { "org.avocado.Runtimes.Activate" => { if let Some (args) = req . parameters . clone () { let args : Activate_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . activate (call as & mut dyn Call_Activate , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromManifest" => { if let Some (args) = req . parameters . clone () { let args : AddFromManifest_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_manifest (call as & mut dyn Call_AddFromManifest , args . r#manifestPath) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.AddFromUrl" => { if let Some (args) = req . parameters . clone () { let args : AddFromUrl_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . add_from_url (call as & mut dyn Call_AddFromUrl , args . r#url , args . r#authToken , args . r#artifactsUrl) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.Inspect" => { if let Some (args) = req . parameters . clone () { let args : Inspect_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . inspect (call as & mut dyn Call_Inspect , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , "org.avocado.Runtimes.List" => self . inner . list (call as & mut dyn Call_List) , "org.avocado.Runtimes.Remove" => { if let Some (args) = req . parameters . clone () { let args : Remove_Args = match serde_json :: from_value (args) { Ok (v) => v , Err (e) => { let es = format ! ("{}" , e) ; let _ = call . reply_invalid_parameter (es . clone ()) ; return Err (varlink :: context ! (varlink :: ErrorKind :: SerdeJsonDe (es))) ; } } ; self . inner . remove (call as & mut dyn Call_Remove , args . r#id) } else { call . reply_invalid_parameter ("parameters" . into ()) } } , m => { call . reply_method_not_found (String :: from (m)) } } } } \ No newline at end of file +#![doc = "This file was automatically generated by the varlink rust generator"] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +use serde_derive::{Deserialize, Serialize}; +use std::io::BufRead; +use std::sync::{Arc, RwLock}; +use varlink::{self, CallTrait}; +#[allow(dead_code)] +#[derive(Clone, PartialEq, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum ErrorKind { + Varlink_Error, + VarlinkReply_Error, + AmbiguousRuntimeId(Option), + RemoveActiveRuntime(Option), + RuntimeNotFound(Option), + StagingFailed(Option), + UpdateFailed(Option), +} +impl ::std::fmt::Display for ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + ErrorKind::Varlink_Error => write!(f, "Varlink Error"), + ErrorKind::VarlinkReply_Error => write!(f, "Varlink error reply"), + ErrorKind::AmbiguousRuntimeId(v) => { + write!(f, "org.avocado.Runtimes.AmbiguousRuntimeId: {:#?}", v) + } + ErrorKind::RemoveActiveRuntime(v) => { + write!(f, "org.avocado.Runtimes.RemoveActiveRuntime: {:#?}", v) + } + ErrorKind::RuntimeNotFound(v) => { + write!(f, "org.avocado.Runtimes.RuntimeNotFound: {:#?}", v) + } + ErrorKind::StagingFailed(v) => { + write!(f, "org.avocado.Runtimes.StagingFailed: {:#?}", v) + } + ErrorKind::UpdateFailed(v) => write!(f, "org.avocado.Runtimes.UpdateFailed: {:#?}", v), + } + } +} +pub struct Error( + pub ErrorKind, + pub Option>, + pub Option<&'static str>, +); +impl Error { + #[allow(dead_code)] + pub fn kind(&self) -> &ErrorKind { + &self.0 + } +} +impl From for Error { + fn from(e: ErrorKind) -> Self { + Error(e, None, None) + } +} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.1 + .as_ref() + .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) + } +} +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(&self.0, f) + } +} +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use std::error::Error as StdError; + if let Some(ref o) = self.2 { + std::fmt::Display::fmt(o, f)?; + } + std::fmt::Debug::fmt(&self.0, f)?; + if let Some(e) = self.source() { + std::fmt::Display::fmt("\nCaused by:\n", f)?; + std::fmt::Debug::fmt(&e, f)?; + } + Ok(()) + } +} +#[allow(dead_code)] +pub type Result = std::result::Result; +impl From for Error { + fn from(e: varlink::Error) -> Self { + match e.kind() { + varlink::ErrorKind::VarlinkErrorReply(r) => Error( + ErrorKind::from(r), + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + _ => Error( + ErrorKind::Varlink_Error, + Some(Box::from(e)), + Some(concat!(file!(), ":", line!(), ": ")), + ), + } + } +} +#[allow(dead_code)] +impl Error { + pub fn source_varlink_kind(&self) -> Option<&varlink::ErrorKind> { + use std::error::Error as StdError; + let mut s: &dyn StdError = self; + while let Some(c) = s.source() { + let k = self + .source() + .and_then(|e| e.downcast_ref::()) + .map(|e| e.kind()); + if k.is_some() { + return k; + } + s = c; + } + None + } +} +impl From<&varlink::Reply> for ErrorKind { + #[allow(unused_variables)] + fn from(e: &varlink::Reply) -> Self { + match e { + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.AmbiguousRuntimeId" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::AmbiguousRuntimeId(v), + Err(_) => ErrorKind::AmbiguousRuntimeId(None), + }, + _ => ErrorKind::AmbiguousRuntimeId(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RemoveActiveRuntime" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RemoveActiveRuntime(v), + Err(_) => ErrorKind::RemoveActiveRuntime(None), + }, + _ => ErrorKind::RemoveActiveRuntime(None), + } + } + varlink::Reply { error: Some(t), .. } + if t == "org.avocado.Runtimes.RuntimeNotFound" => + { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::RuntimeNotFound(v), + Err(_) => ErrorKind::RuntimeNotFound(None), + }, + _ => ErrorKind::RuntimeNotFound(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.StagingFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::StagingFailed(v), + Err(_) => ErrorKind::StagingFailed(None), + }, + _ => ErrorKind::StagingFailed(None), + } + } + varlink::Reply { error: Some(t), .. } if t == "org.avocado.Runtimes.UpdateFailed" => { + match e { + varlink::Reply { + parameters: Some(p), + .. + } => match serde_json::from_value(p.clone()) { + Ok(v) => ErrorKind::UpdateFailed(v), + Err(_) => ErrorKind::UpdateFailed(None), + }, + _ => ErrorKind::UpdateFailed(None), + } + } + _ => ErrorKind::VarlinkReply_Error, + } + } +} +#[allow(dead_code)] +pub trait VarlinkCallError: varlink::CallTrait { + fn reply_ambiguous_runtime_id( + &mut self, + r#id: String, + r#candidates: Vec, + ) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.AmbiguousRuntimeId", + Some( + serde_json::to_value(AmbiguousRuntimeId_Args { r#id, r#candidates }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_remove_active_runtime(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RemoveActiveRuntime", + None, + )) + } + fn reply_runtime_not_found(&mut self, r#id: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.RuntimeNotFound", + Some( + serde_json::to_value(RuntimeNotFound_Args { r#id }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_staging_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.StagingFailed", + Some( + serde_json::to_value(StagingFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } + fn reply_update_failed(&mut self, r#reason: String) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::error( + "org.avocado.Runtimes.UpdateFailed", + Some( + serde_json::to_value(UpdateFailed_Args { r#reason }) + .map_err(varlink::map_context!())?, + ), + )) + } +} +impl VarlinkCallError for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#ManifestExtension { + pub r#name: String, + pub r#version: String, + pub r#imageId: Option, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#Runtime { + pub r#id: String, + pub r#manifestVersion: i64, + pub r#builtAt: String, + pub r#runtime: RuntimeInfo, + pub r#extensions: Vec, + pub r#active: bool, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct r#RuntimeInfo { + pub r#name: String, + pub r#version: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AmbiguousRuntimeId_Args { + pub r#id: String, + pub r#candidates: Vec, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RemoveActiveRuntime_Args {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct RuntimeNotFound_Args { + pub r#id: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct StagingFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct UpdateFailed_Args { + pub r#reason: String, +} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for Activate_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Activate_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Activate: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(Activate_Reply { r#message, r#done }.into()) + } +} +impl Call_Activate for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for AddFromManifest_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromManifest_Args { + pub r#manifestPath: String, +} +#[allow(dead_code)] +pub trait Call_AddFromManifest: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(AddFromManifest_Reply { r#message, r#done }.into()) + } +} +impl Call_AddFromManifest for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Reply { + pub r#message: String, + pub r#done: bool, +} +impl varlink::VarlinkReply for AddFromUrl_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct AddFromUrl_Args { + pub r#url: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#authToken: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#artifactsUrl: Option, +} +#[allow(dead_code)] +pub trait Call_AddFromUrl: VarlinkCallError { + fn reply(&mut self, r#message: String, r#done: bool) -> varlink::Result<()> { + self.reply_struct(AddFromUrl_Reply { r#message, r#done }.into()) + } +} +impl Call_AddFromUrl for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Reply { + pub r#runtime: Runtime, +} +impl varlink::VarlinkReply for Inspect_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Inspect_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Inspect: VarlinkCallError { + fn reply(&mut self, r#runtime: Runtime) -> varlink::Result<()> { + self.reply_struct(Inspect_Reply { r#runtime }.into()) + } +} +impl Call_Inspect for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Reply { + pub r#runtimes: Vec, +} +impl varlink::VarlinkReply for List_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct List_Args {} +#[allow(dead_code)] +pub trait Call_List: VarlinkCallError { + fn reply(&mut self, r#runtimes: Vec) -> varlink::Result<()> { + self.reply_struct(List_Reply { r#runtimes }.into()) + } +} +impl Call_List for varlink::Call<'_> {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Reply {} +impl varlink::VarlinkReply for Remove_Reply {} +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +pub struct Remove_Args { + pub r#id: String, +} +#[allow(dead_code)] +pub trait Call_Remove: VarlinkCallError { + fn reply(&mut self) -> varlink::Result<()> { + self.reply_struct(varlink::Reply::parameters(None)) + } +} +impl Call_Remove for varlink::Call<'_> {} +#[allow(dead_code)] +pub trait VarlinkInterface { + fn activate(&self, call: &mut dyn Call_Activate, r#id: String) -> varlink::Result<()>; + fn add_from_manifest( + &self, + call: &mut dyn Call_AddFromManifest, + r#manifestPath: String, + ) -> varlink::Result<()>; + fn add_from_url( + &self, + call: &mut dyn Call_AddFromUrl, + r#url: String, + r#authToken: Option, + r#artifactsUrl: Option, + ) -> varlink::Result<()>; + fn inspect(&self, call: &mut dyn Call_Inspect, r#id: String) -> varlink::Result<()>; + fn list(&self, call: &mut dyn Call_List) -> varlink::Result<()>; + fn remove(&self, call: &mut dyn Call_Remove, r#id: String) -> varlink::Result<()>; + fn call_upgraded( + &self, + _call: &mut varlink::Call, + _bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + Ok(Vec::new()) + } +} +#[allow(dead_code)] +pub trait VarlinkClientInterface { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall; + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall; + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + r#artifactsUrl: Option, + ) -> varlink::MethodCall; + fn inspect(&mut self, r#id: String) -> varlink::MethodCall; + fn list(&mut self) -> varlink::MethodCall; + fn remove(&mut self, r#id: String) -> varlink::MethodCall; +} +#[allow(dead_code)] +pub struct VarlinkClient { + connection: Arc>, +} +impl VarlinkClient { + #[allow(dead_code)] + pub fn new(connection: Arc>) -> Self { + VarlinkClient { connection } + } +} +impl VarlinkClientInterface for VarlinkClient { + fn activate( + &mut self, + r#id: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Activate", + Activate_Args { r#id }, + ) + } + fn add_from_manifest( + &mut self, + r#manifestPath: String, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromManifest", + AddFromManifest_Args { r#manifestPath }, + ) + } + fn add_from_url( + &mut self, + r#url: String, + r#authToken: Option, + r#artifactsUrl: Option, + ) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.AddFromUrl", + AddFromUrl_Args { + r#url, + r#authToken, + r#artifactsUrl, + }, + ) + } + fn inspect(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Inspect", + Inspect_Args { r#id }, + ) + } + fn list(&mut self) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.List", + List_Args {}, + ) + } + fn remove(&mut self, r#id: String) -> varlink::MethodCall { + varlink::MethodCall::::new( + self.connection.clone(), + "org.avocado.Runtimes.Remove", + Remove_Args { r#id }, + ) + } +} +#[allow(dead_code)] +pub struct VarlinkInterfaceProxy { + inner: Box, +} +#[allow(dead_code)] +pub fn new(inner: Box) -> VarlinkInterfaceProxy { + VarlinkInterfaceProxy { inner } +} +impl varlink::Interface for VarlinkInterfaceProxy { + fn get_description(&self) -> &'static str { + "# Runtime lifecycle management for Avocado Linux\ninterface org.avocado.Runtimes\n\ntype RuntimeInfo (\n name: string,\n version: string\n)\n\ntype ManifestExtension (\n name: string,\n version: string,\n imageId: ?string\n)\n\ntype Runtime (\n id: string,\n manifestVersion: int,\n builtAt: string,\n runtime: RuntimeInfo,\n extensions: []ManifestExtension,\n active: bool\n)\n\n# List all available runtimes\nmethod List() -> (runtimes: []Runtime)\n\n# Add a runtime from a TUF repository URL (authToken: optional bearer token for protected endpoints)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromUrl(url: string, authToken: ?string, artifactsUrl: ?string) -> (message: string, done: bool)\n\n# Add a runtime from a local manifest file\n# Supports streaming: client may set more=true to receive per-message progress\nmethod AddFromManifest(manifestPath: string) -> (message: string, done: bool)\n\n# Remove a staged runtime by ID (or prefix)\nmethod Remove(id: string) -> ()\n\n# Activate a staged runtime by ID (or prefix)\n# Supports streaming: client may set more=true to receive per-message progress\nmethod Activate(id: string) -> (message: string, done: bool)\n\n# Inspect a runtime's details\nmethod Inspect(id: string) -> (runtime: Runtime)\n\nerror RuntimeNotFound (id: string)\nerror AmbiguousRuntimeId (id: string, candidates: []string)\nerror RemoveActiveRuntime ()\nerror StagingFailed (reason: string)\nerror UpdateFailed (reason: string)\n" + } + fn get_name(&self) -> &'static str { + "org.avocado.Runtimes" + } + fn call_upgraded( + &self, + call: &mut varlink::Call, + bufreader: &mut dyn BufRead, + ) -> varlink::Result> { + self.inner.call_upgraded(call, bufreader) + } + fn call(&self, call: &mut varlink::Call) -> varlink::Result<()> { + let req = call.request.unwrap(); + match req.method.as_ref() { + "org.avocado.Runtimes.Activate" => { + if let Some(args) = req.parameters.clone() { + let args: Activate_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner + .activate(call as &mut dyn Call_Activate, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromManifest" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromManifest_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_manifest( + call as &mut dyn Call_AddFromManifest, + args.r#manifestPath, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.AddFromUrl" => { + if let Some(args) = req.parameters.clone() { + let args: AddFromUrl_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.add_from_url( + call as &mut dyn Call_AddFromUrl, + args.r#url, + args.r#authToken, + args.r#artifactsUrl, + ) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.Inspect" => { + if let Some(args) = req.parameters.clone() { + let args: Inspect_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.inspect(call as &mut dyn Call_Inspect, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + "org.avocado.Runtimes.List" => self.inner.list(call as &mut dyn Call_List), + "org.avocado.Runtimes.Remove" => { + if let Some(args) = req.parameters.clone() { + let args: Remove_Args = match serde_json::from_value(args) { + Ok(v) => v, + Err(e) => { + let es = format!("{}", e); + let _ = call.reply_invalid_parameter(es.clone()); + return Err(varlink::context!(varlink::ErrorKind::SerdeJsonDe(es))); + } + }; + self.inner.remove(call as &mut dyn Call_Remove, args.r#id) + } else { + call.reply_invalid_parameter("parameters".into()) + } + } + m => call.reply_method_not_found(String::from(m)), + } + } +} From 2b0fae361b24f48d8e3782321f3217587e6221eb Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 20:53:33 -0400 Subject: [PATCH 26/27] fix: sort runtime list by active-first then newest, sort status by merge priority - Runtime list now shows active runtime first, then remaining by build date (newest first) - Extension status via varlink now sorts by merge_index (priority order) instead of alphabetically --- src/commands/ext.rs | 34 +++++++++++++++++++++++++++++++++- src/manifest.rs | 18 ++++++++---------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/commands/ext.rs b/src/commands/ext.rs index f7db682..b3d949b 100644 --- a/src/commands/ext.rs +++ b/src/commands/ext.rs @@ -1068,7 +1068,39 @@ pub(crate) fn collect_extension_status( }) .collect(); - result.sort_by(|a, b| a.name.cmp(&b.name)); + // Sort descending by merge_index (highest priority / top layer first). + // Extensions without a merge_index sort to the bottom, then alphabetically. + result.sort_by(|a, b| { + let versioned_a = match &a.version { + Some(v) => format!("{}-{}", a.name, v), + None => a.name.clone(), + }; + let versioned_b = match &b.version { + Some(v) => format!("{}-{}", b.name, v), + None => b.name.clone(), + }; + let idx_a = available_extensions + .iter() + .find(|e| { + if let Some(ver) = &e.version { + format!("{}-{}", e.name, ver) == versioned_a + } else { + e.name == versioned_a + } + }) + .and_then(|e| e.merge_index); + let idx_b = available_extensions + .iter() + .find(|e| { + if let Some(ver) = &e.version { + format!("{}-{}", e.name, ver) == versioned_b + } else { + e.name == versioned_b + } + }) + .and_then(|e| e.merge_index); + idx_b.cmp(&idx_a).then_with(|| a.name.cmp(&b.name)) + }); Ok(result) } diff --git a/src/manifest.rs b/src/manifest.rs index 65ef7fb..329930c 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -109,12 +109,11 @@ impl RuntimeManifest { } } - results.sort_by(|(a, _), (b, _)| { - a.runtime - .name - .cmp(&b.runtime.name) - .then_with(|| a.runtime.version.cmp(&b.runtime.version)) - .then_with(|| b.built_at.cmp(&a.built_at)) // newest first + results.sort_by(|(a, a_active), (b, b_active)| { + // Active runtime always first, then newest-built first + b_active + .cmp(a_active) + .then_with(|| b.built_at.cmp(&a.built_at)) }); results @@ -207,13 +206,12 @@ mod tests { let list = RuntimeManifest::list_all(tmp.path()); assert_eq!(list.len(), 3); - // Same name+version group: newest first + // Active first, then newest-built first assert_eq!(list[0].0.id, "bbb"); assert!(list[0].1); // active - assert_eq!(list[1].0.id, "aaa"); + assert_eq!(list[1].0.id, "aaa"); // 2026-02-17 assert!(!list[1].1); - // Different version - assert_eq!(list[2].0.id, "ccc"); + assert_eq!(list[2].0.id, "ccc"); // 2026-02-16 assert!(!list[2].1); } From 4127cafa1912994616a1e03963ec5e5ed4d68f0a Mon Sep 17 00:00:00 2001 From: Justin Schneck Date: Sun, 8 Mar 2026 21:14:38 -0400 Subject: [PATCH 27/27] release: avocadoctl 0.6.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d85ca1..d996bb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,7 +112,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "avocadoctl" -version = "0.6.0-dev" +version = "0.6.0" dependencies = [ "base64", "clap", diff --git a/Cargo.toml b/Cargo.toml index 9786b2f..165bc67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "avocadoctl" -version = "0.6.0-dev" +version = "0.6.0" edition = "2021" description = "Avocado Linux control CLI tool" authors = ["Avocado"]