Add explicit vocabulary and named operation contexts
This commit is contained in:
+43
-53
@@ -19,15 +19,12 @@ use crate::delivery::files::{self, FileOutputError, PreparedDestination};
|
||||
use crate::delivery::qr;
|
||||
use crate::delivery::{self, ClientConfigPayload, DeliverySettings, QrCodeOutput, QrError};
|
||||
use crate::domain::{
|
||||
AddressAvailability, Client, ClientAddresses, ClientStates, DomainError, PublicKey,
|
||||
RuntimeObservation, Snapshot, allocate_ipv4, allocate_ipv6, validate_manual_ipv4,
|
||||
validate_manual_ipv6,
|
||||
AddressAvailability, ApplyStatus, Client, ClientAddresses, ClientStates, DomainError,
|
||||
PublicKey, Snapshot, allocate_ipv4, allocate_ipv6, validate_manual_ipv4, validate_manual_ipv6,
|
||||
};
|
||||
use crate::persistence::{BackupComplete, PersistedState, PersistenceError, SavedStore};
|
||||
use crate::runtime::transport::TransportError;
|
||||
use crate::runtime::{
|
||||
self, RuntimeObservation as TechnicalObservation, SavedPeerProjection, TechnicalMatch,
|
||||
};
|
||||
use crate::runtime::{self, RuntimeObservation, SavedPeerProjection, TechnicalMatch};
|
||||
use crate::service::{self, RestartDeadline, RestartExecution, RestartOutcome};
|
||||
use crate::vault::source::{
|
||||
PreparedImportSetup, SelectedFileImportReport, SourceImportError, SourceImportReport,
|
||||
@@ -504,7 +501,7 @@ impl Application {
|
||||
let states = ClientStates::new(
|
||||
snapshot_from_document(&document),
|
||||
None,
|
||||
RuntimeObservation::Unknown,
|
||||
ApplyStatus::Unknown,
|
||||
)?;
|
||||
Self::open_saved(store, saved, states)
|
||||
}
|
||||
@@ -984,7 +981,7 @@ impl Application {
|
||||
let Ok((projection, _)) = restart_projection_from_document(document) else {
|
||||
return false;
|
||||
};
|
||||
self.states.applied() == &RuntimeObservation::Verified
|
||||
self.states.applied() == &ApplyStatus::Verified
|
||||
&& self.verified_saved_projection.as_ref() == Some(&projection)
|
||||
}
|
||||
|
||||
@@ -1487,7 +1484,7 @@ impl Application {
|
||||
preview: RestartPreview,
|
||||
choice: RestartChoice,
|
||||
service: impl FnOnce(&str, RestartDeadline) -> RestartExecution,
|
||||
runtime_read: impl FnOnce(&str, Duration) -> Result<TechnicalObservation, TransportError>,
|
||||
runtime_read: impl FnOnce(&str, Duration) -> Result<RuntimeObservation, TransportError>,
|
||||
install: impl FnOnce(&SavedStore, &SavedBytes, BackupComplete) -> Result<(), PersistenceError>,
|
||||
) -> RestartReport {
|
||||
self.restart_with_adapters_and_clock(
|
||||
@@ -1532,7 +1529,7 @@ impl Application {
|
||||
preview: RestartPreview,
|
||||
choice: RestartChoice,
|
||||
service: impl FnOnce(&str, RestartDeadline) -> RestartExecution,
|
||||
runtime_read: impl FnOnce(&str, Duration) -> Result<TechnicalObservation, TransportError>,
|
||||
runtime_read: impl FnOnce(&str, Duration) -> Result<RuntimeObservation, TransportError>,
|
||||
install: impl FnOnce(&SavedStore, &SavedBytes, BackupComplete) -> Result<(), PersistenceError>,
|
||||
now: impl Fn() -> Instant,
|
||||
) -> RestartReport {
|
||||
@@ -1860,7 +1857,7 @@ impl Application {
|
||||
let mut proposed = preview.saved_bytes;
|
||||
let document = ConfigDocument::parse(&proposed.server_config)?;
|
||||
let snapshot = snapshot_from_document(&document);
|
||||
let mut restored_states = ClientStates::new(snapshot, None, RuntimeObservation::Unknown)?;
|
||||
let mut restored_states = ClientStates::new(snapshot, None, ApplyStatus::Unknown)?;
|
||||
let mut archived_reservations = BTreeSet::new();
|
||||
let mut reservations = self.states.reserved_addresses().clone();
|
||||
// A restore can remove clients that are currently saved even when their
|
||||
@@ -1947,7 +1944,7 @@ impl Application {
|
||||
.map(VaultBundle::from_toml)
|
||||
.transpose()?;
|
||||
let snapshot = snapshot_from_document(&document);
|
||||
let mut states = ClientStates::new(snapshot, None, RuntimeObservation::Unknown)?;
|
||||
let mut states = ClientStates::new(snapshot, None, ApplyStatus::Unknown)?;
|
||||
if let Some(bytes) = &preview.saved_bytes.internal_state {
|
||||
PersistedState::from_toml(bytes)?.apply_to(&mut states)?;
|
||||
}
|
||||
@@ -2508,16 +2505,14 @@ mod tests {
|
||||
use crate::backup::{BackupReason, HistoricalApplyStatus, create_archive, preview_archive};
|
||||
use crate::config::SettingsFile;
|
||||
use crate::delivery::qr::QrError;
|
||||
use crate::domain::{
|
||||
Client, ClientAddresses, ClientStates, PublicKey, RuntimeObservation, Snapshot,
|
||||
};
|
||||
use crate::domain::{ApplyStatus, Client, ClientAddresses, ClientStates, PublicKey, Snapshot};
|
||||
use crate::persistence::{
|
||||
BackupComplete, InstallCheckpoint, PersistedState, PersistenceError, SavedStore,
|
||||
};
|
||||
use crate::runtime::transport::TransportError;
|
||||
use crate::runtime::{
|
||||
InterfaceObservation, Observed, PeerSetCompleteness, RuntimeObservation as ObservedRuntime,
|
||||
RuntimePeer, RuntimePeerSet,
|
||||
InterfaceObservation, Observed, PeerSetCompleteness, RuntimeObservation, RuntimePeer,
|
||||
RuntimePeerSet,
|
||||
};
|
||||
use crate::service::{RestartExecution, RestartFailure, RestartOutcome};
|
||||
use crate::vault::{VaultBundle, WireGuardPrivateKey};
|
||||
@@ -2586,12 +2581,8 @@ restart_timeout_seconds = 30
|
||||
)
|
||||
.expect("state client valid");
|
||||
let snapshot = Snapshot::new([saved_client]).expect("snapshot valid");
|
||||
let states = ClientStates::new(
|
||||
snapshot.clone(),
|
||||
Some(snapshot),
|
||||
RuntimeObservation::Verified,
|
||||
)
|
||||
.expect("initial applied state valid");
|
||||
let states = ClientStates::new(snapshot.clone(), Some(snapshot), ApplyStatus::Verified)
|
||||
.expect("initial applied state valid");
|
||||
let store = SavedStore::new(root, resolved).expect("saved store mapping valid");
|
||||
(store, states, key, secret)
|
||||
}
|
||||
@@ -2637,7 +2628,7 @@ restart_timeout_seconds = 30
|
||||
app
|
||||
}
|
||||
|
||||
fn observed_runtime(app: &Application) -> ObservedRuntime {
|
||||
fn observed_runtime(app: &Application) -> RuntimeObservation {
|
||||
let records = app.document().peers().iter().map(|peer| {
|
||||
let identity = peer.identity.expect("synthetic peer identity");
|
||||
(
|
||||
@@ -2650,7 +2641,7 @@ restart_timeout_seconds = 30
|
||||
},
|
||||
)
|
||||
});
|
||||
ObservedRuntime {
|
||||
RuntimeObservation {
|
||||
observed_at: None,
|
||||
interface: InterfaceObservation::Present {
|
||||
name: "wg0".to_owned(),
|
||||
@@ -3590,7 +3581,7 @@ restart_timeout_seconds = 30
|
||||
String::from_utf8_lossy(app.document().render())
|
||||
.contains("# wg-admin:alias=bmV3IGFsaWFz")
|
||||
);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert_eq!(
|
||||
app.states().saved().get(&key).expect("saved peer").alias,
|
||||
"legacy-view"
|
||||
@@ -3681,7 +3672,7 @@ restart_timeout_seconds = 30
|
||||
app.states().saved().get(&key).expect("saved peer").alias,
|
||||
"new alias"
|
||||
);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(app.states().applied_snapshot().is_some());
|
||||
let backup = preview_archive(&archive).expect("pre-commit backup parses");
|
||||
assert_eq!(backup.reason, BackupReason::PreCommit);
|
||||
@@ -3769,11 +3760,10 @@ restart_timeout_seconds = 30
|
||||
assert!(state.reserved_addresses.contains(&"10.20.0.2".to_owned()));
|
||||
assert!(state.reserved_addresses.contains(&"fd20::2".to_owned()));
|
||||
|
||||
let reopened_states =
|
||||
ClientStates::new(Snapshot::default(), None, RuntimeObservation::Unknown)
|
||||
.expect("empty supported snapshot is valid");
|
||||
let reopened_states = ClientStates::new(Snapshot::default(), None, ApplyStatus::Unknown)
|
||||
.expect("empty supported snapshot is valid");
|
||||
let reopened = Application::open(store, reopened_states).expect("session reopens");
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(
|
||||
reopened
|
||||
.states()
|
||||
@@ -3912,7 +3902,7 @@ restart_timeout_seconds = 30
|
||||
app.confirm_restore(preview)
|
||||
.expect("restore uses previewed bytes");
|
||||
assert!(!String::from_utf8_lossy(app.document().render()).contains("draft alias"));
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(app.vault().is_some());
|
||||
assert!(app.states().saved().get(&key).is_some());
|
||||
}
|
||||
@@ -3943,7 +3933,7 @@ restart_timeout_seconds = 30
|
||||
let before_restore = store.read_saved().expect("current saved bytes");
|
||||
app.rename_client(key, "draft survives failed restore")
|
||||
.expect("stage draft");
|
||||
let applied_before = app.states().applied().clone();
|
||||
let applied_before = *app.states().applied();
|
||||
let preview = app
|
||||
.preview_restore(selected.file_name().unwrap().to_str().unwrap())
|
||||
.expect("selected archive preview");
|
||||
@@ -4106,7 +4096,7 @@ restart_timeout_seconds = 30
|
||||
.expect("restored reservation state parses");
|
||||
assert!(state.reserved_addresses.contains(&"fd20::2".to_owned()));
|
||||
assert!(app.vault().is_none());
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -4167,7 +4157,7 @@ restart_timeout_seconds = 30
|
||||
.iter()
|
||||
.all(|item| item.historical_apply == HistoricalApplyStatus::Unknown)
|
||||
);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -4284,7 +4274,7 @@ restart_timeout_seconds = 30
|
||||
assert!(report.backup_path.is_some());
|
||||
assert!(report.restart_submitted);
|
||||
assert_eq!(*events.borrow(), vec!["service", "runtime", "persist"]);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Verified);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Verified);
|
||||
assert_eq!(
|
||||
app.states().draft().get(&key).unwrap().alias,
|
||||
"restart fixture"
|
||||
@@ -4352,7 +4342,7 @@ restart_timeout_seconds = 30
|
||||
);
|
||||
|
||||
assert_eq!(report.stage, RestartStage::Complete);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Verified);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Verified);
|
||||
assert!(app.states().applied_snapshot().is_none());
|
||||
assert!(app.states().reserved_addresses().is_empty());
|
||||
assert_eq!(app.saved_bytes().server_config, original_config);
|
||||
@@ -4364,7 +4354,7 @@ restart_timeout_seconds = 30
|
||||
let reopened = Application::open_from_saved_store(app.store.clone())
|
||||
.expect("reopen historically verified saved state");
|
||||
assert_eq!(reopened.historical_apply, historical_apply);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(reopened.states().applied_snapshot().is_none());
|
||||
assert!(reopened.states().reserved_addresses().is_empty());
|
||||
assert!(
|
||||
@@ -4471,12 +4461,12 @@ restart_timeout_seconds = 30
|
||||
|
||||
assert_eq!(report.stage, RestartStage::Verification);
|
||||
assert_eq!(report.failure, Some(RestartFailureKind::RuntimeMismatch));
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert_eq!(app.states().reserved_addresses(), &reserved_before);
|
||||
let reopened = Application::open_from_saved_store(app.store.clone())
|
||||
.expect("failed verification leaves saved reservations durable");
|
||||
assert_eq!(reopened.states().reserved_addresses(), &reserved_before);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -4590,7 +4580,7 @@ restart_timeout_seconds = 30
|
||||
assert!(!report.restart_may_still_complete);
|
||||
assert!(report.manual_recovery_required);
|
||||
assert!(!runtime_called.get());
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(!app.states().reserved_addresses().is_empty());
|
||||
}
|
||||
|
||||
@@ -4641,7 +4631,7 @@ restart_timeout_seconds = 30
|
||||
assert!(!report.restart_may_still_complete);
|
||||
assert!(report.manual_recovery_required);
|
||||
assert!(!install_called.get());
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(!app.states().reserved_addresses().is_empty());
|
||||
}
|
||||
|
||||
@@ -4697,7 +4687,7 @@ restart_timeout_seconds = 30
|
||||
assert!(!report.restart_may_still_complete);
|
||||
assert!(report.manual_recovery_required);
|
||||
assert!(!install_called.get());
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4844,7 +4834,7 @@ restart_timeout_seconds = 30
|
||||
| RestartFailure::JobResultUnknown
|
||||
)
|
||||
);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4865,7 +4855,7 @@ restart_timeout_seconds = 30
|
||||
phase: crate::service::RestartPhase::WaitForJob,
|
||||
},
|
||||
|_, _| {
|
||||
Ok(ObservedRuntime {
|
||||
Ok(RuntimeObservation {
|
||||
observed_at: None,
|
||||
interface: InterfaceObservation::Missing,
|
||||
})
|
||||
@@ -4890,7 +4880,7 @@ restart_timeout_seconds = 30
|
||||
);
|
||||
assert_eq!(failed_write.stage, RestartStage::Persistence);
|
||||
assert!(failed_write.manual_recovery_required);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert!(!app.states().reserved_addresses().is_empty());
|
||||
}
|
||||
|
||||
@@ -4983,7 +4973,7 @@ restart_timeout_seconds = 30
|
||||
verified_at_utc: verified_at.to_owned()
|
||||
}
|
||||
);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -5021,7 +5011,7 @@ restart_timeout_seconds = 30
|
||||
Err(AppError::Persistence(PersistenceError::RecoveryRequired))
|
||||
));
|
||||
assert_eq!(app.historical_apply, HistoricalApplyStatus::Unknown);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
assert_eq!(app.saved_bytes().internal_state, before.internal_state);
|
||||
|
||||
let resolved = SettingsFile::parse_toml(SETTINGS)
|
||||
@@ -5036,7 +5026,7 @@ restart_timeout_seconds = 30
|
||||
assert_eq!(recovered.internal_state, before.internal_state);
|
||||
let reopened = Application::open(reopened_store, states).expect("application reopens");
|
||||
assert_eq!(reopened.historical_apply, HistoricalApplyStatus::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -5074,7 +5064,7 @@ restart_timeout_seconds = 30
|
||||
);
|
||||
let reopened = Application::open(store, states).expect("committed state reopens");
|
||||
assert_eq!(reopened.historical_apply, HistoricalApplyStatus::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -5127,7 +5117,7 @@ restart_timeout_seconds = 30
|
||||
let pre_restore = app.confirm_restore(preview).expect("restore succeeds");
|
||||
|
||||
assert_eq!(app.historical_apply, HistoricalApplyStatus::Unknown);
|
||||
assert_eq!(app.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(app.states().applied(), &ApplyStatus::Unknown);
|
||||
let archived = preview_archive(&pre_restore).expect("pre-restore backup validates");
|
||||
assert_eq!(
|
||||
archived.historical_apply,
|
||||
@@ -5146,11 +5136,11 @@ restart_timeout_seconds = 30
|
||||
let reopened_states = ClientStates::new(
|
||||
snapshot_from_document(&restored_document),
|
||||
None,
|
||||
RuntimeObservation::Unknown,
|
||||
ApplyStatus::Unknown,
|
||||
)
|
||||
.unwrap();
|
||||
let reopened = Application::open(store, reopened_states).expect("restored state reopens");
|
||||
assert_eq!(reopened.historical_apply, HistoricalApplyStatus::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &RuntimeObservation::Unknown);
|
||||
assert_eq!(reopened.states().applied(), &ApplyStatus::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user