ryra_core/config/
status.rs1use std::path::PathBuf;
2
3use super::schema::*;
4use crate::metadata::load_metadata;
5
6pub enum RyraStatus {
8 NotInitialized,
9 Initialized(StatusInfo),
10 Error(String),
11}
12
13pub struct StatusInfo {
14 pub config_path: PathBuf,
15 pub smtp: ProviderStatus,
16 pub auth: ProviderStatus,
17 pub backup: Option<BackupSummary>,
21 pub tailscale: Option<TailscaleSummary>,
27 pub services: Vec<ServiceInfo>,
28}
29
30pub enum ProviderStatus {
31 None,
32 Configured { name: String },
33}
34
35pub struct BackupSummary {
36 pub backend_label: String,
39 pub included: usize,
41}
42
43pub struct TailscaleSummary {
44 pub advertised: usize,
46}
47
48pub struct ServiceInfo {
49 pub name: String,
50 pub url: Option<String>,
51 pub ports: std::collections::BTreeMap<String, u16>,
52 pub installed: bool,
53 pub backup_enabled: bool,
57 pub tailscale_exposed: bool,
61}
62
63impl StatusInfo {
64 pub fn from_config(config_path: PathBuf, config: &Config) -> Self {
65 let services: Vec<ServiceInfo> = crate::list_installed()
66 .unwrap_or_default()
67 .into_iter()
68 .map(|s| {
69 let backup_enabled = load_metadata(&s.name)
73 .ok()
74 .flatten()
75 .map(|m| m.backup_enabled)
76 .unwrap_or(false);
77 let url = s.exposure.url().map(|u| u.to_string());
78 let tailscale_exposed = url.as_deref().is_some_and(crate::is_tailscale_url);
79 ServiceInfo {
80 name: s.name,
81 url,
82 ports: s.ports,
83 installed: s.installed,
84 backup_enabled,
85 tailscale_exposed,
86 }
87 })
88 .collect();
89
90 let backup = config.backup.as_ref().map(|b| BackupSummary {
91 backend_label: format_backend(&b.backend),
92 included: services.iter().filter(|s| s.backup_enabled).count(),
93 });
94
95 let tailscale = config.tailscale.as_ref().map(|_| TailscaleSummary {
96 advertised: services.iter().filter(|s| s.tailscale_exposed).count(),
97 });
98
99 Self {
100 config_path,
101 smtp: match &config.smtp {
102 None => ProviderStatus::None,
103 Some(smtp) => ProviderStatus::Configured {
104 name: smtp.host.clone(),
105 },
106 },
107 auth: match &config.auth {
108 None => ProviderStatus::None,
109 Some(auth) => ProviderStatus::Configured {
110 name: format!("{} ({})", auth.provider_name(), auth.url()),
111 },
112 },
113 backup,
114 tailscale,
115 services,
116 }
117 }
118}
119
120fn format_backend(backend: &BackupBackend) -> String {
124 match backend {
125 BackupBackend::S3 {
126 endpoint, bucket, ..
127 } => format!("S3 ({endpoint}/{bucket})"),
128 BackupBackend::Local { path } => format!("local ({})", path.display()),
129 BackupBackend::Managed => "ryra-managed".to_string(),
130 }
131}