openwhisk_rust/api/
rule.rs

1use derive_new::new;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5use super::{HttpMethods, KeyValue, Service, NAMESPACE_ENDPOINT, RULES_ENDPOINT};
6use crate::client::Context;
7
8/// Representation of rule Service
9#[derive(new, Default, Debug, Clone)]
10pub struct RuleService<T> {
11    /// A rule service must have a client to handle http request
12    client: T,
13    /// A rule service uses the context which sets openwhisk properties
14    context: Context,
15}
16#[derive(Debug, Clone, Serialize, Deserialize, Default)]
17pub struct Rule {
18    pub name: String,
19    pub trigger: String,
20    pub action: String,
21}
22
23impl Rule {
24    fn body(namespace: String, rule: &Rule) -> Result<Value, serde_json::Error> {
25        let trigger = format!("/{}/{}/", namespace, rule.trigger);
26
27        let action = format!("/{}/{}/", namespace, rule.action);
28
29        serde_json::to_value(Rule {
30            name: rule.name.clone(),
31            trigger,
32            action,
33        })
34    }
35}
36
37/// Representation of Rule
38#[derive(Debug, Clone, Serialize, Deserialize, Default)]
39pub struct RuleResponse {
40    /// A rule must have a namspace where it exists
41    #[serde(default)]
42    pub namespace: String,
43    /// A rule must have a name to represent it
44    #[serde(default)]
45    pub name: String,
46    /// A action must have a versioning
47    #[serde(default)]
48    pub version: String,
49    /// Keyvalue pair for annotate rules
50    #[serde(default)]
51    pub annotations: Vec<KeyValue>,
52    /// The execution status of the rule
53    #[serde(default)]
54    pub status: String,
55    /// A rule must have a trigger mapped to it
56    #[serde(default)]
57    pub trigger: Value,
58    /// A rule must have an action to pass the trigger
59    #[serde(default)]
60    pub action: Value,
61    /// Toggle to publish rule
62    #[serde(default)]
63    pub publish: bool,
64    /// Updated version count of actions
65    #[serde(default)]
66    pub updated: i64,
67}
68
69/// Representation of rules list options
70#[derive(new, Debug, Clone, Serialize, Deserialize, Default)]
71pub struct RuleListOptions {
72    /// The limit for the required rules.
73    pub limit: i64,
74    /// The counts to be skipped.
75    pub skip: i64,
76    /// Toggle to get documents.
77    pub docs: bool,
78}
79
80impl RuleResponse {
81    fn set_status(state: String) -> Self {
82        Self {
83            status: state,
84            ..Default::default()
85        }
86    }
87}
88
89impl<T> RuleService<T>
90where
91    T: Service,
92{
93    /// Returns a list of Rules
94    pub fn list(&self) -> Result<Vec<RuleResponse>, String> {
95        let url = format!(
96            "{}/api/v1/{}/{}/{}",
97            self.context.host(),
98            NAMESPACE_ENDPOINT,
99            self.context.namespace(),
100            RULES_ENDPOINT,
101        );
102
103        let auth = self.context.auth();
104        let user = auth.0;
105        let pass = auth.1;
106
107        let request = match self.client.new_request(
108            Some(HttpMethods::GET),
109            url.as_str(),
110            Some((user, pass)),
111            None,
112        ) {
113            Ok(request) => request,
114            Err(error) => return Err(error),
115        };
116
117        match self.client.invoke_request(request) {
118            Ok(x) => match serde_json::from_value(x) {
119                Ok(rules) => Ok(rules),
120                Err(err) => Err(format!("Failed to deserailize Rules {}", err)),
121            },
122            Err(x) => Err(format!("Failed to fetch the list of Rules {}", x)),
123        }
124    }
125
126    /// Inserts a rule
127    ///
128    /// # Arguments
129    /// * `rule` - The rule ro be inserted
130    /// * `overwrite`  - Toggle to get overwrtite an existing rule
131    ///  
132    pub fn insert(&self, rule: &Rule, overwrite: bool) -> Result<RuleResponse, String> {
133        let url = format!(
134            "{}/api/v1/{}/{}/{}/{}?overwrite={}",
135            self.context.host(),
136            NAMESPACE_ENDPOINT,
137            self.context.namespace(),
138            RULES_ENDPOINT,
139            rule.name,
140            overwrite
141        );
142
143        let auth = self.context.auth();
144        let user = auth.0;
145        let pass = auth.1;
146
147        let body = match Rule::body(self.context.namespace().to_string(), rule) {
148            Ok(body) => body,
149            Err(error) => return Err(format!("Failed deserailize body {}", error)),
150        };
151
152        let request = match self.client.new_request(
153            Some(HttpMethods::PUT),
154            url.as_str(),
155            Some((user, pass)),
156            Some(body),
157        ) {
158            Ok(request) => request,
159            Err(error) => return Err(error),
160        };
161
162        match self.client.invoke_request(request) {
163            Ok(x) => match serde_json::from_value(x) {
164                Ok(actions) => Ok(actions),
165                Err(err) => Err(format!("Failed to deserailize rule {}", err)),
166            },
167            Err(x) => Err(format!("Failed to create rule {}", x)),
168        }
169    }
170
171    /// To get the properties of the rule
172    ///
173    /// # Arguments
174    /// * `rule_name` - String slice that holds rule name
175    ///
176    pub fn get(&self, rule_name: &str) -> Result<RuleResponse, String> {
177        let url = format!(
178            "{}/api/v1/{}/{}/{}/{}",
179            self.context.host(),
180            NAMESPACE_ENDPOINT,
181            self.context.namespace(),
182            RULES_ENDPOINT,
183            rule_name
184        );
185
186        let auth = self.context.auth();
187        let user = auth.0;
188        let pass = auth.1;
189
190        let request = match self.client.new_request(
191            Some(HttpMethods::GET),
192            url.as_str(),
193            Some((user, pass)),
194            None,
195        ) {
196            Ok(request) => request,
197            Err(error) => return Err(error),
198        };
199
200        match self.client.invoke_request(request) {
201            Ok(x) => match serde_json::from_value(x) {
202                Ok(actions) => Ok(actions),
203                Err(err) => Err(format!("Failed to deserailize rule {}", err)),
204            },
205            Err(x) => Err(format!("Failed to get rule properties{}", x)),
206        }
207    }
208
209    /// Deletes an already existing rule
210    ///
211    /// # Arguments
212    /// * `rule_name` - String slice that holds rule name
213    ///
214    pub fn delete(&self, rule_name: &str) -> Result<RuleResponse, String> {
215        let url = format!(
216            "{}/api/v1/{}/{}/{}/{}",
217            self.context.host(),
218            NAMESPACE_ENDPOINT,
219            self.context.namespace(),
220            RULES_ENDPOINT,
221            rule_name
222        );
223
224        let auth = self.context.auth();
225        let user = auth.0;
226        let pass = auth.1;
227
228        let request = match self.client.new_request(
229            Some(HttpMethods::PUT),
230            url.as_str(),
231            Some((user, pass)),
232            None,
233        ) {
234            Ok(request) => request,
235            Err(error) => return Err(error),
236        };
237
238        match self.client.invoke_request(request) {
239            Ok(x) => match serde_json::from_value(x) {
240                Ok(actions) => Ok(actions),
241                Err(err) => Err(format!("Failed to deserailize rule {}", err)),
242            },
243            Err(x) => Err(format!("Failed to get rule properties{}", x)),
244        }
245    }
246
247    /// Sets the state of the rule
248    ///
249    /// # Arguments
250    /// * `rule_name` - String slice that holds rule name
251    /// * 'state' - Execution state of the rule    
252    ///
253    pub fn setstate(&self, rule_name: &str, state: &str) -> Result<RuleResponse, String> {
254        let state = state.to_lowercase();
255
256        if state != "active" && state != "inactive" {
257            Err("Invalid setstate options".to_string())
258        } else {
259            let url = format!(
260                "{}/api/v1/{}/{}/{}/{}",
261                self.context.host(),
262                NAMESPACE_ENDPOINT,
263                self.context.namespace(),
264                RULES_ENDPOINT,
265                rule_name
266            );
267
268            let auth = self.context.auth();
269            let user = auth.0;
270            let pass = auth.1;
271
272            let setstate = RuleResponse::set_status(state);
273
274            let body = match serde_json::to_value(setstate) {
275                Ok(body) => body,
276                Err(error) => return Err(format!("Failed deserailize body {}", error)),
277            };
278
279            let request = match self.client.new_request(
280                Some(HttpMethods::POST),
281                url.as_str(),
282                Some((user, pass)),
283                Some(body),
284            ) {
285                Ok(request) => request,
286                Err(error) => return Err(error),
287            };
288
289            match self.client.invoke_request(request) {
290                Ok(x) => match serde_json::from_value(x) {
291                    Ok(actions) => Ok(actions),
292                    Err(err) => Err(format!("Failed to deserailize rule {}", err)),
293                },
294                Err(x) => Err(format!("Failed to SetState for Rule {}", x)),
295            }
296        }
297    }
298}