orign 0.2.3

A globally distributed container orchestrator
Documentation
use crate::config::CONFIG;
use crate::models::V1UserProfile;
use anyhow::{anyhow, Result};
use chrono::prelude::*;
use nebulous::models::{V1AgentKey, V1CreateAgentKeyRequest};
use reqwest::Client;
use rsb_derive::Builder;
use serde::{Deserialize, Serialize};
use slack_morphism::prelude::*;
use std::env;
use std::sync::Arc;
use tracing::info;

// For HTTP calls
use reqwest::Client as ReqwestClient;
use thiserror::Error;

pub async fn get_orign_agent_key(
    user_profile: &V1UserProfile,
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
    let create_agent_key_request = V1CreateAgentKeyRequest {
        agent_id: "orign".to_string(),
        name: format!("orign-{}", uuid::Uuid::new_v4()),
        duration: 604800,
    };

    let auth_server_url = CONFIG.auth_server_url.clone();

    let agent_key = create_agent_key(
        &auth_server_url,
        &user_profile.token.clone().unwrap(),
        create_agent_key_request,
    )
    .await
    .unwrap();

    Ok(agent_key.key.unwrap())
}

/// Creates a new agent key by calling the `/v1/agent/keys` endpoint
///
/// # Arguments
///
/// * `client` - The HTTP client to use for the request
/// * `base_url` - The base URL of the API
/// * `api_key` - The API key to use for authentication
/// * `request` - The request parameters for creating the agent key
///
/// # Returns
///
/// Returns the created agent key on success, or an error if the request fails
pub async fn create_agent_key(
    base_url: &str,
    api_key: &str,
    request: V1CreateAgentKeyRequest,
) -> Result<V1AgentKey> {
    let client = Client::new();
    // Change return type to anyhow's Result
    let url = format!("{}/v1/agent/keys", base_url);

    let response = client
        .post(&url)
        .header("Authorization", format!("Bearer {}", api_key))
        .json(&request)
        .send()
        .await?;

    if !response.status().is_success() {
        let status = response.status();
        let error_text = response.text().await?;
        return Err(anyhow!("API error {}: {}", status.as_u16(), error_text));
    }

    let agent_key: V1AgentKey = response.json().await?;
    info!("Agent key created: {:?}", agent_key);
    Ok(agent_key)
}

// This function is analogous to your Python "get_agent_token"
pub async fn get_agent_token_root(
    agent_id: &str,
    name: &str,
    org: Option<&str>,
    role: Option<&str>,
    user_id: Option<&str>,
) -> Result<String> {
    let root_auth_token = match env::var("ROOT_AUTH_TOKEN") {
        Ok(token) => token,
        Err(_) => {
            return Err(anyhow!("ROOT_AUTH_TOKEN is not set"));
        }
    };
    let agentsea_auth_url = CONFIG.auth_server_url.clone();

    let url = format!("{}/v1/admin/agent/keys", agentsea_auth_url);
    let mut body = serde_json::json!({
        "agent_id": agent_id,
        "name": name,
        "duration": 3600,
        "org": org,
        "role": role,
    });

    if let Some(u) = user_id {
        body["user_id"] = serde_json::Value::String(u.to_string());
    }

    let client = ReqwestClient::new();
    let resp = client
        .post(&url)
        .header("Authorization", format!("Bearer {}", root_auth_token))
        .json(&body)
        .send()
        .await?
        .error_for_status()?
        .json::<serde_json::Value>()
        .await?;

    // Extract the "key" field
    let key = resp["key"]
        .as_str()
        .ok_or_else(|| anyhow!("Key not found in agentsea auth response"))?
        .to_string();

    Ok(key)
}