gatehouse_runtime_protocol/lifecycle/journal/
resolution.rs1use super::*;
3use crate::lifecycle::wire::Entry;
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(deny_unknown_fields)]
6pub struct CreatePlan {
7 pub name: String,
8 pub labels: Vec<Entry>,
9 pub environment: Vec<Entry>,
10 pub container_port: u16,
11 #[serde(default, skip_serializing_if = "Option::is_none")]
13 pub command: Option<Vec<String>>,
14}
15impl CreatePlan {
16 pub fn validate(&self, resolve: &Request) -> Result<()> {
17 resolve.validate()?;
18 if !matches!(resolve.operation, Operation::ResolveImage { .. })
19 || resolve.binding.generation != 1
20 {
21 return Err(Invalid("reservation requires initial image resolution"));
22 }
23 self.request(
24 resolve,
25 &format!("sha256:{}", "0".repeat(64)),
26 &resolve.binding.invocation,
27 )?
28 .validate()
29 }
30 fn request(&self, resolve: &Request, image_id: &str, invocation: &str) -> Result<Request> {
31 let mut request = resolve.clone();
32 request.operation = Operation::Create {
33 name: self.name.clone(),
34 image_id: image_id.into(),
35 labels: self.labels.clone(),
36 environment: self.environment.clone(),
37 container_port: self.container_port,
38 command: self.command.clone(),
39 };
40 request.binding.generation = 2;
41 request.binding.invocation = invocation.into();
42 request.binding.operation_key = request.operation_key()?;
43 Ok(request)
44 }
45}
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47#[serde(deny_unknown_fields)]
48pub(super) struct ResolutionProof {
49 pub request: Request,
50 pub plan: CreatePlan,
51 pub response: Response,
52}
53impl ResolutionProof {
54 pub fn create(&self, invocation: &str) -> Result<Request> {
55 self.plan.validate(&self.request)?;
56 self.response.validate(&self.request)?;
57 let Outcome::Image { image_id, .. } = &self.response.outcome else {
58 return Err(Invalid("image resolution not proven"));
59 };
60 if invocation == self.request.binding.invocation {
61 return Err(Invalid("create invocation must be fresh"));
62 }
63 let create = self.plan.request(&self.request, image_id, invocation)?;
64 create.validate()?;
65 Ok(create)
66 }
67 pub fn validate_create(&self, create: &Request) -> Result<()> {
68 if self.create(&create.binding.invocation)? != *create {
69 return Err(Invalid("create differs from reserved plan/image evidence"));
70 }
71 Ok(())
72 }
73}