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;