wasmcloud_control_interface/types/
component.rs

1//! Data types used when dealing with components on a wasmCloud lattice
2
3use std::collections::{BTreeMap, HashMap};
4
5use serde::{Deserialize, Serialize};
6
7use crate::Result;
8
9/// A summary description of an component within a host inventory
10#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
11#[non_exhaustive]
12pub struct ComponentDescription {
13    /// The unique component identifier for this component
14    #[serde(default)]
15    pub(crate) id: String,
16
17    /// Image reference for this component
18    #[serde(default)]
19    pub(crate) image_ref: String,
20
21    /// Name of this component, if one exists
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub(crate) name: Option<String>,
24
25    /// The annotations that were used in the start request that produced
26    /// this component instance
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub(crate) annotations: Option<BTreeMap<String, String>>,
29
30    /// The revision number for this component instance
31    #[serde(default)]
32    pub(crate) revision: i32,
33
34    /// The maximum number of concurrent requests this instance can handle
35    #[serde(default)]
36    pub(crate) max_instances: u32,
37
38    /// The collective resource constraints for this component, such as memory limits and maximum execution time
39    #[serde(default)]
40    pub(crate) limits: Option<HashMap<String, String>>,
41}
42
43#[derive(Default, Clone, PartialEq, Eq)]
44#[non_exhaustive]
45pub struct ComponentDescriptionBuilder {
46    id: Option<String>,
47    image_ref: Option<String>,
48    name: Option<String>,
49    annotations: Option<BTreeMap<String, String>>,
50    revision: Option<i32>,
51    max_instances: Option<u32>,
52    limits: Option<HashMap<String, String>>,
53}
54
55impl ComponentDescriptionBuilder {
56    #[must_use]
57    pub fn id(mut self, v: String) -> Self {
58        self.id = Some(v);
59        self
60    }
61
62    #[must_use]
63    pub fn image_ref(mut self, v: String) -> Self {
64        self.image_ref = Some(v);
65        self
66    }
67
68    #[must_use]
69    pub fn name(mut self, v: String) -> Self {
70        self.name = Some(v);
71        self
72    }
73
74    #[must_use]
75    pub fn revision(mut self, v: i32) -> Self {
76        self.revision = Some(v);
77        self
78    }
79
80    #[must_use]
81    pub fn max_instances(mut self, v: u32) -> Self {
82        self.max_instances = Some(v);
83        self
84    }
85
86    #[must_use]
87    pub fn limits(mut self, v: Option<HashMap<String, String>>) -> Self {
88        self.limits = v;
89        self
90    }
91
92    #[must_use]
93    pub fn annotations(mut self, v: BTreeMap<String, String>) -> Self {
94        self.annotations = Some(v);
95        self
96    }
97
98    pub fn build(self) -> Result<ComponentDescription> {
99        Ok(ComponentDescription {
100            image_ref: self
101                .image_ref
102                .ok_or_else(|| "image_ref is required".to_string())?,
103            id: self.id.ok_or_else(|| "id is required".to_string())?,
104            name: self.name,
105            revision: self.revision.unwrap_or_default(),
106            max_instances: self.max_instances.unwrap_or_default(),
107            annotations: self.annotations,
108            limits: self.limits,
109        })
110    }
111}
112
113impl ComponentDescription {
114    /// Get the ID of the component
115    pub fn id(&self) -> &str {
116        &self.id
117    }
118
119    /// Get the image reference of the component
120    pub fn image_ref(&self) -> &str {
121        &self.image_ref
122    }
123
124    /// Get the name of the component
125    pub fn name(&self) -> Option<&str> {
126        self.name.as_deref()
127    }
128
129    /// Get the annotations of the component
130    pub fn annotations(&self) -> Option<&BTreeMap<String, String>> {
131        self.annotations.as_ref()
132    }
133
134    /// Get the revision of the component
135    pub fn revision(&self) -> i32 {
136        self.revision
137    }
138
139    /// Get the revision of the component
140    pub fn max_instances(&self) -> u32 {
141        self.max_instances
142    }
143
144    pub fn limits(&self) -> Option<HashMap<String, String>> {
145        self.limits.clone()
146    }
147
148    #[must_use]
149    pub fn builder() -> ComponentDescriptionBuilder {
150        ComponentDescriptionBuilder::default()
151    }
152}
153
154#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
155#[non_exhaustive]
156pub struct ComponentInstance {
157    /// The annotations that were used in the start request that produced
158    /// this component instance
159    #[serde(default, skip_serializing_if = "Option::is_none")]
160    pub(crate) annotations: Option<BTreeMap<String, String>>,
161
162    /// Image reference for this component
163    #[serde(default)]
164    pub(crate) image_ref: String,
165
166    /// This instance's unique ID (guid)
167    #[serde(default)]
168    pub(crate) instance_id: String,
169
170    /// The revision number for this component instance
171    #[serde(default)]
172    pub(crate) revision: i32,
173
174    /// The maximum number of concurrent requests this instance can handle
175    #[serde(default)]
176    pub(crate) max_instances: u32,
177}
178
179impl ComponentInstance {
180    /// Get the image reference of the component instance
181    pub fn image_ref(&self) -> &str {
182        &self.image_ref
183    }
184
185    /// Get the image ID of the component instance
186    pub fn instance_id(&self) -> &str {
187        &self.instance_id
188    }
189
190    /// Get the annotations of the component
191    pub fn annotations(&self) -> Option<&BTreeMap<String, String>> {
192        self.annotations.as_ref()
193    }
194
195    /// Get the revision of the component
196    pub fn revision(&self) -> i32 {
197        self.revision
198    }
199
200    /// Get the revision of the component
201    pub fn max_instances(&self) -> u32 {
202        self.max_instances
203    }
204
205    #[must_use]
206    pub fn builder() -> ComponentInstanceBuilder {
207        ComponentInstanceBuilder::default()
208    }
209}
210
211#[derive(Default, Clone, PartialEq, Eq)]
212#[non_exhaustive]
213pub struct ComponentInstanceBuilder {
214    instance_id: Option<String>,
215    image_ref: Option<String>,
216    revision: Option<i32>,
217    max_instances: Option<u32>,
218    annotations: Option<BTreeMap<String, String>>,
219}
220
221impl ComponentInstanceBuilder {
222    #[must_use]
223    pub fn instance_id(mut self, v: String) -> Self {
224        self.instance_id = Some(v);
225        self
226    }
227
228    #[must_use]
229    pub fn image_ref(mut self, v: String) -> Self {
230        self.image_ref = Some(v);
231        self
232    }
233
234    #[must_use]
235    pub fn revision(mut self, v: i32) -> Self {
236        self.revision = Some(v);
237        self
238    }
239
240    #[must_use]
241    pub fn max_instances(mut self, v: u32) -> Self {
242        self.max_instances = Some(v);
243        self
244    }
245
246    #[must_use]
247    pub fn annotations(mut self, v: BTreeMap<String, String>) -> Self {
248        self.annotations = Some(v);
249        self
250    }
251
252    pub fn build(self) -> Result<ComponentInstance> {
253        Ok(ComponentInstance {
254            image_ref: self
255                .image_ref
256                .ok_or_else(|| "image_ref is required".to_string())?,
257            instance_id: self
258                .instance_id
259                .ok_or_else(|| "id is required".to_string())?,
260            revision: self.revision.unwrap_or_default(),
261            max_instances: self.max_instances.unwrap_or_default(),
262            annotations: self.annotations,
263        })
264    }
265}
266
267#[cfg(test)]
268mod tests {
269    use std::collections::BTreeMap;
270
271    use super::{ComponentDescription, ComponentInstance};
272
273    #[test]
274    fn component_desc_builder() {
275        assert_eq!(
276            ComponentDescription {
277                id: "id".into(),
278                image_ref: "ref".into(),
279                name: Some("name".into()),
280                annotations: Some(BTreeMap::from([("a".into(), "b".into())])),
281                revision: 0,
282                max_instances: 1,
283                limits: None,
284            },
285            ComponentDescription::builder()
286                .id("id".into())
287                .name("test".into())
288                .image_ref("ref".into())
289                .name("name".into())
290                .annotations(BTreeMap::from([("a".into(), "b".into())]))
291                .revision(0)
292                .max_instances(1)
293                .limits(None)
294                .build()
295                .unwrap()
296        )
297    }
298
299    #[test]
300    fn component_instance_builder() {
301        assert_eq!(
302            ComponentInstance {
303                instance_id: "id".into(),
304                image_ref: "ref".into(),
305                annotations: Some(BTreeMap::from([("a".into(), "b".into())])),
306                revision: 0,
307                max_instances: 1,
308            },
309            ComponentInstance::builder()
310                .instance_id("id".into())
311                .image_ref("ref".into())
312                .annotations(BTreeMap::from([("a".into(), "b".into())]))
313                .revision(0)
314                .max_instances(1)
315                .build()
316                .unwrap()
317        )
318    }
319}