Skip to main content

fiberplane_models/
data_sources.rs

1use crate::{names::Name, providers::Error, timestamps::Timestamp};
2use base64uuid::Base64Uuid;
3#[cfg(feature = "fp-bindgen")]
4use fp_bindgen::prelude::Serializable;
5use serde::{Deserialize, Serialize};
6use serde_json::{Map, Value};
7use std::collections::BTreeMap;
8use strum_macros::Display;
9use typed_builder::TypedBuilder;
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TypedBuilder)]
12#[non_exhaustive]
13#[serde(rename_all = "camelCase")]
14pub struct DataSource {
15    /// Data source ID.
16    #[builder(setter(into))]
17    pub id: Base64Uuid,
18
19    /// Name of the data source.
20    ///
21    /// Data source names do not need to be unique per workspace, but they are
22    /// unique per proxy.
23    pub name: Name,
24
25    /// Optional name of the FPD instance through which requests to the data
26    /// source should be proxied. This is `None` for direct data sources.
27    #[builder(default, setter(strip_option))]
28    pub proxy_name: Option<Name>,
29
30    /// The type of provider used for querying the data source.
31    #[builder(setter(into))]
32    pub provider_type: String,
33
34    /// Protocol version supported by the provider.
35    #[builder(default)]
36    #[serde(default)]
37    pub protocol_version: u8,
38
39    /// Optional human-friendly description of the data source.
40    #[builder(default, setter(into, strip_option))]
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub description: Option<String>,
43
44    /// Optional configuration for the data source. If the data source is
45    /// proxied through an FPD instance, the config will not be exposed to
46    /// outside clients.
47    #[builder(default, setter(into, strip_option))]
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub config: Option<Map<String, Value>>,
50
51    /// The data source status as reported by the FPD instance. Will be `None`
52    /// for direct data sources.
53    #[builder(default, setter(strip_option))]
54    #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
55    pub status: Option<DataSourceStatus>,
56
57    /// Timestamp at which the data source was created.
58    #[builder(setter(into))]
59    pub created_at: Timestamp,
60
61    /// Timestamp at which the data source or its config was last updated.
62    #[builder(setter(into))]
63    pub updated_at: Timestamp,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Display)]
67#[cfg_attr(
68    feature = "fp-bindgen",
69    derive(Serializable),
70    fp(rust_module = "fiberplane_models::data_sources")
71)]
72#[non_exhaustive]
73#[serde(tag = "status", content = "error", rename_all = "snake_case")]
74pub enum DataSourceStatus {
75    Connected,
76    Error(Error),
77}
78
79#[derive(Debug, Deserialize, Serialize, Clone, TypedBuilder)]
80#[non_exhaustive]
81#[serde(rename_all = "camelCase")]
82pub struct NewDataSource {
83    pub name: Name,
84
85    #[builder(setter(into))]
86    pub provider_type: String,
87
88    #[serde(default)]
89    pub protocol_version: u8,
90
91    #[builder(default, setter(into, strip_option))]
92    pub description: Option<String>,
93
94    #[builder(default, setter(into))]
95    pub config: Map<String, Value>,
96}
97
98#[derive(Debug, Default, Deserialize, Serialize, Clone, TypedBuilder)]
99#[non_exhaustive]
100#[serde(rename_all = "camelCase")]
101pub struct UpdateDataSource {
102    #[builder(default, setter(into, strip_option))]
103    pub description: Option<String>,
104
105    #[builder(default, setter(into, strip_option))]
106    pub config: Option<Map<String, Value>>,
107}
108
109#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, TypedBuilder)]
110#[cfg_attr(
111    feature = "fp-bindgen",
112    derive(Serializable),
113    fp(rust_module = "fiberplane_models::data_sources")
114)]
115#[non_exhaustive]
116#[serde(rename_all = "camelCase")]
117pub struct SelectedDataSource {
118    /// The name of the selected data source
119    pub name: Name,
120
121    /// If this is a proxy data source, the name of the proxy
122    #[builder(default, setter(strip_option))]
123    #[serde(default, skip_serializing_if = "Option::is_none")]
124    pub proxy_name: Option<Name>,
125}
126
127pub type ProviderType = String;
128
129/// This is a map from provider type to the selected data source for that type.
130pub type SelectedDataSources = BTreeMap<ProviderType, SelectedDataSource>;
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use pretty_assertions::assert_eq;
136    use serde_json::json;
137
138    #[test]
139    fn status_serialization() {
140        let serialized = serde_json::to_value(&DataSourceStatus::Connected).unwrap();
141        assert_eq!(serialized, json!({"status":"connected"}));
142
143        assert_eq!(
144            serde_json::to_value(&DataSourceStatus::Error(Error::NotFound)).unwrap(),
145            json!({
146                "status": "error",
147                "error": {
148                    "type": "not_found",
149                }
150            })
151        );
152    }
153}