example/
example.rs

1//! # Пример CloudPub SDK
2//!
3//! Этот пример демонстрирует полный рабочий процесс использования CloudPub Rust SDK,
4//! включая настройку соединения, публикацию сервисов, управление и очистку.
5//!
6//! ## Запуск примера
7//!
8//! ```bash
9//! cargo run --example example
10//! ```
11//!
12//! ## Предварительные требования
13//!
14//! 1. Сервер CloudPub должен быть запущен и доступен
15//! 2. Действительные учетные данные (email и пароль)
16//! 3. Локальные сервисы для публикации (пример использует localhost порты)
17
18use anyhow::Result;
19use cloudpub_sdk::protocol::{Auth, Endpoint, Protocol};
20use cloudpub_sdk::Connection;
21use std::io;
22use std::path::Path;
23
24#[tokio::main]
25async fn main() -> Result<()> {
26    // ====================================================================
27    // ШАГ 1: УСТАНОВЛЕНИЕ СОЕДИНЕНИЯ
28    // ====================================================================
29    println!("1. Подключение к серверу");
30
31    // Создание соединения с использованием паттерна билдера
32    // Билдер позволяет настроить различные параметры соединения
33    let mut conn = Connection::builder()
34        // Указать путь к пользовательскому файлу конфигурации (опционально)
35        // Если не указан, используется системное расположение по умолчанию
36        .config_path(Path::new("/tmp/cloudpub.toml"))
37        // Установить уровень логирования для отладки
38        // Варианты: "trace", "debug", "info", "warn", "error"
39        .log_level("info")
40        // Включить подробный вывод в stderr для отладки
41        // Полезно при разработке, отключите в продакшене
42        .verbose(true)
43        // Предоставить учетные данные для аутентификации
44        // Вы также можете использовать .token() для аутентификации на основе токена
45        .credentials("admin@example.com", "test")
46        // Установить таймаут для операций (в секундах)
47        // Применяется ко всем асинхронным операциям
48        .timeout_secs(3)
49        // Построить и установить соединение
50        // Произойдет аутентификация и ожидание готовности соединения
51        .build()
52        .await?;
53
54    // ====================================================================
55    // ШАГ 2: ПУБЛИКАЦИЯ HTTP СЕРВИСА
56    // ====================================================================
57    println!("2. Публикация нового HTTP сервиса...");
58
59    // Публикация локального HTTP сервиса для доступа через CloudPub
60    let endpoint = conn
61        .publish(
62            Protocol::Http,                           // Тип протокола
63            "localhost:8080".to_string(),             // Локальный адрес для публикации
64            Some("Тестовый HTTP сервис".to_string()), // Человекочитаемое имя сервиса
65            Some(Auth::None),                         // Метод аутентификации для доступа к сервису
66            None,                                     // Без ограничений ACL
67            None,                                     // Без пользовательских заголовков
68            None,                                     // Без правил фильтрации
69        )
70        .await?;
71
72    // Endpoint содержит информацию об опубликованном сервисе
73    // as_url() возвращает публичный URL, по которому доступен сервис
74    println!("  Сервис опубликован: {}", endpoint.as_url());
75
76    // ====================================================================
77    // ШАГ 3: ПУБЛИКАЦИЯ TCP СЕРВИСА
78    // ====================================================================
79    println!("3. Публикация нового TCP сервиса...");
80
81    // TCP сервисы полезны для публикации SSH, баз данных или пользовательских TCP протоколов
82    let endpoint = conn
83        .publish(
84            Protocol::Tcp,                           // TCP протокол
85            "localhost:22".to_string(),              // Локальный SSH порт (пример)
86            Some("Тестовый TCP сервис".to_string()), // Имя сервиса
87            Some(Auth::None),                        // Аутентификация не требуется
88            None,                                    // Без ограничений ACL
89            None,                                    // Без пользовательских заголовков
90            None,                                    // Без правил фильтрации
91        )
92        .await?;
93
94    println!("  Сервис опубликован: {}", endpoint.as_url());
95
96    // Сохранить GUID для последующих операций
97    // GUID уникально идентифицирует этот сервис
98    let service_guid = endpoint.guid.clone();
99
100    // ====================================================================
101    // ШАГ 4: СПИСОК ВСЕХ СЕРВИСОВ
102    // ====================================================================
103    println!("4. Список сервисов:");
104
105    // Получить все сервисы, зарегистрированные текущим пользователем
106    let services = conn.ls().await?;
107
108    // Отобразить каждый сервис с его GUID и URL
109    for service in &services {
110        println!("  {}: {}", service.guid, service.as_url());
111
112        // Сервисы также содержат дополнительные метаданные:
113        // - service.name: Опциональное человекочитаемое имя
114        // - service.status: Текущий статус (работает, остановлен и т.д.)
115        // - service.protocol: Тип протокола
116        // - service.auth: Метод аутентификации
117    }
118
119    // ====================================================================
120    // ШАГ 5: ЗАПУСК СЕРВИСА
121    // ====================================================================
122    println!("5. Запуск сервиса {}...", service_guid);
123
124    // Запустить ранее остановленный сервис
125    // Примечание: Сервисы обычно запускаются автоматически после публикации
126    conn.start(service_guid.clone()).await?;
127    println!("   - Сервис запущен");
128
129    // ====================================================================
130    // ШАГ 6: ПРОВЕРКА СТАТУСА СЕРВИСА
131    // ====================================================================
132    println!("6. Проверка статуса сервиса...");
133
134    // Получить список сервисов снова, чтобы увидеть обновленный статус
135    let services = conn.ls().await?;
136
137    // Найти наш конкретный сервис и отобразить его статус
138    if let Some(service) = services.iter().find(|s| s.guid == service_guid) {
139        println!(
140            "   - Статус сервиса: {}",
141            service.status.as_ref().unwrap_or(&"Неизвестно".to_string())
142        );
143
144        // Поле статуса указывает состояние сервиса:
145        // - "running": Сервис активен и доступен
146        // - "stopped": Сервис зарегистрирован, но не доступен
147        // - "error": Сервис столкнулся с ошибкой
148    }
149
150    let mut buffer = String::new();
151    io::stdin()
152        .read_line(&mut buffer)
153        .expect("Не удалось прочитать строку");
154
155    // ====================================================================
156    // ШАГ 7: ОСТАНОВКА СЕРВИСА
157    // ====================================================================
158    println!("7. Остановка сервиса {}...", service_guid);
159
160    // Остановка делает сервис временно недоступным,
161    // но сохраняет его регистрацию
162    conn.stop(service_guid.clone()).await?;
163    println!("   - Сервис остановлен");
164
165    // ====================================================================
166    // ШАГ 8: ОТМЕНА ПУБЛИКАЦИИ СЕРВИСА
167    // ====================================================================
168    println!("8. Отмена регистрации сервиса {}...", service_guid);
169
170    // Отмена публикации удаляет регистрацию сервиса
171    // Сервис больше не будет доступен через CloudPub
172    conn.unpublish(service_guid.clone()).await?;
173    println!("   - Регистрация сервиса отменена");
174
175    // ====================================================================
176    // ШАГ 9: ПРОВЕРКА УДАЛЕНИЯ
177    // ====================================================================
178    println!("9. Финальный список сервисов...");
179
180    // Получить список сервисов для подтверждения удаления
181    let services = conn.ls().await?;
182    println!("   - Осталось {} сервис(ов)", services.len());
183
184    // ====================================================================
185    // ШАГ 10: ОЧИСТКА ВСЕХ СЕРВИСОВ
186    // ====================================================================
187    println!("10. Очистка всех сервисов...");
188
189    // Clean удаляет все сервисы, зарегистрированные текущим пользователем
190    // Используйте с осторожностью, так как это действие нельзя отменить
191    conn.clean().await?;
192    println!("   - Все сервисы удалены");
193
194    // Проверить, что все сервисы были удалены
195    let services = conn.ls().await?;
196    println!("   Финальное количество: {} сервис(ов)", services.len());
197
198    println!("Демонстрация успешно завершена!");
199
200    // ====================================================================
201    // ОЧИСТКА СОЕДИНЕНИЯ
202    // ====================================================================
203    // Соединение будет автоматически закрыто, когда `conn` выйдет из области видимости
204    // Реализация Drop обрабатывает:
205    // - Отправку сообщения Break для корректной остановки клиента
206    // - Отмену фоновых задач
207    // - Очистку ресурсов
208
209    Ok(())
210}