shuttle_common/models/
resource.rs

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