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
use super::error::Error as CdsError;
use super::models;

use std::collections::HashMap;

use reqwest::Client as HttpClient;
use serde::de::DeserializeOwned;
use serde::Serialize;

const SESSION_TOKEN_HEADER: &'static str = "Session-Token";

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(default)]
pub struct Client<'a> {
    pub name: &'a str, //Useful for multi instance to give a name to your instance
    pub host: &'a str,
    pub username: &'a str,
    pub token: &'a str,
    pub insecure_skip_verify_tls: bool,
}

impl<'a> Client<'a> {
    pub fn new<T: Into<&'a str>>(host: T, username: T, token: T) -> Self {
        let host: &'a str = host.into();
        Client {
            host: host,
            username: username.into(),
            token: token.into(),
            insecure_skip_verify_tls: !host.starts_with("https"),
            ..Default::default()
        }
    }

    pub fn status(&self) -> Result<models::Status, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), "/mon/status".to_string(), body)
    }

    pub fn config(&self) -> Result<HashMap<String, String>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), "/config/user".to_string(), body)
    }

    pub fn me(&self) -> Result<models::User, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), format!("/user/{}", self.username), body)
    }

    pub fn broadcasts(&self) -> Result<Vec<models::Broadcast>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), "/broadcast".to_string(), body)
    }

    pub fn projects(&self) -> Result<Vec<models::Project>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), "/project".to_string(), body)
    }

    pub fn applications(&self, project_key: &str) -> Result<Vec<models::Application>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            format!("/project/{}/applications", project_key),
            body,
        )
    }

    pub fn application(
        &self,
        project_key: &str,
        application_name: &str,
    ) -> Result<models::Application, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            format!("/project/{}/application/{}", project_key, application_name),
            body,
        )
    }

    pub fn workflows(&self, project_key: &str) -> Result<Vec<models::Workflow>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            format!("/project/{}/workflows", project_key),
            body,
        )
    }

    pub fn workflow(
        &self,
        project_key: &str,
        workflow_name: &str,
    ) -> Result<models::Workflow, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            format!("/project/{}/workflows/{}", project_key, workflow_name),
            body,
        )
    }

    pub fn queue_count(&self) -> Result<models::QueueCount, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            "/queue/workflows/count".to_string(),
            body,
        )
    }

    pub fn bookmarks(&self) -> Result<Vec<models::Bookmark>, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json("GET".to_string(), String::from("/bookmarks"), body)
    }

    pub fn last_run(
        &self,
        project_key: &str,
        workflow_name: &str,
    ) -> Result<models::WorkflowRun, CdsError> {
        let body: Vec<u8> = vec![];
        self.stream_json(
            "GET".to_string(),
            format!(
                "/project/{}/workflows/{}/runs/latest",
                project_key, workflow_name
            ),
            body,
        )
    }

    pub fn stream_json<T: Serialize, U: DeserializeOwned>(
        &self,
        method: String,
        path: String,
        body: T,
    ) -> Result<U, CdsError> {
        let url = format!("{}{}", self.host, path);
        let mut resp_http = HttpClient::new()
            .request(reqwest::Method::from_bytes(method.as_bytes())?, &url)
            .header(reqwest::header::CONTENT_TYPE, "application/json")
            .header(reqwest::header::USER_AGENT, "CDS/sdk")
            .header("X-Requested-With", "X-CDS-SDK")
            .header(SESSION_TOKEN_HEADER, self.token)
            .basic_auth(self.username, Some(self.token))
            .json(&body)
            .send()?;

        if resp_http.status().as_u16() > 400u16 {
            let mut err: CdsError = resp_http.json().map_err(CdsError::from)?;
            err.status = resp_http.status().as_u16();
            return Err(err);
        }

        resp_http.json().map_err(CdsError::from)
    }
}