lenso_plugin_bundle/
selection.rs1use lenso_app_plan::{ExecutionClassId, authoring::PluginDescriptor};
2
3use crate::{BundleError, PluginArtifactV2, PluginManifest, invalid_bundle};
4
5#[derive(Clone, Debug, Eq, PartialEq)]
7pub struct RuntimeAdmission {
8 pub execution_class: ExecutionClassId,
9 pub runtime_profile: String,
10}
11
12#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct ImplementationPolicy {
15 pub host_target: String,
16 pub runtimes: Vec<RuntimeAdmission>,
17}
18
19#[derive(Clone, Debug, Eq, PartialEq)]
21pub struct ResolvedPluginImplementation {
22 pub implementation_id: String,
23 pub descriptor: PluginDescriptor,
24 pub artifact: PluginArtifactV2,
25}
26
27pub fn resolve_implementation(
29 manifest: &PluginManifest,
30 policy: &ImplementationPolicy,
31) -> Result<ResolvedPluginImplementation, BundleError> {
32 match manifest {
33 PluginManifest::V2(value) => {
34 let descriptor =
35 serde_json::from_value::<PluginDescriptor>(value.entry.descriptor.clone())
36 .map_err(|error| BundleError::InvalidManifest(error.to_string()))?;
37 if !policy.runtimes.iter().any(|admission| {
38 admission.execution_class == *descriptor.execution_class()
39 && admission.runtime_profile == descriptor.runtime_profile()
40 }) || !target_matches(&value.artifact, &policy.host_target)
41 {
42 return invalid_bundle("V2 Bundle has no implementation admitted by Host policy");
43 }
44 Ok(ResolvedPluginImplementation {
45 implementation_id: "default".to_owned(),
46 descriptor,
47 artifact: value.artifact.clone(),
48 })
49 }
50 PluginManifest::V3(value) => resolve_profiled_implementation(
51 &value.contract,
52 value.implementations.iter().map(|candidate| {
53 (
54 &candidate.id,
55 &candidate.host_targets,
56 &candidate.artifact,
57 &candidate.runtime,
58 )
59 }),
60 policy,
61 "V3",
62 ),
63 PluginManifest::V4(value) => resolve_profiled_implementation(
64 &value.contract,
65 value.implementations.iter().map(|candidate| {
66 (
67 &candidate.id,
68 &candidate.host_targets,
69 &candidate.artifact,
70 &candidate.runtime,
71 )
72 }),
73 policy,
74 "V4",
75 ),
76 }
77}
78
79fn resolve_profiled_implementation<'a>(
80 contract: &lenso_app_plan::authoring::PluginContract,
81 candidates: impl Iterator<
82 Item = (
83 &'a String,
84 &'a Vec<String>,
85 &'a PluginArtifactV2,
86 &'a lenso_app_plan::authoring::PluginImplementation,
87 ),
88 >,
89 policy: &ImplementationPolicy,
90 schema: &str,
91) -> Result<ResolvedPluginImplementation, BundleError> {
92 let candidates = candidates.collect::<Vec<_>>();
93 for admission in &policy.runtimes {
94 let matches = candidates
95 .iter()
96 .filter(|(_, targets, _, runtime)| {
97 runtime.execution_class() == &admission.execution_class
98 && runtime.runtime_profile() == admission.runtime_profile
99 && targets
100 .iter()
101 .any(|target| target == "*" || target == &policy.host_target)
102 })
103 .collect::<Vec<_>>();
104 match matches.as_slice() {
105 [] => {}
106 [(id, _, artifact, runtime)] => {
107 return Ok(ResolvedPluginImplementation {
108 implementation_id: (*id).clone(),
109 descriptor: contract.resolve(runtime),
110 artifact: (*artifact).clone(),
111 });
112 }
113 _ => {
114 return invalid_bundle(format!(
115 "Host policy ambiguously matches {} implementations of `({}, {})`",
116 matches.len(),
117 admission.execution_class.as_str(),
118 admission.runtime_profile
119 ));
120 }
121 }
122 }
123 invalid_bundle(format!(
124 "{schema} Bundle has no implementation admitted by Host policy"
125 ))
126}
127
128fn target_matches(artifact: &PluginArtifactV2, host_target: &str) -> bool {
129 artifact.media_type == "application/wasm" || artifact.target == host_target
130}