fundaia 0.53.0

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

pub struct NewServer<'a> {
    pub name: &'a str,
    pub connection: &'a str,
    pub address: &'a str,
    pub identity: Option<&'a str>,
    pub region: Option<&'a str>,
}

fn server_path(server: &str) -> String {
    format!(
        "/api/infra/servers/{}",
        utf8_percent_encode(server, NON_ALPHANUMERIC)
    )
}

fn placement_path(project_id: &str, environment: &str) -> String {
    format!(
        "/api/infra/projects/{project_id}/environments/{}/server",
        utf8_percent_encode(environment, NON_ALPHANUMERIC)
    )
}

impl ApiClient {
    pub async fn servers(&self) -> Result<Answer<ServersPage>> {
        self.get_answer("/api/infra/servers").await
    }

    pub async fn server(&self, server: &str) -> Result<Answer<ServerDetail>> {
        self.get_answer(&server_path(server)).await
    }

    pub async fn add_server(&self, draft: &NewServer<'_>) -> Result<Answer<ServerPage>> {
        let mut body = serde_json::json!({
            "name": draft.name,
            "connection": draft.connection,
            "address": draft.address,
        });
        if let Some(identity) = draft.identity {
            body["identity"] = serde_json::json!(identity);
        }
        if let Some(region) = draft.region {
            body["region"] = serde_json::json!(region);
        }
        self.post_answer("/api/infra/servers", &body).await
    }

    pub async fn cordon_server(&self, server: &str, cordoned: bool) -> Result<Answer<ServerPage>> {
        let verb = if cordoned { "cordon" } else { "uncordon" };
        self.post_answer(
            &format!("{}/{verb}", server_path(server)),
            &serde_json::json!({}),
        )
        .await
    }

    pub async fn set_server_failover(
        &self,
        server: &str,
        failover: bool,
    ) -> Result<Answer<ServerPage>> {
        self.answer(
            Method::PATCH,
            &server_path(server),
            Some(&serde_json::json!({ "failover": failover })),
        )
        .await
    }

    pub async fn plan_drain(&self, server: &str) -> Result<Answer<DrainPlan>> {
        self.get_answer(&format!("{}/drain", server_path(server)))
            .await
    }

    pub async fn drain_server(&self, server: &str) -> Result<Answer<DrainPlan>> {
        self.post_answer(
            &format!("{}/drain", server_path(server)),
            &serde_json::json!({}),
        )
        .await
    }

    pub async fn remove_server(
        &self,
        server: &str,
        confirmation: &str,
    ) -> Result<Answer<RemovedServer>> {
        self.answer(
            Method::DELETE,
            &format!(
                "{}?confirm={}",
                server_path(server),
                utf8_percent_encode(confirmation, NON_ALPHANUMERIC)
            ),
            None::<&()>,
        )
        .await
    }

    pub async fn environment_server(
        &self,
        project_id: &str,
        environment: &str,
    ) -> Result<Answer<EnvironmentPlacement>> {
        self.get_answer(&placement_path(project_id, environment))
            .await
    }

    pub async fn move_environment(
        &self,
        project_id: &str,
        environment: &str,
        server: &str,
    ) -> Result<Answer<MovePage>> {
        self.answer(
            Method::PUT,
            &placement_path(project_id, environment),
            Some(&serde_json::json!({ "server": server })),
        )
        .await
    }

    pub async fn environment_move(&self, move_id: &str) -> Result<Answer<MovePage>> {
        self.get_answer(&format!(
            "/api/infra/moves/{}",
            utf8_percent_encode(move_id, NON_ALPHANUMERIC)
        ))
        .await
    }
}