diff options
Diffstat (limited to '')
-rw-r--r-- | flake.nix | 6 | ||||
-rw-r--r-- | src/bin/activate.rs | 95 | ||||
-rw-r--r-- | src/bin/deploy.rs | 8 | ||||
-rw-r--r-- | src/deploy.rs | 29 | ||||
-rw-r--r-- | src/lib.rs | 1 |
5 files changed, 88 insertions, 51 deletions
@@ -90,7 +90,11 @@ # work around https://github.com/NixOS/nixpkgs/issues/73404 cd /tmp - $PROFILE/bin/switch-to-configuration switch + if [[ $DRY_ACTIVATE == "1" ]]; then + $PROFILE/bin/switch-to-configuration dry-activate + else + $PROFILE/bin/switch-to-configuration switch + fi # https://github.com/serokell/deploy-rs/issues/31 ${with base.config.boot.loader; diff --git a/src/bin/activate.rs b/src/bin/activate.rs index 947e883..73d064f 100644 --- a/src/bin/activate.rs +++ b/src/bin/activate.rs @@ -66,6 +66,10 @@ struct ActivateOpts { /// Auto rollback if failure #[clap(long)] auto_rollback: bool, + + /// Show what will be activated on the machines + #[clap(long)] + dry_activate: bool, } /// Activate a profile @@ -348,70 +352,76 @@ pub async fn activate( temp_path: String, confirm_timeout: u16, magic_rollback: bool, + dry_activate: bool, ) -> Result<(), ActivateError> { - info!("Activating profile"); - - let nix_env_set_exit_status = Command::new("nix-env") - .arg("-p") - .arg(&profile_path) - .arg("--set") - .arg(&closure) - .status() - .await - .map_err(ActivateError::SetProfileError)?; - - match nix_env_set_exit_status.code() { - Some(0) => (), - a => { - if auto_rollback { - deactivate(&profile_path).await?; + if !dry_activate { + info!("Activating profile"); + let nix_env_set_exit_status = Command::new("nix-env") + .arg("-p") + .arg(&profile_path) + .arg("--set") + .arg(&closure) + .status() + .await + .map_err(ActivateError::SetProfileError)?; + match nix_env_set_exit_status.code() { + Some(0) => (), + a => { + if auto_rollback && !dry_activate { + deactivate(&profile_path).await?; + } + return Err(ActivateError::SetProfileExitError(a)); } - return Err(ActivateError::SetProfileExitError(a)); - } - }; + }; + } debug!("Running activation script"); let activate_status = match Command::new(format!("{}/deploy-rs-activate", profile_path)) - .env("PROFILE", &profile_path) - .current_dir(&profile_path) + .env("PROFILE", &closure) + .env("DRY_ACTIVATE", if dry_activate { "1" } else { "0" }) + .current_dir(&closure) .status() .await .map_err(ActivateError::RunActivateError) { Ok(x) => x, Err(e) => { - if auto_rollback { + if auto_rollback && !dry_activate { deactivate(&profile_path).await?; } return Err(e); } }; - match activate_status.code() { - Some(0) => (), - a => { - if auto_rollback { - deactivate(&profile_path).await?; + if !dry_activate { + match activate_status.code() { + Some(0) => (), + a => { + if auto_rollback { + deactivate(&profile_path).await?; + } + return Err(ActivateError::RunActivateExitError(a)); } - return Err(ActivateError::RunActivateExitError(a)); - } - }; + }; - info!("Activation succeeded!"); + if !dry_activate { + info!("Activation succeeded!"); + } - if magic_rollback { - info!("Magic rollback is enabled, setting up confirmation hook..."); + if magic_rollback { + info!("Magic rollback is enabled, setting up confirmation hook..."); - match activation_confirmation(profile_path.clone(), temp_path, confirm_timeout, closure) - .await - { - Ok(()) => {} - Err(err) => { - deactivate(&profile_path).await?; - return Err(ActivateError::ActivationConfirmationError(err)); - } - }; + match activation_confirmation(profile_path.clone(), temp_path, confirm_timeout, closure) + .await + { + Ok(()) => {} + Err(err) => { + deactivate(&profile_path).await?; + return Err(ActivateError::ActivationConfirmationError(err)); + } + }; + } } Ok(()) @@ -446,6 +456,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { opts.temp_path, activate_opts.confirm_timeout, activate_opts.magic_rollback, + activate_opts.dry_activate, ) .await .map_err(|x| Box::new(x) as Box<dyn std::error::Error>), diff --git a/src/bin/deploy.rs b/src/bin/deploy.rs index 9c41d25..10e0552 100644 --- a/src/bin/deploy.rs +++ b/src/bin/deploy.rs @@ -74,6 +74,9 @@ struct Opts { /// Where to store temporary files (only used by magic-rollback) #[clap(long)] temp_path: Option<String>, + /// Show what will be activated on the machines + #[clap(long)] + dry_activate: bool, } /// Returns if the available Nix installation supports flakes @@ -379,6 +382,7 @@ async fn run_deploy( extra_build_args: &[String], debug_logs: bool, log_dir: Option<String>, + dry_activate: bool, ) -> Result<(), RunDeployError> { let to_deploy: ToDeploy = match (&deploy_flake.node, &deploy_flake.profile) { (Some(node_name), Some(profile_name)) => { @@ -499,7 +503,7 @@ async fn run_deploy( } for (deploy_data, deploy_defs) in &parts { - deploy::deploy::deploy_profile(&deploy_data, &deploy_defs).await?; + deploy::deploy::deploy_profile(&deploy_data, &deploy_defs, dry_activate).await?; } Ok(()) @@ -546,6 +550,7 @@ async fn run() -> Result<(), RunError> { magic_rollback: opts.magic_rollback, temp_path: opts.temp_path, confirm_timeout: opts.confirm_timeout, + dry_activate: opts.dry_activate, }; let supports_flakes = test_flake_support().await.map_err(RunError::FlakeTest)?; @@ -574,6 +579,7 @@ async fn run() -> Result<(), RunError> { &opts.extra_build_args, opts.debug_logs, opts.log_dir, + opts.dry_activate, ) .await?; diff --git a/src/deploy.rs b/src/deploy.rs index f6871d2..f6cd4ef 100644 --- a/src/deploy.rs +++ b/src/deploy.rs @@ -18,6 +18,7 @@ struct ActivateCommandData<'a> { magic_rollback: bool, debug_logs: bool, log_dir: Option<&'a str>, + dry_activate: bool, } fn build_activate_command(data: ActivateCommandData) -> String { @@ -49,6 +50,10 @@ fn build_activate_command(data: ActivateCommandData) -> String { self_activate_command = format!("{} --auto-rollback", self_activate_command); } + if data.dry_activate { + self_activate_command = format!("{} --dry-activate", self_activate_command); + } + if let Some(sudo_cmd) = &data.sudo { self_activate_command = format!("{} {}", sudo_cmd, self_activate_command); } @@ -62,6 +67,7 @@ fn test_activation_command_builder() { let profile_path = "/blah/profiles/test"; let closure = "/nix/store/blah/etc"; let auto_rollback = true; + let dry_activate = false; let temp_path = "/tmp"; let confirm_timeout = 30; let magic_rollback = true; @@ -78,7 +84,8 @@ fn test_activation_command_builder() { confirm_timeout, magic_rollback, debug_logs, - log_dir + log_dir, + dry_activate }), "sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt --temp-path '/tmp' activate '/nix/store/blah/etc' '/blah/profiles/test' --confirm-timeout 30 --magic-rollback --auto-rollback" .to_string(), @@ -210,11 +217,14 @@ pub enum DeployProfileError { pub async fn deploy_profile( deploy_data: &super::DeployData<'_>, deploy_defs: &super::DeployDefs, + dry_activate: bool, ) -> Result<(), DeployProfileError> { - info!( - "Activating profile `{}` for node `{}`", - deploy_data.profile_name, deploy_data.node_name - ); + if !dry_activate { + info!( + "Activating profile `{}` for node `{}`", + deploy_data.profile_name, deploy_data.node_name + ); + } let temp_path: Cow<str> = match &deploy_data.merged_settings.temp_path { Some(x) => x.into(), @@ -227,6 +237,8 @@ pub async fn deploy_profile( let auto_rollback = deploy_data.merged_settings.auto_rollback.unwrap_or(true); + let dry_activate = dry_activate; + let self_activate_command = build_activate_command(ActivateCommandData { sudo: &deploy_defs.sudo, profile_path: &deploy_defs.profile_path, @@ -237,6 +249,7 @@ pub async fn deploy_profile( magic_rollback, debug_logs: deploy_data.debug_logs, log_dir: deploy_data.log_dir, + dry_activate, }); debug!("Constructed activation command: {}", self_activate_command); @@ -255,7 +268,7 @@ pub async fn deploy_profile( ssh_activate_command.arg(&ssh_opt); } - if !magic_rollback { + if !magic_rollback || dry_activate { let ssh_activate_exit_status = ssh_activate_command .arg(self_activate_command) .status() @@ -267,7 +280,9 @@ pub async fn deploy_profile( a => return Err(DeployProfileError::SSHActivateExitError(a)), }; - info!("Success activating, done!"); + if !dry_activate { + info!("Success activating, done!"); + } } else { let self_wait_command = build_wait_command(WaitCommandData { sudo: &deploy_defs.sudo, @@ -140,6 +140,7 @@ pub struct CmdOverrides { pub magic_rollback: Option<bool>, pub temp_path: Option<String>, pub confirm_timeout: Option<u16>, + pub dry_activate: bool, } #[derive(PartialEq, Debug)] |