Skip to main content

pipedash_plugin_api/
builders.rs

1use serde_json::Value;
2
3use crate::history::RunHistoryPolicy;
4use crate::metadata::{
5    PluginCapabilities,
6    PluginMetadata,
7};
8use crate::presentation::PluginPresentation;
9use crate::schema::{
10    ConfigField,
11    ConfigFieldType,
12    ConfigSchema,
13    ConfigSection,
14    TableSchema,
15};
16use crate::types::{
17    Feature,
18    Permission,
19};
20
21const HTTP_URL_REGEX: &str = r"^https?://.*";
22const HTTP_URL_MESSAGE: &str = "Must be a valid HTTP or HTTPS URL";
23const KUBECONFIG_CONTENT_DESCRIPTION: &str = "Paste the kubeconfig YAML instead of using a file path, for example on iOS and Android where no kubeconfig file exists. When set, it is used instead of the path above and is stored with your other credentials. Use token or client certificate authentication: exec credential plugins (aws, gke-gcloud-auth-plugin, kubelogin) are not supported on iOS and Android.";
24
25impl ConfigField {
26    fn with_type(
27        key: &str, section: ConfigSection, label: &str, field_type: ConfigFieldType,
28    ) -> Self {
29        Self {
30            key: key.to_string(),
31            section,
32            label: label.to_string(),
33            description: None,
34            field_type,
35            required: false,
36            default_value: None,
37            options: None,
38            validation_regex: None,
39            validation_message: None,
40        }
41    }
42
43    pub fn text(key: &str, section: ConfigSection, label: &str) -> Self {
44        Self::with_type(key, section, label, ConfigFieldType::Text)
45    }
46
47    pub fn textarea(key: &str, section: ConfigSection, label: &str) -> Self {
48        Self::with_type(key, section, label, ConfigFieldType::TextArea)
49    }
50
51    pub fn password(key: &str, section: ConfigSection, label: &str) -> Self {
52        Self::with_type(key, section, label, ConfigFieldType::Password)
53    }
54
55    pub fn boolean(key: &str, section: ConfigSection, label: &str) -> Self {
56        Self::with_type(key, section, label, ConfigFieldType::Boolean)
57    }
58
59    pub fn select(key: &str, section: ConfigSection, label: &str, options: &[&str]) -> Self {
60        Self {
61            options: Some(options.iter().map(|option| option.to_string()).collect()),
62            ..Self::with_type(key, section, label, ConfigFieldType::Select)
63        }
64    }
65
66    pub fn description(mut self, description: &str) -> Self {
67        self.description = Some(description.to_string());
68        self
69    }
70
71    pub fn required(mut self) -> Self {
72        self.required = true;
73        self
74    }
75
76    pub fn default_text(mut self, value: &str) -> Self {
77        self.default_value = Some(Value::String(value.to_string()));
78        self
79    }
80
81    pub fn default_bool(mut self, value: bool) -> Self {
82        self.default_value = Some(Value::Bool(value));
83        self
84    }
85
86    pub fn validation(mut self, regex: &str, message: &str) -> Self {
87        self.validation_regex = Some(regex.to_string());
88        self.validation_message = Some(message.to_string());
89        self
90    }
91
92    pub fn http_url_validation(self) -> Self {
93        self.validation(HTTP_URL_REGEX, HTTP_URL_MESSAGE)
94    }
95
96    pub fn token(label: &str, description: &str) -> Self {
97        Self::password("token", ConfigSection::Authentication, label)
98            .description(description)
99            .required()
100    }
101
102    pub fn insecure_tls() -> Self {
103        Self::boolean(
104            "insecure",
105            ConfigSection::Connection,
106            "Skip TLS Verification",
107        )
108        .description("Skip TLS certificate verification (useful for self-signed certificates)")
109        .default_bool(false)
110    }
111
112    pub fn kubeconfig_content(key: &str, label: &str) -> Self {
113        Self::textarea(key, ConfigSection::Authentication, label)
114            .description(KUBECONFIG_CONTENT_DESCRIPTION)
115    }
116}
117
118impl Permission {
119    pub fn new(name: &str, description: &str, required: bool) -> Self {
120        Self {
121            name: name.to_string(),
122            description: description.to_string(),
123            required,
124        }
125    }
126}
127
128impl Feature {
129    pub fn new(id: &str, name: &str, description: &str, required_permissions: &[&str]) -> Self {
130        Self {
131            id: id.to_string(),
132            name: name.to_string(),
133            description: description.to_string(),
134            required_permissions: required_permissions
135                .iter()
136                .map(|permission| permission.to_string())
137                .collect(),
138        }
139    }
140}
141
142impl PluginCapabilities {
143    pub fn standard() -> Self {
144        Self {
145            trigger: true,
146            cancel: true,
147            logs: true,
148            uses_http_proxy: true,
149            ..Self::default()
150        }
151    }
152}
153
154impl PluginMetadata {
155    pub fn new(
156        name: &str, config_schema: ConfigSchema, table_schema: TableSchema,
157        capabilities: PluginCapabilities,
158    ) -> Self {
159        Self {
160            name: name.to_string(),
161            provider_type: String::new(),
162            version: String::new(),
163            description: String::new(),
164            author: None,
165            icon: None,
166            config_schema,
167            table_schema,
168            capabilities,
169            required_permissions: Vec::new(),
170            features: Vec::new(),
171            run_history: RunHistoryPolicy::default(),
172            token_prefixes: Vec::new(),
173            presentation: PluginPresentation::new(name),
174        }
175    }
176
177    pub fn with_permissions(mut self, permissions: Vec<Permission>) -> Self {
178        self.required_permissions = permissions;
179        self
180    }
181
182    pub fn with_features(mut self, features: Vec<Feature>) -> Self {
183        self.features = features;
184        self
185    }
186}
187
188#[cfg(test)]
189mod tests;