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