Skip to main content

vector/template/
configurable.rs

1use super::*;
2
3impl Template {
4    /// Confine this template to its literal prefix, returning a [`ConfinedTemplate`] that enforces
5    /// the confinement invariant at render time.
6    ///
7    /// Most sinks reach this through [`Template::confine`]; call this directly only when a sink
8    /// constructs an [`UnconfinedTemplate`] itself (e.g. from a default value) and needs to confine
9    /// it.
10    pub fn confine(
11        self,
12        config: &ConfinementConfig,
13        component_name: &'static str,
14        field_name: &'static str,
15    ) -> crate::Result<ConfinedTemplate> {
16        // Full opt-out: bypass all confinement for this template (startup AND
17        // runtime). The `vector_security_confinement_disabled` gauge is owned by
18        // the topology, not emitted here.
19        if config.dangerously_allow_unconfined_template_resolution {
20            ConfinementConfig::warn_unconfined_template("sink", component_name, field_name);
21            return Ok(ConfinedTemplate {
22                inner: self.inner,
23                checker: None,
24            });
25        }
26        match ConfinementChecker::for_template(&self) {
27            Ok(Some(checker)) => Ok(ConfinedTemplate {
28                inner: self.inner,
29                checker: Some(checker),
30            }),
31            Ok(None) => Ok(ConfinedTemplate {
32                inner: self.inner,
33                checker: None,
34            }),
35            Err(e) => Err(e.into()),
36        }
37    }
38
39    /// Set the tz offset used when rendering strftime specifiers.
40    pub const fn with_tz_offset(mut self, tz_offset: Option<FixedOffset>) -> Self {
41        self.inner.tz_offset = tz_offset;
42        self
43    }
44
45    /// Returns the names of the fields referenced by this template, if any.
46    ///
47    /// This is a read-only inspection that does not render, so it is available before confinement
48    /// (e.g. for topology field detection).
49    pub fn get_fields(&self) -> Option<Vec<String>> {
50        self.inner.get_fields()
51    }
52
53    /// Longest leading substring of the template source that is rendered
54    /// verbatim — no `{{ field }}` reference and no strftime specifier.
55    ///
56    /// Sinks use this to derive a confinement boundary from the
57    /// operator-authored portion of the template.
58    pub fn literal_prefix(&self) -> &str {
59        self.inner.literal_prefix()
60    }
61
62    /// Returns a reference to the template source string.
63    pub const fn get_ref(&self) -> &str {
64        self.inner.get_ref()
65    }
66
67    /// Returns `true` if the template source is empty.
68    pub const fn is_empty(&self) -> bool {
69        self.inner.is_empty()
70    }
71
72    /// Returns `true` if the template depends on the input event or time.
73    pub const fn is_dynamic(&self) -> bool {
74        self.inner.is_dynamic()
75    }
76}
77
78impl fmt::Display for Template {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        self.inner.fmt(f)
81    }
82}
83
84impl From<UnconfinedTemplate> for Template {
85    fn from(inner: UnconfinedTemplate) -> Self {
86        Template { inner }
87    }
88}
89
90impl TryFrom<String> for Template {
91    type Error = TemplateParseError;
92
93    fn try_from(s: String) -> Result<Self, Self::Error> {
94        UnconfinedTemplate::try_from(s).map(|inner| Template { inner })
95    }
96}
97
98impl TryFrom<&str> for Template {
99    type Error = TemplateParseError;
100
101    fn try_from(s: &str) -> Result<Self, Self::Error> {
102        UnconfinedTemplate::try_from(s).map(|inner| Template { inner })
103    }
104}
105
106impl TryFrom<PathBuf> for Template {
107    type Error = TemplateParseError;
108
109    fn try_from(p: PathBuf) -> Result<Self, Self::Error> {
110        UnconfinedTemplate::try_from(p).map(|inner| Template { inner })
111    }
112}
113
114impl From<Template> for String {
115    fn from(t: Template) -> String {
116        t.inner.src
117    }
118}
119
120// This is safe because we literally defer to `String` for the schema of `Template`.
121impl ConfigurableString for Template {}