fundaia 0.52.3

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

pub struct NewEnvironment<'a> {
    pub name: &'a str,
    pub copy_from: Option<&'a str>,
    pub empty: bool,
    pub deploy: bool,
}

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

    pub async fn create_environment(
        &self,
        project_id: &str,
        draft: &NewEnvironment<'_>,
    ) -> Result<Answer<CreatedEnvironment>> {
        self.post_answer(
            &format!("/api/infra/projects/{project_id}/environments"),
            &environment_body(draft),
        )
        .await
    }

    pub async fn rename_environment(
        &self,
        project_id: &str,
        environment: &str,
        name: &str,
    ) -> Result<Answer<EnvironmentPage>> {
        self.answer(
            Method::PATCH,
            &format!(
                "/api/infra/projects/{project_id}/environments/{}",
                utf8_percent_encode(environment, NON_ALPHANUMERIC)
            ),
            Some(&serde_json::json!({ "name": name })),
        )
        .await
    }

    pub async fn delete_environment(
        &self,
        project_id: &str,
        environment: &str,
        confirmation: &str,
    ) -> Result<()> {
        self.delete(&format!(
            "/api/infra/projects/{project_id}/environments/{}?confirm={}",
            utf8_percent_encode(environment, NON_ALPHANUMERIC),
            utf8_percent_encode(confirmation, NON_ALPHANUMERIC)
        ))
        .await
    }

    pub async fn copy_service_to_environment(
        &self,
        project_id: &str,
        environment: &str,
        from: &str,
        deploy: bool,
    ) -> Result<Answer<CopiedServicePage>> {
        let mut body = serde_json::Map::new();
        body.insert("from".into(), from.into());
        if !deploy {
            body.insert("deploy".into(), false.into());
        }

        self.post_answer(
            &format!(
                "/api/infra/projects/{project_id}/environments/{}/services",
                utf8_percent_encode(environment, NON_ALPHANUMERIC)
            ),
            &serde_json::Value::Object(body),
        )
        .await
    }
}

fn environment_body(draft: &NewEnvironment<'_>) -> serde_json::Value {
    let mut body = serde_json::Map::new();
    body.insert("name".into(), draft.name.into());
    if draft.empty {
        body.insert("copyFrom".into(), serde_json::Value::Null);
    } else if let Some(source) = draft.copy_from {
        body.insert("copyFrom".into(), source.into());
    }
    if !draft.deploy {
        body.insert("deploy".into(), false.into());
    }
    serde_json::Value::Object(body)
}

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

    fn named(name: &str) -> NewEnvironment<'_> {
        NewEnvironment {
            name,
            copy_from: None,
            empty: false,
            deploy: true,
        }
    }

    #[test]
    fn it_should_leave_the_source_to_the_server_when_none_is_named() {
        assert_eq!(
            environment_body(&named("staging")),
            serde_json::json!({ "name": "staging" })
        );
    }

    #[test]
    fn it_should_ask_for_an_empty_environment_with_a_null_source() {
        let draft = NewEnvironment {
            empty: true,
            ..named("sandbox")
        };
        assert_eq!(
            environment_body(&draft),
            serde_json::json!({ "name": "sandbox", "copyFrom": null })
        );
    }

    #[test]
    fn it_should_say_only_no_about_deploying() {
        let draft = NewEnvironment {
            deploy: false,
            copy_from: Some("qa"),
            ..named("staging")
        };
        assert_eq!(
            environment_body(&draft),
            serde_json::json!({ "name": "staging", "copyFrom": "qa", "deploy": false })
        );
    }
}