1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
use http::StatusCode;
use serde::{Deserialize, Serialize};
use std::env;
use std::fmt::Debug;

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct WhiskError {
    pub code: String,
    pub error: String,
}
/// Representation  of OpenWhisk Properties
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct WskProperties {
    /// Auth_token - `:` seperated username and passeord
    pub auth_token: String,
    /// Api Host to interact with Openwhisk API
    pub host: String,
    /// Version
    #[serde(default = "default")]
    pub version: String,
    /// Toggle to set secure or insecure connection
    pub insecure: bool,
    /// Namespace for the endpoint
    pub namespace: String,
    /// Verbose - Toggle to enable it
    #[serde(default = "bool::default")]
    pub verbose: bool,
    /// Debug - Toggle to ennable it
    #[serde(default = "bool::default")]
    pub debug: bool,
}

fn default() -> String {
    "v1".to_string()
}

/// Context which used to set whisk properties
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct Context {
    /// API Host Url
    host: String,
    /// Namespace where actions,triggrs, rules exists
    namespace: String,
    /// Toggle to make secure and inscure connection (Set true or false)
    insecure: bool,
    /// Username for Authentication which is set by auth_token
    username: String,
    /// Passwod for Authentication which is set by auth_token
    password: String,
    /// Verion
    version: String,
}

impl WskProperties {
    /// New Creates Openwhisk properties
    ///
    /// # Arguments
    /// * `auth_token`  - The authorization token
    /// * `host`        - The API url
    /// * `insecure`    - Toggle for secure connection
    /// * `namespace`   - Name of the namespace
    ///
    /// # Example
    ///
    /// ```
    /// use openwhisk_rust::WskProperties;
    ///
    /// let new_wsk_property = WskProperties::new(
    /// "your:auth_token".to_string(),
    /// "host".to_string(),
    /// true,
    /// "namespace".to_string()
    /// );
    ///
    /// ```
    pub fn new(auth_token: String, host: String, insecure: bool, namespace: String) -> Self {
        Self {
            auth_token,
            host,
            insecure,
            namespace,
            version: default(),
            ..Default::default()
        }
    }

    /// To set Verbose, Version and Debug
    ///
    /// # Arguments
    /// * `debug`   - Bool to toggle debug
    /// * `verbose` - Bool to toggle verbose
    /// * `version` - Version of wsk properties
    ///
    /// # Example
    ///
    /// ```
    /// use openwhisk_rust::WskProperties;
    ///
    /// let new_wsk_property = WskProperties::new(
    /// "your:auth_token".to_string(),
    /// "host".to_string(),
    /// true,
    /// "namespace".to_string()
    /// );
    ///
    /// new_wsk_property.set_verbose_debug_version(false,false,"v2".to_string());
    ///
    /// ```
    pub fn set_verbose_debug_version(&self, debug: bool, verbose: bool, version: String) -> Self {
        Self {
            auth_token: self.auth_token.clone(),
            host: self.host.clone(),
            version,
            insecure: self.insecure,
            namespace: self.namespace.clone(),
            verbose,
            debug,
        }
    }
}

/// Trait Openwhisk
pub trait OpenWhisk {
    type Output;
    /// creates new openwhisk client
    fn new_whisk_client(insecure: Option<bool>) -> Self::Output;
}

impl Context {
    /// Creates and retruns context based on the Whisk Properties supplied
    ///
    /// # Arguments
    /// * `wskprops` - Option of WhiskProperties
    pub fn new(wskprops: Option<&WskProperties>) -> Context {
        let api_key = if env::var("__OW_API_KEY").is_ok() {
            env::var("__OW_API_KEY").unwrap()
        } else {
            match wskprops {
                Some(wskprops) => wskprops.auth_token.clone(),
                None => "test:test".to_string(),
            }
        };
        let auth: Vec<&str> = api_key.split(':').collect();
        let host = if env::var("__OW_API_HOST").is_ok() {
            env::var("__OW_API_HOST").unwrap()
        } else {
            match wskprops {
                Some(wskprops) => wskprops.host.clone(),
                None => "host.docker.internal".to_string(),
            }
        };
        let namespace = if env::var("__OW_NAMESPACE").is_ok() {
            env::var("__OW_NAMESPACE").unwrap()
        } else {
            match wskprops {
                Some(wskprops) => wskprops.namespace.clone(),
                None => "guest".to_string(),
            }
        };

        let connectiontype = match wskprops {
            Some(config) => config.insecure,
            None => false,
        };

        let version = match wskprops {
            Some(config) => config.version.clone(),
            None => "v1".to_string(),
        };

        Context {
            host,
            namespace,
            insecure: connectiontype,
            username: auth[0].to_string(),
            password: auth[1].to_string(),
            version,
        }
    }

    /// Returns namspace value
    pub fn namespace(&self) -> &str {
        &self.namespace
    }

    /// Returns secure value
    pub fn is_secure(&self) -> bool {
        self.insecure
    }

    /// Returns tuple containing username and password
    pub fn auth(&self) -> (&str, &str) {
        (&self.username, &self.password)
    }

    /// Returns host
    pub fn host(&self) -> &str {
        &self.host
    }
}

pub fn whisk_errors(code: StatusCode, message: String) -> String {
    format!(": Error -> [ Status :{}, Message : {} ]", code, message)
}