difftreelog
feat explicitly mark hosts as managed by fleet
in: trunk
7 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -924,6 +924,7 @@
"hostname",
"human-repr",
"indicatif",
+ "indoc",
"itertools 0.13.0",
"nix-eval",
"nixlike",
@@ -1537,6 +1538,12 @@
]
[[package]]
+name = "indoc"
+version = "2.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
+
+[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
cmds/fleet/Cargo.tomldiffbeforeafterboth--- a/cmds/fleet/Cargo.toml
+++ b/cmds/fleet/Cargo.toml
@@ -47,6 +47,7 @@
nix-eval.workspace = true
nom = "7.1.3"
fleet-base = { version = "0.1.0", path = "../../crates/fleet-base" }
+indoc = "2.0.6"
[features]
default = ["indicatif"]
cmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth1use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf, time::Duration};1use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf, str::FromStr, time::Duration};223use anyhow::{anyhow, Result};3use anyhow::{anyhow, bail, Result};4use clap::{Parser, ValueEnum};4use clap::{Parser, ValueEnum};5use fleet_base::{5use fleet_base::{6 host::{Config, ConfigHost},6 host::{Config, ConfigHost},332 }333 }333}334}335336#[derive(Clone, PartialEq, Copy)]337enum DeployKind {338 // NixOS => NixOS managed by fleet339 UpgradeToFleet,340 // NixOS managed by fleet => NixOS managed by fleet341 Fleet,342}343impl FromStr for DeployKind {344 type Err = anyhow::Error;345 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {346 match s {347 "upgrade-to-fleet" => Ok(Self::UpgradeToFleet),348 "fleet" => Ok(Self::Fleet),349 v => bail!("unknown deploy_kind: {v}; expected on of \"upgrade-to-fleet\", \"fleet\""),350 }351 }352}334353335impl Deploy {354impl Deploy {336 pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {355 pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {348 let local_host = config.local_host();367 let local_host = config.local_host();349 let opts = opts.clone();368 let opts = opts.clone();350 let batch = batch.clone();369 let batch = batch.clone();370 let mut deploy_kind: Option<DeployKind> =371 opts.action_attr(&host, "deploy_kind").await?;351372352 set.spawn_local(373 set.spawn_local(353 (async move {374 (async move {356 {377 {357 Ok(path) => path,378 Ok(path) => path,358 Err(e) => {379 Err(e) => {359 error!("failed to deploy host: {}", e);380 error!("failed to build host system closure: {}", e);360 return;381 return;361 }382 }362 };383 };384 if deploy_kind == None {385 let is_fleet_managed = match host.file_exists("/etc/FLEET_HOST").await {386 Ok(v) => v,387 Err(e) => {388 error!("failed to query remote system kind: {}", e);389 return;390 },391 };392 if !is_fleet_managed {393 error!(indoc::indoc!{"394 host is not marked as managed by fleet395 if you're not trying to lustrate/install system from scratch,396 you should either397 1. manually create /etc/FLEET_HOST file on the target host,398 2. use ?deploy_kind=fleet host argument if you're upgrading from older version of fleet399 3. use ?deploy_kind=upgrade_to_fleet if you're upgrading from plain nixos to fleet-managed nixos400 "});401 return;402 }403 deploy_kind = Some(DeployKind::Fleet);404 }405 let deploy_kind = deploy_kind.expect("deploy_kind is set");406407 // TODO: Make disable_rollback a host attribute instead408 let mut disable_rollback = self.disable_rollback;409 if !disable_rollback && deploy_kind != DeployKind::Fleet {410 warn!("disabling rollback, as not supported by non-fleet deployment kinds");411 disable_rollback = true;412 }413363 if !opts.is_local(&hostname) {414 if !opts.is_local(&hostname) {364 info!("uploading system closure");415 info!("uploading system closure");411 error!("unreachable? failed to get specialization");462 error!("unreachable? failed to get specialization");412 return;463 return;413 },464 },414 self.disable_rollback,465 disable_rollback,415 )466 )416 .await467 .await417 {468 {cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -66,9 +66,9 @@
#[derive(Parser)]
enum Opts {
- /// Prepare systems for deployments
+ /// Build system closures
BuildSystems(BuildSystems),
-
+ /// Upload and switch system closures
Deploy(Deploy),
/// Secret management
#[clap(subcommand)]
crates/fleet-base/src/command.rsdiffbeforeafterboth--- a/crates/fleet-base/src/command.rs
+++ b/crates/fleet-base/src/command.rs
@@ -5,6 +5,7 @@
use futures::StreamExt;
use itertools::Either;
use openssh::{OverSsh, OwningCommand, Session};
+use serde::de::DeserializeOwned;
use tokio::{io::AsyncRead, process::Command, select};
use tokio_util::codec::{BytesCodec, FramedRead, LinesCodec};
use tracing::debug;
@@ -230,6 +231,10 @@
let bytes = self.run_bytes().await?;
Ok(String::from_utf8(bytes)?)
}
+ pub async fn run_value<T: DeserializeOwned>(self) -> Result<T> {
+ let v = self.run_string().await?;
+ Ok(serde_json::from_str(&v)?)
+ }
pub async fn run_bytes(self) -> Result<Vec<u8>> {
let str = self.clone().into_string();
let cmd = self.wrap_sudo_if_needed().into_command()?;
crates/fleet-base/src/host.rsdiffbeforeafterboth--- a/crates/fleet-base/src/host.rs
+++ b/crates/fleet-base/src/host.rs
@@ -105,6 +105,14 @@
let path = cmd.run_string().await?;
Ok(path.trim_end().to_owned())
}
+ pub async fn file_exists(&self, path: impl AsRef<OsStr>) -> Result<bool> {
+ let mut cmd = self.cmd("sh").await?;
+ cmd.arg("-c")
+ .arg("test -e \"$1\" && echo true || echo false")
+ .arg("_")
+ .arg(path);
+ Ok(cmd.run_value().await?)
+ }
pub async fn read_file_bin(&self, path: impl AsRef<OsStr>) -> Result<Vec<u8>> {
let mut cmd = self.cmd("cat").await?;
cmd.arg(path);
modules/nixos/meta.nixdiffbeforeafterboth--- a/modules/nixos/meta.nix
+++ b/modules/nixos/meta.nix
@@ -1,8 +1,17 @@
-{lib, ...}: let
+{ lib, ... }:
+let
inherit (lib.modules) mkRemovedOptionModule;
-in {
+in
+{
imports = [
- (mkRemovedOptionModule ["tags"] "tags are now defined at the host level, not the nixos system level for fast filtering without evaluating unnecessary hosts.")
- (mkRemovedOptionModule ["network"] "network is now defined at the host level, not the nixos system level")
+ (mkRemovedOptionModule [ "tags" ]
+ "tags are now defined at the host level, not the nixos system level for fast filtering without evaluating unnecessary hosts."
+ )
+ (mkRemovedOptionModule [
+ "network"
+ ] "network is now defined at the host level, not the nixos system level")
];
+
+ # Version of environment (fleet scripts such as rollback) already installed on the host
+ config.environment.etc.FLEET_HOST.text = "1";
}