leave the old applied dirs alone: no startup deletion. Refs #5913
This commit is contained in:
parent
db4f8a7b15
commit
c39a836bc5
3 changed files with 8 additions and 68 deletions
|
|
@ -195,8 +195,8 @@ hive-c0re keeps no copy of an agent's config: the forge's `agent-configs/<name>`
|
||||||
record what the agent's last successful build pinned, and nothing else.
|
record what the agent's last successful build pinned, and nothing else.
|
||||||
|
|
||||||
Older hives also kept an *applied* repo at `applied/<name>` and a *proposed*
|
Older hives also kept an *applied* repo at `applied/<name>` and a *proposed*
|
||||||
clone at `agents/<name>/config`. The startup migration removes the applied
|
clone at `agents/<name>/config`. Nothing reads either any more, and you can
|
||||||
repos. Nothing reads the proposed clone any more, and you can delete it.
|
delete them.
|
||||||
|
|
||||||
The container's `--flake` ref is `internal/meta` (see "Meta flake" above).
|
The container's `--flake` ref is `internal/meta` (see "Meta flake" above).
|
||||||
The agent's `agent-configs/<n>/flake.nix`
|
The agent's `agent-configs/<n>/flake.nix`
|
||||||
|
|
@ -271,9 +271,6 @@ host set up before the current deploy scheme (described above)
|
||||||
converges to it automatically. Each phase is a no-op
|
converges to it automatically. Each phase is a no-op
|
||||||
once already applied:
|
once already applied:
|
||||||
|
|
||||||
- **Applied repos**: deletes the per-agent `applied/<n>` repos an earlier hive
|
|
||||||
kept. The deploy markers beside them stay. Non-destructive for everything
|
|
||||||
else — it doesn't touch live containers, state dirs, or claude creds.
|
|
||||||
- **Agent files**: refreshes the files that follow the agent set
|
- **Agent files**: refreshes the files that follow the agent set
|
||||||
(`agent_set::refresh`) from the current agent list. Set
|
(`agent_set::refresh`) from the current agent list. Set
|
||||||
`HIVE_SKIP_META_MIGRATION=1` on the service to defer this phase.
|
`HIVE_SKIP_META_MIGRATION=1` on the service to defer this phase.
|
||||||
|
|
|
||||||
|
|
@ -547,8 +547,8 @@ Under `/var/lib/hyperhive/applied/` — the hive-c0re-only deploy markers
|
||||||
`.<name>.hyperhive-rev` and `.<name>.config-rev`: the hyperhive and config
|
`.<name>.hyperhive-rev` and `.<name>.config-rev`: the hyperhive and config
|
||||||
commits the agent's last successful build pinned. No config lives here; the
|
commits the agent's last successful build pinned. No config lives here; the
|
||||||
forge's `agent-configs/<name>` is the only copy. A hive that predates this
|
forge's `agent-configs/<name>` is the only copy. A hive that predates this
|
||||||
finds per-agent `applied/<name>` repos here; `migrate::run` deletes them at
|
finds per-agent `applied/<name>` repos here. Nothing reads them any more, and
|
||||||
startup.
|
you can delete them.
|
||||||
|
|
||||||
Under `/var/lib/hyperhive/meta/` — system-level config files, plain state
|
Under `/var/lib/hyperhive/meta/` — system-level config files, plain state
|
||||||
with no git history. The flake agents build from is the
|
with no git history. The flake agents build from is the
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! Startup convergence. Three phases, all idempotent and unguarded:
|
//! Startup convergence. Two phases, all idempotent and unguarded:
|
||||||
//! harness files, the leftover applied repos, the agent-set files, plus the
|
//! harness files and the agent-set files, plus the
|
||||||
//! removal of the legacy meta repo's leftovers. They re-run every
|
//! removal of the legacy meta repo's leftovers. They re-run every
|
||||||
//! boot on purpose — each one is a no-op once its state is already
|
//! boot on purpose — each one is a no-op once its state is already
|
||||||
//! correct.
|
//! correct.
|
||||||
|
|
@ -72,16 +72,8 @@ pub async fn run() -> Result<()> {
|
||||||
Err(e) => tracing::warn!(error = ?e, "migration: removing the legacy meta .git failed"),
|
Err(e) => tracing::warn!(error = ?e, "migration: removing the legacy meta .git failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 1: the applied repos an earlier hive kept per agent.
|
// Phase 1: the files that follow the agent set.
|
||||||
tracing::debug!("migration: phase 1 (leftover applied repos)");
|
tracing::debug!("migration: phase 1 (agent_set refresh)");
|
||||||
match remove_applied_repos(&crate::paths::applied_root()) {
|
|
||||||
Ok(0) => {}
|
|
||||||
Ok(n) => tracing::info!(count = n, "migration: removed leftover applied repos"),
|
|
||||||
Err(e) => tracing::warn!(error = ?e, "migration: removing the applied repos failed"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 2: the files that follow the agent set.
|
|
||||||
tracing::debug!("migration: phase 2 (agent_set refresh)");
|
|
||||||
// `refresh` takes the agents it is given as the whole set, so an empty
|
// `refresh` takes the agents it is given as the whole set, so an empty
|
||||||
// stand-in for an unreadable list would drop every agent from the topology.
|
// stand-in for an unreadable list would drop every agent from the topology.
|
||||||
let agents = match lifecycle::agents_for_meta_listing().await {
|
let agents = match lifecycle::agents_for_meta_listing().await {
|
||||||
|
|
@ -167,29 +159,6 @@ async fn enumerate_agents() -> Result<Vec<hive_types::Ident>> {
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the per-agent `applied/<name>` repos an earlier hive kept in `root`,
|
|
||||||
/// destroyed agents' included. The forge's `agent-configs/<name>` is the only
|
|
||||||
/// copy of a config now, so nothing reads them. The dot-files beside them (the
|
|
||||||
/// deploy markers) stay. Returns how many it removed.
|
|
||||||
fn remove_applied_repos(root: &Path) -> Result<usize> {
|
|
||||||
let entries = match std::fs::read_dir(root) {
|
|
||||||
Ok(entries) => entries,
|
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(0),
|
|
||||||
Err(e) => return Err(e).with_context(|| format!("reading {}", root.display())),
|
|
||||||
};
|
|
||||||
let mut removed = 0;
|
|
||||||
for entry in entries {
|
|
||||||
let entry = entry.with_context(|| format!("reading {}", root.display()))?;
|
|
||||||
if !entry.file_type()?.is_dir() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let path = entry.path();
|
|
||||||
std::fs::remove_dir_all(&path).with_context(|| format!("removing {}", path.display()))?;
|
|
||||||
removed += 1;
|
|
||||||
}
|
|
||||||
Ok(removed)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -231,30 +200,4 @@ mod tests {
|
||||||
assert!(dir.path().join("forge-other").exists(), "neighbour stays");
|
assert!(dir.path().join("forge-other").exists(), "neighbour stays");
|
||||||
assert!(!remove_core_token(dir.path()).expect("second"), "no-op");
|
assert!(!remove_core_token(dir.path()).expect("second"), "no-op");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn applied_repos_go_and_the_markers_beside_them_stay() {
|
|
||||||
let root = tempfile::tempdir().expect("tempdir");
|
|
||||||
for name in ["alice", "bob"] {
|
|
||||||
std::fs::create_dir_all(root.path().join(name).join(".git")).expect("mkdir repo");
|
|
||||||
std::fs::write(root.path().join(name).join("agent.nix"), "{}").expect("write config");
|
|
||||||
std::fs::write(root.path().join(format!(".{name}.config-rev")), "abc").expect("marker");
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(remove_applied_repos(root.path()).expect("first"), 2);
|
|
||||||
assert!(!root.path().join("alice").exists());
|
|
||||||
assert!(
|
|
||||||
root.path().join(".alice.config-rev").exists(),
|
|
||||||
"marker stays"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
remove_applied_repos(root.path()).expect("second"),
|
|
||||||
0,
|
|
||||||
"no-op"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
remove_applied_repos(&root.path().join("missing")).expect("absent root"),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue