Skip to main content

compose_lens/model/
lifecycle_hook.rs

1//! Source-aware service lifecycle-hook descriptors.
2
3use crate::source::SourceSpan;
4
5use super::{BooleanValue, Command, Environment, FieldReference, Located};
6
7/// One authored service lifecycle-hook mapping.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ServiceHook {
10    span: SourceSpan,
11    command: Option<Command>,
12    environment: Option<Environment>,
13    privileged: Option<Located<BooleanValue>>,
14    user: Option<Located<String>>,
15    working_dir: Option<Located<String>>,
16    extension_fields: Vec<FieldReference>,
17    unknown_fields: Vec<FieldReference>,
18}
19
20impl ServiceHook {
21    pub(crate) const fn new(span: SourceSpan) -> Self {
22        Self {
23            span,
24            command: None,
25            environment: None,
26            privileged: None,
27            user: None,
28            working_dir: None,
29            extension_fields: Vec::new(),
30            unknown_fields: Vec::new(),
31        }
32    }
33
34    pub(crate) fn set_command(&mut self, value: Command) {
35        self.command = Some(value);
36    }
37
38    pub(crate) fn set_environment(&mut self, value: Environment) {
39        self.environment = Some(value);
40    }
41
42    pub(crate) fn set_privileged(&mut self, value: Located<BooleanValue>) {
43        self.privileged = Some(value);
44    }
45
46    pub(crate) fn set_user(&mut self, value: Located<String>) {
47        self.user = Some(value);
48    }
49
50    pub(crate) fn set_working_dir(&mut self, value: Located<String>) {
51        self.working_dir = Some(value);
52    }
53
54    pub(crate) fn push_extension(&mut self, field: FieldReference) {
55        self.extension_fields.push(field);
56    }
57
58    pub(crate) fn push_unknown(&mut self, field: FieldReference) {
59        self.unknown_fields.push(field);
60    }
61
62    /// Returns the complete hook mapping span.
63    #[must_use]
64    pub const fn span(&self) -> SourceSpan {
65        self.span
66    }
67
68    /// Returns the required command without shell or argv interpretation.
69    #[must_use]
70    pub const fn command(&self) -> Option<&Command> {
71        self.command.as_ref()
72    }
73
74    /// Returns the hook-local environment without combining it with service environment values.
75    #[must_use]
76    pub const fn environment(&self) -> Option<&Environment> {
77        self.environment.as_ref()
78    }
79
80    /// Returns the explicit hook privilege choice.
81    #[must_use]
82    pub const fn privileged(&self) -> Option<&Located<BooleanValue>> {
83        self.privileged.as_ref()
84    }
85
86    /// Returns the strict YAML-string hook user without default resolution.
87    #[must_use]
88    pub const fn user(&self) -> Option<&Located<String>> {
89        self.user.as_ref()
90    }
91
92    /// Returns the strict YAML-string hook working directory without path resolution.
93    #[must_use]
94    pub const fn working_dir(&self) -> Option<&Located<String>> {
95        self.working_dir.as_ref()
96    }
97
98    /// Returns retained hook `x-*` members.
99    #[must_use]
100    pub fn extension_fields(&self) -> &[FieldReference] {
101        &self.extension_fields
102    }
103
104    /// Returns malformed, duplicate, and unknown hook members.
105    #[must_use]
106    pub fn unknown_fields(&self) -> &[FieldReference] {
107        &self.unknown_fields
108    }
109}
110
111/// One authored service `pre_start` hook mapping.
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct PreStartServiceHook {
114    span: SourceSpan,
115    command: Option<Command>,
116    image: Option<Located<String>>,
117    environment: Option<Environment>,
118    privileged: Option<Located<BooleanValue>>,
119    per_replica: Option<Located<BooleanValue>>,
120    user: Option<Located<String>>,
121    working_dir: Option<Located<String>>,
122    extension_fields: Vec<FieldReference>,
123    unknown_fields: Vec<FieldReference>,
124}
125
126impl PreStartServiceHook {
127    pub(crate) const fn new(span: SourceSpan) -> Self {
128        Self {
129            span,
130            command: None,
131            image: None,
132            environment: None,
133            privileged: None,
134            per_replica: None,
135            user: None,
136            working_dir: None,
137            extension_fields: Vec::new(),
138            unknown_fields: Vec::new(),
139        }
140    }
141
142    pub(crate) fn set_command(&mut self, value: Command) {
143        self.command = Some(value);
144    }
145
146    pub(crate) fn set_image(&mut self, value: Located<String>) {
147        self.image = Some(value);
148    }
149
150    pub(crate) fn set_environment(&mut self, value: Environment) {
151        self.environment = Some(value);
152    }
153
154    pub(crate) fn set_privileged(&mut self, value: Located<BooleanValue>) {
155        self.privileged = Some(value);
156    }
157
158    pub(crate) fn set_per_replica(&mut self, value: Located<BooleanValue>) {
159        self.per_replica = Some(value);
160    }
161
162    pub(crate) fn set_user(&mut self, value: Located<String>) {
163        self.user = Some(value);
164    }
165
166    pub(crate) fn set_working_dir(&mut self, value: Located<String>) {
167        self.working_dir = Some(value);
168    }
169
170    pub(crate) fn push_extension(&mut self, field: FieldReference) {
171        self.extension_fields.push(field);
172    }
173
174    pub(crate) fn push_unknown(&mut self, field: FieldReference) {
175        self.unknown_fields.push(field);
176    }
177
178    /// Returns the complete hook mapping span.
179    #[must_use]
180    pub const fn span(&self) -> SourceSpan {
181        self.span
182    }
183
184    /// Returns the optional command without shell or argv interpretation.
185    #[must_use]
186    pub const fn command(&self) -> Option<&Command> {
187        self.command.as_ref()
188    }
189
190    /// Returns the strict raw hook image without image-reference interpretation.
191    #[must_use]
192    pub const fn image(&self) -> Option<&Located<String>> {
193        self.image.as_ref()
194    }
195
196    /// Returns the hook-local environment without combining it with service environment values.
197    #[must_use]
198    pub const fn environment(&self) -> Option<&Environment> {
199        self.environment.as_ref()
200    }
201
202    /// Returns the explicit hook privilege choice.
203    #[must_use]
204    pub const fn privileged(&self) -> Option<&Located<BooleanValue>> {
205        self.privileged.as_ref()
206    }
207
208    /// Returns the explicit per-replica choice without injecting a default.
209    #[must_use]
210    pub const fn per_replica(&self) -> Option<&Located<BooleanValue>> {
211        self.per_replica.as_ref()
212    }
213
214    /// Returns the strict YAML-string hook user without default resolution.
215    #[must_use]
216    pub const fn user(&self) -> Option<&Located<String>> {
217        self.user.as_ref()
218    }
219
220    /// Returns the strict YAML-string hook working directory without path resolution.
221    #[must_use]
222    pub const fn working_dir(&self) -> Option<&Located<String>> {
223        self.working_dir.as_ref()
224    }
225
226    /// Returns retained hook `x-*` members.
227    #[must_use]
228    pub fn extension_fields(&self) -> &[FieldReference] {
229        &self.extension_fields
230    }
231
232    /// Returns malformed, duplicate, and unknown hook members.
233    #[must_use]
234    pub fn unknown_fields(&self) -> &[FieldReference] {
235        &self.unknown_fields
236    }
237}
238
239/// One authored `post_start` sequence item.
240#[derive(Debug, Clone, PartialEq, Eq)]
241#[non_exhaustive]
242pub enum PostStartHook {
243    /// A valid or partially recovered hook mapping.
244    Hook(Box<ServiceHook>),
245    /// A non-mapping item retained by source span.
246    Unmodeled {
247        /// Complete malformed-item span.
248        span: SourceSpan,
249    },
250}
251
252impl PostStartHook {
253    /// Returns the complete sequence-item span.
254    #[must_use]
255    pub const fn span(&self) -> SourceSpan {
256        match self {
257            Self::Hook(hook) => hook.span(),
258            Self::Unmodeled { span } => *span,
259        }
260    }
261}
262
263/// One authored `pre_stop` sequence item.
264#[derive(Debug, Clone, PartialEq, Eq)]
265#[non_exhaustive]
266pub enum PreStopHook {
267    /// A valid or partially recovered hook mapping.
268    Hook(Box<ServiceHook>),
269    /// A non-mapping item retained by source span.
270    Unmodeled {
271        /// Complete malformed-item span.
272        span: SourceSpan,
273    },
274}
275
276impl PreStopHook {
277    /// Returns the complete sequence-item span.
278    #[must_use]
279    pub const fn span(&self) -> SourceSpan {
280        match self {
281            Self::Hook(hook) => hook.span(),
282            Self::Unmodeled { span } => *span,
283        }
284    }
285}
286
287/// One authored `pre_start` sequence item.
288#[derive(Debug, Clone, PartialEq, Eq)]
289#[non_exhaustive]
290pub enum PreStartHook {
291    /// A valid or partially recovered hook mapping.
292    Hook(Box<PreStartServiceHook>),
293    /// A non-mapping item retained by source span.
294    Unmodeled {
295        /// Complete malformed-item span.
296        span: SourceSpan,
297    },
298}
299
300impl PreStartHook {
301    /// Returns the complete sequence-item span.
302    #[must_use]
303    pub const fn span(&self) -> SourceSpan {
304        match self {
305            Self::Hook(hook) => hook.span(),
306            Self::Unmodeled { span } => *span,
307        }
308    }
309}
310
311/// An authored `post_start` hook sequence, including an explicit empty sequence.
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct PostStartHooks {
314    span: SourceSpan,
315    entries: Vec<PostStartHook>,
316}
317
318impl PostStartHooks {
319    pub(crate) const fn new(span: SourceSpan, entries: Vec<PostStartHook>) -> Self {
320        Self { span, entries }
321    }
322
323    /// Returns the complete hook sequence span.
324    #[must_use]
325    pub const fn span(&self) -> SourceSpan {
326        self.span
327    }
328
329    /// Returns all hook and malformed entries in physical authored order.
330    #[must_use]
331    pub fn entries(&self) -> &[PostStartHook] {
332        &self.entries
333    }
334}
335
336/// An authored `pre_stop` hook sequence, including an explicit empty sequence.
337#[derive(Debug, Clone, PartialEq, Eq)]
338pub struct PreStopHooks {
339    span: SourceSpan,
340    entries: Vec<PreStopHook>,
341}
342
343impl PreStopHooks {
344    pub(crate) const fn new(span: SourceSpan, entries: Vec<PreStopHook>) -> Self {
345        Self { span, entries }
346    }
347
348    /// Returns the complete hook sequence span.
349    #[must_use]
350    pub const fn span(&self) -> SourceSpan {
351        self.span
352    }
353
354    /// Returns all hook and malformed entries in physical authored order.
355    #[must_use]
356    pub fn entries(&self) -> &[PreStopHook] {
357        &self.entries
358    }
359}
360
361/// An authored `pre_start` hook sequence, including an explicit empty sequence.
362#[derive(Debug, Clone, PartialEq, Eq)]
363pub struct PreStartHooks {
364    span: SourceSpan,
365    entries: Vec<PreStartHook>,
366}
367
368impl PreStartHooks {
369    pub(crate) const fn new(span: SourceSpan, entries: Vec<PreStartHook>) -> Self {
370        Self { span, entries }
371    }
372
373    /// Returns the complete hook sequence span.
374    #[must_use]
375    pub const fn span(&self) -> SourceSpan {
376        self.span
377    }
378
379    /// Returns all hook and malformed entries in physical authored order.
380    #[must_use]
381    pub fn entries(&self) -> &[PreStartHook] {
382        &self.entries
383    }
384}