cloudpub-sdk 3.0.2

Rust SDK for CloudPub - A secure tunnel and service publishing platform
Documentation
//! # Пример CloudPub SDK
//!
//! Этот пример демонстрирует полный рабочий процесс использования CloudPub Rust SDK,
//! включая настройку соединения, публикацию сервисов, управление и очистку.
//!
//! ## Запуск примера
//!
//! ```bash
//! cargo run --example example
//! ```
//!
//! ## Предварительные требования
//!
//! 1. Сервер CloudPub должен быть запущен и доступен
//! 2. Действительные учетные данные (email и пароль)
//! 3. Локальные сервисы для публикации (пример использует localhost порты)

use anyhow::Result;
use cloudpub_sdk::protocol::{Auth, Endpoint, Protocol};
use cloudpub_sdk::Connection;
use std::io;
use std::path::Path;

#[tokio::main]
async fn main() -> Result<()> {
    // ====================================================================
    // ШАГ 1: УСТАНОВЛЕНИЕ СОЕДИНЕНИЯ
    // ====================================================================
    println!("1. Подключение к серверу");

    // Создание соединения с использованием паттерна билдера
    // Билдер позволяет настроить различные параметры соединения
    let mut conn = Connection::builder()
        // Указать путь к пользовательскому файлу конфигурации (опционально)
        // Если не указан, используется системное расположение по умолчанию
        .config_path(Path::new("/tmp/cloudpub.toml"))
        // Установить уровень логирования для отладки
        // Варианты: "trace", "debug", "info", "warn", "error"
        .log_level("info")
        // Включить подробный вывод в stderr для отладки
        // Полезно при разработке, отключите в продакшене
        .verbose(true)
        // Предоставить учетные данные для аутентификации
        // Вы также можете использовать .token() для аутентификации на основе токена
        .credentials("admin@example.com", "test")
        // Установить таймаут для операций (в секундах)
        // Применяется ко всем асинхронным операциям
        .timeout_secs(3)
        // Построить и установить соединение
        // Произойдет аутентификация и ожидание готовности соединения
        .build()
        .await?;

    // ====================================================================
    // ШАГ 2: ПУБЛИКАЦИЯ HTTP СЕРВИСА
    // ====================================================================
    println!("2. Публикация нового HTTP сервиса...");

    // Публикация локального HTTP сервиса для доступа через CloudPub
    let endpoint = conn
        .publish(
            Protocol::Http,                           // Тип протокола
            "localhost:8080".to_string(),             // Локальный адрес для публикации
            Some("Тестовый HTTP сервис".to_string()), // Человекочитаемое имя сервиса
            Some(Auth::None),                         // Метод аутентификации для доступа к сервису
            None,                                     // Без ограничений ACL
            None,                                     // Без пользовательских заголовков
            None,                                     // Без правил фильтрации
        )
        .await?;

    // Endpoint содержит информацию об опубликованном сервисе
    // as_url() возвращает публичный URL, по которому доступен сервис
    println!("  Сервис опубликован: {}", endpoint.as_url());

    // ====================================================================
    // ШАГ 3: ПУБЛИКАЦИЯ TCP СЕРВИСА
    // ====================================================================
    println!("3. Публикация нового TCP сервиса...");

    // TCP сервисы полезны для публикации SSH, баз данных или пользовательских TCP протоколов
    let endpoint = conn
        .publish(
            Protocol::Tcp,                           // TCP протокол
            "localhost:22".to_string(),              // Локальный SSH порт (пример)
            Some("Тестовый TCP сервис".to_string()), // Имя сервиса
            Some(Auth::None),                        // Аутентификация не требуется
            None,                                    // Без ограничений ACL
            None,                                    // Без пользовательских заголовков
            None,                                    // Без правил фильтрации
        )
        .await?;

    println!("  Сервис опубликован: {}", endpoint.as_url());

    // Сохранить GUID для последующих операций
    // GUID уникально идентифицирует этот сервис
    let service_guid = endpoint.guid.clone();

    // ====================================================================
    // ШАГ 4: СПИСОК ВСЕХ СЕРВИСОВ
    // ====================================================================
    println!("4. Список сервисов:");

    // Получить все сервисы, зарегистрированные текущим пользователем
    let services = conn.ls().await?;

    // Отобразить каждый сервис с его GUID и URL
    for service in &services {
        println!("  {}: {}", service.guid, service.as_url());

        // Сервисы также содержат дополнительные метаданные:
        // - service.name: Опциональное человекочитаемое имя
        // - service.status: Текущий статус (работает, остановлен и т.д.)
        // - service.protocol: Тип протокола
        // - service.auth: Метод аутентификации
    }

    // ====================================================================
    // ШАГ 5: ЗАПУСК СЕРВИСА
    // ====================================================================
    println!("5. Запуск сервиса {}...", service_guid);

    // Запустить ранее остановленный сервис
    // Примечание: Сервисы обычно запускаются автоматически после публикации
    conn.start(service_guid.clone()).await?;
    println!("   - Сервис запущен");

    // ====================================================================
    // ШАГ 6: ПРОВЕРКА СТАТУСА СЕРВИСА
    // ====================================================================
    println!("6. Проверка статуса сервиса...");

    // Получить список сервисов снова, чтобы увидеть обновленный статус
    let services = conn.ls().await?;

    // Найти наш конкретный сервис и отобразить его статус
    if let Some(service) = services.iter().find(|s| s.guid == service_guid) {
        println!(
            "   - Статус сервиса: {}",
            service.status.as_ref().unwrap_or(&"Неизвестно".to_string())
        );

        // Поле статуса указывает состояние сервиса:
        // - "running": Сервис активен и доступен
        // - "stopped": Сервис зарегистрирован, но не доступен
        // - "error": Сервис столкнулся с ошибкой
    }

    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("Не удалось прочитать строку");

    // ====================================================================
    // ШАГ 7: ОСТАНОВКА СЕРВИСА
    // ====================================================================
    println!("7. Остановка сервиса {}...", service_guid);

    // Остановка делает сервис временно недоступным,
    // но сохраняет его регистрацию
    conn.stop(service_guid.clone()).await?;
    println!("   - Сервис остановлен");

    // ====================================================================
    // ШАГ 8: ОТМЕНА ПУБЛИКАЦИИ СЕРВИСА
    // ====================================================================
    println!("8. Отмена регистрации сервиса {}...", service_guid);

    // Отмена публикации удаляет регистрацию сервиса
    // Сервис больше не будет доступен через CloudPub
    conn.unpublish(service_guid.clone()).await?;
    println!("   - Регистрация сервиса отменена");

    // ====================================================================
    // ШАГ 9: ПРОВЕРКА УДАЛЕНИЯ
    // ====================================================================
    println!("9. Финальный список сервисов...");

    // Получить список сервисов для подтверждения удаления
    let services = conn.ls().await?;
    println!("   - Осталось {} сервис(ов)", services.len());

    // ====================================================================
    // ШАГ 10: ОЧИСТКА ВСЕХ СЕРВИСОВ
    // ====================================================================
    println!("10. Очистка всех сервисов...");

    // Clean удаляет все сервисы, зарегистрированные текущим пользователем
    // Используйте с осторожностью, так как это действие нельзя отменить
    conn.clean().await?;
    println!("   - Все сервисы удалены");

    // Проверить, что все сервисы были удалены
    let services = conn.ls().await?;
    println!("   Финальное количество: {} сервис(ов)", services.len());

    println!("Демонстрация успешно завершена!");

    // ====================================================================
    // ОЧИСТКА СОЕДИНЕНИЯ
    // ====================================================================
    // Соединение будет автоматически закрыто, когда `conn` выйдет из области видимости
    // Реализация Drop обрабатывает:
    // - Отправку сообщения Break для корректной остановки клиента
    // - Отмену фоновых задач
    // - Очистку ресурсов

    Ok(())
}