lenso_plugin_bundle/
selection.rs1use lenso_app_plan::{ExecutionClassId, authoring::PluginDescriptor};
2
3use crate::{
4 BundleError, PluginArtifactV2, PluginImplementationV3, PluginManifest, invalid_bundle,
5};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct ImplementationPolicy {
10 pub host_target: String,
11 pub execution_classes: Vec<ExecutionClassId>,
12}
13
14#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct ResolvedPluginImplementation {
17 pub implementation_id: String,
18 pub descriptor: PluginDescriptor,
19 pub artifact: PluginArtifactV2,
20}
21
22pub fn resolve_implementation(
24 manifest: &PluginManifest,
25 policy: &ImplementationPolicy,
26) -> Result<ResolvedPluginImplementation, BundleError> {
27 match manifest {
28 PluginManifest::V2(value) => {
29 let descriptor =
30 serde_json::from_value::<PluginDescriptor>(value.entry.descriptor.clone())
31 .map_err(|error| BundleError::InvalidManifest(error.to_string()))?;
32 if !policy
33 .execution_classes
34 .contains(descriptor.execution_class())
35 || !target_matches(&value.artifact, &policy.host_target)
36 {
37 return invalid_bundle("V2 Bundle has no implementation admitted by Host policy");
38 }
39 Ok(ResolvedPluginImplementation {
40 implementation_id: "default".to_owned(),
41 descriptor,
42 artifact: value.artifact.clone(),
43 })
44 }
45 PluginManifest::V3(value) => {
46 for execution_class in &policy.execution_classes {
47 let matches = value
48 .implementations
49 .iter()
50 .filter(|candidate| {
51 candidate.runtime.execution_class() == execution_class
52 && candidate
53 .host_targets
54 .iter()
55 .any(|target| target == "*" || target == &policy.host_target)
56 })
57 .collect::<Vec<_>>();
58 match matches.as_slice() {
59 [] => {}
60 [candidate] => return Ok(resolved_v3(value, candidate)),
61 _ => {
62 return invalid_bundle(format!(
63 "Host policy ambiguously matches {} implementations of `{}`",
64 matches.len(),
65 execution_class.as_str()
66 ));
67 }
68 }
69 }
70 invalid_bundle("V3 Bundle has no implementation admitted by Host policy")
71 }
72 }
73}
74
75fn resolved_v3(
76 manifest: &crate::PluginManifestV3,
77 candidate: &PluginImplementationV3,
78) -> ResolvedPluginImplementation {
79 ResolvedPluginImplementation {
80 implementation_id: candidate.id.clone(),
81 descriptor: manifest.contract.resolve(&candidate.runtime),
82 artifact: candidate.artifact.clone(),
83 }
84}
85
86fn target_matches(artifact: &PluginArtifactV2, host_target: &str) -> bool {
87 artifact.media_type == "application/wasm" || artifact.target == host_target
88}