This commit is contained in:
@@ -93,16 +93,23 @@ translations! {
|
||||
configs_loading_status: "Loading status..." , "Загрузка статуса...";
|
||||
configs_no_pods: "No AmneziaWG pods." , "Нет подов AmneziaWG.";
|
||||
configs_server: "Server" , "Сервер";
|
||||
configs_endpoint: "Endpoint" , "Endpoint";
|
||||
configs_message: "Message" , "Сообщение";
|
||||
configs_pod: "Pod" , "Pod";
|
||||
configs_node: "Node" , "Нода";
|
||||
configs_rollout: "Rollout" , "Применение";
|
||||
configs_ready: "Ready" , "Готов";
|
||||
configs_not_ready: "Not ready" , "Не готов";
|
||||
configs_phase: "Phase" , "Фаза";
|
||||
configs_uptime: "Uptime" , "Аптайм";
|
||||
configs_restarts: "Restarts" , "Рестарты";
|
||||
configs_config_applied: "Config applied" , "Конфиг применён";
|
||||
configs_reload_status: "Reload status" , "Статус reload";
|
||||
configs_config_hash: "Config hash" , "Хэш конфига";
|
||||
configs_status_applied: "applied" , "применён";
|
||||
configs_status_starting: "starting" , "стартует";
|
||||
configs_status_pending_restart: "pending restart" , "ждёт рестарт";
|
||||
configs_status_error: "reload error" , "ошибка reload";
|
||||
configs_status_unknown: "unknown" , "неизвестно";
|
||||
configs_never: "n/a" , "н/д";
|
||||
configs_servers: "Servers" , "Серверы";
|
||||
|
||||
+57
-2
@@ -399,6 +399,12 @@ fn qcompress(data: &[u8]) -> Result<Vec<u8>, String> {
|
||||
|
||||
const CLIENT_SECRET_UPDATED_AT_ANNOTATION: &str =
|
||||
"amnezia-fellow.hexor.cy/client-secret-updated-at-ms";
|
||||
const CLIENT_SECRET_APPLIED_AT_ANNOTATION: &str =
|
||||
"amnezia-fellow.hexor.cy/client-secret-applied-at-ms";
|
||||
const CLIENT_SECRET_APPLIED_HASH_ANNOTATION: &str =
|
||||
"amnezia-fellow.hexor.cy/client-secret-applied-hash";
|
||||
const CLIENT_SECRET_RELOAD_STATUS_ANNOTATION: &str =
|
||||
"amnezia-fellow.hexor.cy/client-secret-reload-status";
|
||||
const AMNEZIAWG_POD_LABEL_SELECTOR: &str = "app=amneziawg";
|
||||
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema)]
|
||||
@@ -613,6 +619,9 @@ pub struct VpnPodRolloutStatus {
|
||||
pub ready: bool,
|
||||
pub restart_count: i32,
|
||||
pub started_at_ms: Option<i64>,
|
||||
pub config_applied_at_ms: Option<i64>,
|
||||
pub config_applied_hash: Option<String>,
|
||||
pub config_reload_status: Option<String>,
|
||||
pub uptime_seconds: Option<u64>,
|
||||
pub rollout_status: String,
|
||||
pub message: Option<String>,
|
||||
@@ -705,6 +714,7 @@ fn pod_rollout_status(
|
||||
config_updated_at_ms: Option<i64>,
|
||||
now_ms: i64,
|
||||
) -> VpnPodRolloutStatus {
|
||||
let annotations = pod.metadata.annotations.clone().unwrap_or_default();
|
||||
let name = pod.metadata.name.unwrap_or_default();
|
||||
let node_name = pod
|
||||
.spec
|
||||
@@ -728,11 +738,26 @@ fn pod_rollout_status(
|
||||
let started_at_ms = status
|
||||
.and_then(|status| status.start_time.as_ref())
|
||||
.map(time_to_millis);
|
||||
let config_applied_at_ms = annotation_i64(&annotations, CLIENT_SECRET_APPLIED_AT_ANNOTATION);
|
||||
let config_applied_hash = annotations
|
||||
.get(CLIENT_SECRET_APPLIED_HASH_ANNOTATION)
|
||||
.filter(|value| !value.is_empty())
|
||||
.cloned();
|
||||
let config_reload_status = annotations
|
||||
.get(CLIENT_SECRET_RELOAD_STATUS_ANNOTATION)
|
||||
.filter(|value| !value.is_empty())
|
||||
.cloned();
|
||||
let uptime_seconds = started_at_ms.map(|started| {
|
||||
let elapsed_ms = now_ms.saturating_sub(started);
|
||||
(elapsed_ms / 1000) as u64
|
||||
});
|
||||
let rollout_status = rollout_status(config_updated_at_ms, started_at_ms, ready);
|
||||
let rollout_status = rollout_status(
|
||||
config_updated_at_ms,
|
||||
started_at_ms,
|
||||
config_applied_at_ms,
|
||||
config_reload_status.as_deref(),
|
||||
ready,
|
||||
);
|
||||
let message = status.and_then(|status| status.message.clone().or(status.reason.clone()));
|
||||
|
||||
VpnPodRolloutStatus {
|
||||
@@ -744,6 +769,9 @@ fn pod_rollout_status(
|
||||
ready,
|
||||
restart_count,
|
||||
started_at_ms,
|
||||
config_applied_at_ms,
|
||||
config_applied_hash,
|
||||
config_reload_status,
|
||||
uptime_seconds,
|
||||
rollout_status,
|
||||
message,
|
||||
@@ -781,9 +809,16 @@ fn amneziawg_restart_count(status: &k8s_openapi::api::core::v1::PodStatus) -> i3
|
||||
fn rollout_status(
|
||||
config_updated_at_ms: Option<i64>,
|
||||
started_at_ms: Option<i64>,
|
||||
config_applied_at_ms: Option<i64>,
|
||||
config_reload_status: Option<&str>,
|
||||
ready: bool,
|
||||
) -> String {
|
||||
match (config_updated_at_ms, started_at_ms) {
|
||||
if config_reload_status == Some("error") {
|
||||
return "error".to_owned();
|
||||
}
|
||||
|
||||
let effective_applied_at_ms = started_at_ms.into_iter().chain(config_applied_at_ms).max();
|
||||
match (config_updated_at_ms, effective_applied_at_ms) {
|
||||
(None, _) => "unknown".to_owned(),
|
||||
(Some(_), None) => "pending_restart".to_owned(),
|
||||
(Some(updated), Some(started)) if started >= updated && ready => "applied".to_owned(),
|
||||
@@ -802,6 +837,10 @@ fn client_secret_updated_at_ms(secret: &Secret) -> Option<i64> {
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn annotation_i64(annotations: &BTreeMap<String, String>, key: &str) -> Option<i64> {
|
||||
annotations.get(key)?.parse().ok()
|
||||
}
|
||||
|
||||
fn time_to_millis(time: &Time) -> i64 {
|
||||
time.0.as_millisecond()
|
||||
}
|
||||
@@ -1037,6 +1076,22 @@ mod tests {
|
||||
assert!(!overrides.contains_key("empty"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rollout_status_uses_hot_reload_annotations() {
|
||||
assert_eq!(
|
||||
rollout_status(Some(2_000), Some(1_000), Some(3_000), Some("applied"), true),
|
||||
"applied"
|
||||
);
|
||||
assert_eq!(
|
||||
rollout_status(Some(2_000), Some(1_000), None, Some("error"), true),
|
||||
"error"
|
||||
);
|
||||
assert_eq!(
|
||||
rollout_status(Some(2_000), Some(1_000), None, None, true),
|
||||
"pending_restart"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qcompress_uses_qt_wire_format() {
|
||||
let payload = br#"{"description":"de-fsn1"}"#;
|
||||
|
||||
Reference in New Issue
Block a user