wasmcloud_control_interface/types/
component.rs

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