shuttle_common/models/
resource.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Clone, Debug, Serialize, Deserialize)]
5#[typeshare::typeshare]
6pub struct ProvisionResourceRequest {
7    /// The type of this resource
8    pub r#type: ResourceType,
9    /// The config used when creating this resource.
10    /// Use `Self::r#type` to know how to parse this data.
11    pub config: Value,
12}
13
14/// Helper for deserializing
15#[derive(Deserialize)]
16#[serde(untagged)] // Try deserializing as a Shuttle resource, fall back to a custom value
17pub enum ResourceInput {
18    Shuttle(ProvisionResourceRequest),
19    Custom(Value),
20}
21
22/// The resource state represents the stage of the provisioning process the resource is in.
23#[derive(
24    Debug, Clone, PartialEq, Eq, strum::Display, strum::EnumString, Serialize, Deserialize,
25)]
26#[serde(rename_all = "lowercase")]
27#[strum(serialize_all = "lowercase")]
28#[typeshare::typeshare]
29pub enum ResourceState {
30    Authorizing,
31    Provisioning,
32    Failed,
33    Ready,
34    Deleting,
35    Deleted,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
39#[typeshare::typeshare]
40pub struct ResourceResponse {
41    pub r#type: ResourceType,
42    pub state: ResourceState,
43    /// The config used when creating this resource. Use the `r#type` to know how to parse this data.
44    pub config: Value,
45    /// The output type for this resource, if state is Ready. Use the `r#type` to know how to parse this data.
46    pub output: Value,
47}
48
49#[derive(Debug, Serialize, Deserialize)]
50#[typeshare::typeshare]
51pub struct ResourceListResponse {
52    pub resources: Vec<ResourceResponse>,
53}
54
55#[derive(
56    Clone,
57    Copy,
58    Debug,
59    Deserialize,
60    Serialize,
61    Eq,
62    PartialEq,
63    strum::AsRefStr,
64    strum::Display,
65    strum::EnumString,
66)]
67#[typeshare::typeshare]
68// is a flat enum instead of nested enum to allow typeshare
69pub enum ResourceType {
70    #[strum(to_string = "database::shared::postgres")]
71    #[serde(rename = "database::shared::postgres")]
72    DatabaseSharedPostgres,
73    #[strum(to_string = "database::aws_rds::postgres")]
74    #[serde(rename = "database::aws_rds::postgres")]
75    DatabaseAwsRdsPostgres,
76    #[strum(to_string = "database::aws_rds::mysql")]
77    #[serde(rename = "database::aws_rds::mysql")]
78    DatabaseAwsRdsMySql,
79    #[strum(to_string = "database::aws_rds::mariadb")]
80    #[serde(rename = "database::aws_rds::mariadb")]
81    DatabaseAwsRdsMariaDB,
82    /// (Will probably be removed)
83    #[strum(to_string = "secrets")]
84    #[serde(rename = "secrets")]
85    Secrets,
86    /// Local provisioner only
87    #[strum(to_string = "container")]
88    #[serde(rename = "container")]
89    Container,
90}
91
92#[cfg(test)]
93mod test {
94    use std::str::FromStr;
95
96    use super::*;
97
98    #[test]
99    fn to_string_and_back() {
100        let inputs = [
101            ResourceType::DatabaseSharedPostgres,
102            ResourceType::Secrets,
103            ResourceType::Container,
104        ];
105
106        for input in inputs {
107            let actual = ResourceType::from_str(input.as_ref()).unwrap();
108            assert_eq!(input, actual, ":{} should map back to itself", input);
109        }
110    }
111}