fundaia 0.55.0

Command line for the Fundaia deployment platform: projects, services, variables, deployments, logs and metrics
use super::*;

pub struct NewWebhook<'a> {
    pub url: &'a str,
    pub name: Option<&'a str>,
    pub format: Option<&'a str>,
    pub events: &'a [String],
}

pub struct WebhookChange<'a> {
    pub name: Option<&'a str>,
    pub events: Option<&'a [String]>,
    pub enabled: Option<bool>,
}

impl ApiClient {
    pub async fn webhooks(&self, project_id: &str) -> Result<Answer<WebhooksPage>> {
        self.get_answer(&format!("/api/infra/projects/{project_id}/webhooks"))
            .await
    }

    pub async fn create_webhook(
        &self,
        project_id: &str,
        draft: &NewWebhook<'_>,
    ) -> Result<Answer<CreatedWebhook>> {
        self.post_answer(
            &format!("/api/infra/projects/{project_id}/webhooks"),
            &webhook_body(draft),
        )
        .await
    }

    pub async fn update_webhook(
        &self,
        project_id: &str,
        webhook: &str,
        change: &WebhookChange<'_>,
    ) -> Result<Answer<WebhookPage>> {
        self.answer(
            Method::PATCH,
            &format!(
                "/api/infra/projects/{project_id}/webhooks/{}",
                utf8_percent_encode(webhook, NON_ALPHANUMERIC)
            ),
            Some(&change_body(change)),
        )
        .await
    }

    pub async fn delete_webhook(&self, project_id: &str, webhook: &str) -> Result<()> {
        self.delete(&format!(
            "/api/infra/projects/{project_id}/webhooks/{}",
            utf8_percent_encode(webhook, NON_ALPHANUMERIC)
        ))
        .await
    }

    pub async fn test_webhook(
        &self,
        project_id: &str,
        webhook: &str,
    ) -> Result<Answer<WebhookTestPage>> {
        self.post_answer(
            &format!(
                "/api/infra/projects/{project_id}/webhooks/{}/test",
                utf8_percent_encode(webhook, NON_ALPHANUMERIC)
            ),
            &serde_json::json!({}),
        )
        .await
    }
}

fn webhook_body(draft: &NewWebhook<'_>) -> serde_json::Value {
    let mut body = serde_json::Map::new();
    body.insert("url".into(), draft.url.into());
    if let Some(name) = draft.name {
        body.insert("name".into(), name.into());
    }
    if let Some(format) = draft.format {
        body.insert("format".into(), format.into());
    }
    if !draft.events.is_empty() {
        body.insert("events".into(), draft.events.into());
    }
    serde_json::Value::Object(body)
}

fn change_body(change: &WebhookChange<'_>) -> serde_json::Value {
    let mut body = serde_json::Map::new();
    if let Some(name) = change.name {
        body.insert("name".into(), name.into());
    }
    if let Some(events) = change.events {
        body.insert("events".into(), events.into());
    }
    if let Some(enabled) = change.enabled {
        body.insert("enabled".into(), enabled.into());
    }
    serde_json::Value::Object(body)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_should_leave_the_format_and_events_to_the_server_when_none_is_given() {
        let draft = NewWebhook {
            url: "https://hooks.slack.com/services/x",
            name: None,
            format: None,
            events: &[],
        };
        assert_eq!(
            webhook_body(&draft),
            serde_json::json!({ "url": "https://hooks.slack.com/services/x" })
        );
    }

    #[test]
    fn it_should_send_only_what_changes() {
        let change = WebhookChange {
            name: None,
            events: None,
            enabled: Some(false),
        };
        assert_eq!(
            change_body(&change),
            serde_json::json!({ "enabled": false })
        );
    }
}