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