From 70c55363a91572790ba5d49b70c58040f112e55c Mon Sep 17 00:00:00 2001
From: notgne2
Date: Fri, 8 Jan 2021 18:24:04 -0700
Subject: Restructure project
---
src/utils/data.rs | 73 ---------
src/utils/deploy.rs | 296 ------------------------------------
src/utils/mod.rs | 426 ----------------------------------------------------
src/utils/push.rs | 174 ---------------------
4 files changed, 969 deletions(-)
delete mode 100644 src/utils/data.rs
delete mode 100644 src/utils/deploy.rs
delete mode 100644 src/utils/mod.rs
delete mode 100644 src/utils/push.rs
(limited to 'src/utils')
diff --git a/src/utils/data.rs b/src/utils/data.rs
deleted file mode 100644
index f557e41..0000000
--- a/src/utils/data.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-FileCopyrightText: 2020 Serokell
-//
-// SPDX-License-Identifier: MPL-2.0
-
-use merge::Merge;
-
-use std::collections::HashMap;
-
-#[derive(Deserialize, Debug, Clone, Merge)]
-pub struct GenericSettings {
- #[serde(rename(deserialize = "sshUser"))]
- pub ssh_user: Option,
- pub user: Option,
- #[serde(
- skip_serializing_if = "Vec::is_empty",
- default,
- rename(deserialize = "sshOpts")
- )]
- #[merge(strategy = merge::vec::append)]
- pub ssh_opts: Vec,
- #[serde(rename(deserialize = "fastConnection"))]
- pub fast_connection: Option,
- #[serde(rename(deserialize = "autoRollback"))]
- pub auto_rollback: Option,
- #[serde(rename(deserialize = "confirmTimeout"))]
- pub confirm_timeout: Option,
- #[serde(rename(deserialize = "tempPath"))]
- pub temp_path: Option,
- #[serde(rename(deserialize = "magicRollback"))]
- pub magic_rollback: Option,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct NodeSettings {
- pub hostname: String,
- pub profiles: HashMap,
- #[serde(
- skip_serializing_if = "Vec::is_empty",
- default,
- rename(deserialize = "profilesOrder")
- )]
- pub profiles_order: Vec,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct ProfileSettings {
- pub path: String,
- #[serde(rename(deserialize = "profilePath"))]
- pub profile_path: Option,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct Profile {
- #[serde(flatten)]
- pub profile_settings: ProfileSettings,
- #[serde(flatten)]
- pub generic_settings: GenericSettings,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct Node {
- #[serde(flatten)]
- pub generic_settings: GenericSettings,
- #[serde(flatten)]
- pub node_settings: NodeSettings,
-}
-
-#[derive(Deserialize, Debug, Clone)]
-pub struct Data {
- #[serde(flatten)]
- pub generic_settings: GenericSettings,
- pub nodes: HashMap,
-}
diff --git a/src/utils/deploy.rs b/src/utils/deploy.rs
deleted file mode 100644
index 3371160..0000000
--- a/src/utils/deploy.rs
+++ /dev/null
@@ -1,296 +0,0 @@
-// SPDX-FileCopyrightText: 2020 Serokell
-// SPDX-FileCopyrightText: 2020 Andreas Fuchs
-//
-// SPDX-License-Identifier: MPL-2.0
-
-use std::borrow::Cow;
-use tokio::process::Command;
-
-use thiserror::Error;
-
-fn build_activate_command(
- sudo: &Option,
- profile_path: &str,
- closure: &str,
- auto_rollback: bool,
- temp_path: &Cow,
- confirm_timeout: u16,
- magic_rollback: bool,
- debug_logs: bool,
- log_dir: Option<&str>,
-) -> String {
- let mut self_activate_command = format!("{}/activate-rs", closure);
-
- if debug_logs {
- self_activate_command = format!("{} --debug-logs", self_activate_command);
- }
-
- if let Some(log_dir) = log_dir {
- self_activate_command = format!("{} --log-dir {}", self_activate_command, log_dir);
- }
-
- self_activate_command = format!(
- "{} --temp-path '{}' activate '{}' '{}'",
- self_activate_command, temp_path, closure, profile_path
- );
-
- self_activate_command = format!(
- "{} --confirm-timeout {}",
- self_activate_command, confirm_timeout
- );
-
- if magic_rollback {
- self_activate_command = format!("{} --magic-rollback", self_activate_command);
- }
-
- if auto_rollback {
- self_activate_command = format!("{} --auto-rollback", self_activate_command);
- }
-
- if let Some(sudo_cmd) = &sudo {
- self_activate_command = format!("{} {}", sudo_cmd, self_activate_command);
- }
-
- self_activate_command
-}
-
-#[test]
-fn test_activation_command_builder() {
- let sudo = Some("sudo -u test".to_string());
- let profile_path = "/blah/profiles/test";
- let closure = "/nix/store/blah/etc";
- let auto_rollback = true;
- let temp_path = &"/tmp".into();
- let confirm_timeout = 30;
- let magic_rollback = true;
- let debug_logs = true;
- let log_dir = Some("/tmp/something.txt");
-
- assert_eq!(
- build_activate_command(
- &sudo,
- profile_path,
- closure,
- auto_rollback,
- temp_path,
- confirm_timeout,
- magic_rollback,
- debug_logs,
- log_dir
- ),
- "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(),
- );
-}
-
-fn build_wait_command(
- sudo: &Option,
- closure: &str,
- temp_path: &Cow,
- debug_logs: bool,
- log_dir: Option<&str>,
-) -> String {
- let mut self_activate_command = format!("{}/activate-rs", closure);
-
- if debug_logs {
- self_activate_command = format!("{} --debug-logs", self_activate_command);
- }
-
- if let Some(log_dir) = log_dir {
- self_activate_command = format!("{} --log-dir {}", self_activate_command, log_dir);
- }
-
- self_activate_command = format!(
- "{} --temp-path '{}' wait '{}'",
- self_activate_command, temp_path, closure
- );
-
- if let Some(sudo_cmd) = &sudo {
- self_activate_command = format!("{} {}", sudo_cmd, self_activate_command);
- }
-
- self_activate_command
-}
-
-#[test]
-fn test_wait_command_builder() {
- let sudo = Some("sudo -u test".to_string());
- let closure = "/nix/store/blah/etc";
- let temp_path = &"/tmp".into();
- let debug_logs = true;
- let log_dir = Some("/tmp/something.txt");
-
- assert_eq!(
- build_wait_command(
- &sudo,
- closure,
- temp_path,
- debug_logs,
- log_dir
- ),
- "sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt --temp-path '/tmp' wait '/nix/store/blah/etc'"
- .to_string(),
- );
-}
-
-#[derive(Error, Debug)]
-pub enum DeployProfileError {
- #[error("Failed to calculate activate bin path from deploy bin path: {0}")]
- DeployPathToActivatePathError(#[from] super::DeployPathToActivatePathError),
-
- #[error("Failed to spawn activation command over SSH: {0}")]
- SSHSpawnActivateError(std::io::Error),
-
- #[error("Failed to run activation command over SSH: {0}")]
- SSHActivateError(std::io::Error),
- #[error("Activating over SSH resulted in a bad exit code: {0:?}")]
- SSHActivateExitError(Option),
-
- #[error("Failed to run wait command over SSH: {0}")]
- SSHWaitError(std::io::Error),
- #[error("Waiting over SSH resulted in a bad exit code: {0:?}")]
- SSHWaitExitError(Option),
-
- #[error("Failed to run confirmation command over SSH (the server should roll back): {0}")]
- SSHConfirmError(std::io::Error),
- #[error(
- "Confirming activation over SSH resulted in a bad exit code (the server should roll back): {0:?}"
- )]
- SSHConfirmExitError(Option),
-}
-
-pub async fn deploy_profile(
- deploy_data: &super::DeployData<'_>,
- deploy_defs: &super::DeployDefs,
-) -> Result<(), DeployProfileError> {
- info!(
- "Activating profile `{}` for node `{}`",
- deploy_data.profile_name, deploy_data.node_name
- );
-
- let temp_path: Cow = match &deploy_data.merged_settings.temp_path {
- Some(x) => x.into(),
- None => "/tmp".into(),
- };
-
- let confirm_timeout = deploy_data.merged_settings.confirm_timeout.unwrap_or(30);
-
- let magic_rollback = deploy_data.merged_settings.magic_rollback.unwrap_or(true);
-
- let auto_rollback = deploy_data.merged_settings.auto_rollback.unwrap_or(true);
-
- let self_activate_command = build_activate_command(
- &deploy_defs.sudo,
- &deploy_defs.profile_path,
- &deploy_data.profile.profile_settings.path,
- auto_rollback,
- &temp_path,
- confirm_timeout,
- magic_rollback,
- deploy_data.debug_logs,
- deploy_data.log_dir,
- );
-
- debug!("Constructed activation command: {}", self_activate_command);
-
- let self_wait_command = build_wait_command(
- &deploy_defs.sudo,
- &deploy_data.profile.profile_settings.path,
- &temp_path,
- deploy_data.debug_logs,
- deploy_data.log_dir,
- );
-
- debug!("Constructed wait command: {}", self_wait_command);
-
- let hostname = match deploy_data.cmd_overrides.hostname {
- Some(ref x) => x,
- None => &deploy_data.node.node_settings.hostname,
- };
-
- let ssh_addr = format!("ssh://{}@{}", deploy_defs.ssh_user, hostname);
-
- let mut ssh_activate_command_ = Command::new("ssh");
- let ssh_activate_command = ssh_activate_command_.arg(&ssh_addr);
-
- for ssh_opt in &deploy_data.merged_settings.ssh_opts {
- ssh_activate_command.arg(&ssh_opt);
- }
-
- if !magic_rollback {
- let ssh_activate_exit_status = ssh_activate_command
- .arg(self_activate_command)
- .status()
- .await
- .map_err(DeployProfileError::SSHActivateError)?;
-
- match ssh_activate_exit_status.code() {
- Some(0) => (),
- a => return Err(DeployProfileError::SSHActivateExitError(a)),
- };
-
- info!("Success activating, done!");
- } else {
- let ssh_activate = ssh_activate_command
- .arg(self_activate_command)
- .spawn()
- .map_err(DeployProfileError::SSHSpawnActivateError)?;
-
- info!("Creating activation waiter");
-
- let mut ssh_wait_command_ = Command::new("ssh");
- let ssh_wait_command = ssh_wait_command_.arg(&ssh_addr);
-
- for ssh_opt in &deploy_data.merged_settings.ssh_opts {
- ssh_wait_command.arg(ssh_opt);
- }
-
- let ssh_wait_exit_status = ssh_wait_command
- .arg(self_wait_command)
- .status()
- .await
- .map_err(DeployProfileError::SSHWaitError)?;
-
- match ssh_wait_exit_status.code() {
- Some(0) => (),
- a => return Err(DeployProfileError::SSHWaitExitError(a)),
- };
-
- info!("Success activating, attempting to confirm activation");
-
- let mut c = Command::new("ssh");
- let mut ssh_confirm_command = c.arg(format!("ssh://{}@{}", deploy_defs.ssh_user, hostname));
-
- for ssh_opt in &deploy_data.merged_settings.ssh_opts {
- ssh_confirm_command = ssh_confirm_command.arg(ssh_opt);
- }
-
- let lock_path =
- super::make_lock_path(&temp_path, &deploy_data.profile.profile_settings.path);
-
- let mut confirm_command = format!("rm {}", lock_path);
- if let Some(sudo_cmd) = &deploy_defs.sudo {
- confirm_command = format!("{} {}", sudo_cmd, confirm_command);
- }
-
- debug!(
- "Attempting to run command to confirm deployment: {}",
- confirm_command
- );
-
- let ssh_exit_status = ssh_confirm_command
- .arg(confirm_command)
- .status()
- .await
- .map_err(DeployProfileError::SSHConfirmError)?;
-
- match ssh_exit_status.code() {
- Some(0) => (),
- a => return Err(DeployProfileError::SSHConfirmExitError(a)),
- };
-
- info!("Deployment confirmed.");
- }
-
- Ok(())
-}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
deleted file mode 100644
index bc46f4c..0000000
--- a/src/utils/mod.rs
+++ /dev/null
@@ -1,426 +0,0 @@
-// SPDX-FileCopyrightText: 2020 Serokell
-// SPDX-FileCopyrightText: 2020 Andreas Fuchs
-//
-// SPDX-License-Identifier: MPL-2.0
-
-use rnix::{types::*, SyntaxKind::*};
-
-use merge::Merge;
-
-use thiserror::Error;
-
-use flexi_logger::*;
-
-#[macro_export]
-macro_rules! good_panic {
- ($($tts:tt)*) => {{
- error!($($tts)*);
- std::process::exit(1);
- }}
-}
-
-pub fn make_lock_path(temp_path: &str, closure: &str) -> String {
- let lock_hash =
- &closure["/nix/store/".len()..closure.find("-").unwrap_or_else(|| closure.len())];
- format!("{}/deploy-rs-canary-{}", temp_path, lock_hash)
-}
-
-fn make_emoji(level: log::Level) -> &'static str {
- match level {
- log::Level::Error => "❌",
- log::Level::Warn => "⚠️",
- log::Level::Info => "ℹ️",
- log::Level::Debug => "❓",
- log::Level::Trace => "🖊️",
- }
-}
-
-pub fn logger_formatter_activate(
- w: &mut dyn std::io::Write,
- _now: &mut DeferredNow,
- record: &Record,
-) -> Result<(), std::io::Error> {
- let level = record.level();
-
- write!(
- w,
- "⭐ {} [activate] [{}] {}",
- make_emoji(level),
- style(level, level.to_string()),
- record.args()
- )
-}
-
-pub fn logger_formatter_wait(
- w: &mut dyn std::io::Write,
- _now: &mut DeferredNow,
- record: &Record,
-) -> Result<(), std::io::Error> {
- let level = record.level();
-
- write!(
- w,
- "👀 {} [wait] [{}] {}",
- make_emoji(level),
- style(level, level.to_string()),
- record.args()
- )
-}
-
-pub fn logger_formatter_deploy(
- w: &mut dyn std::io::Write,
- _now: &mut DeferredNow,
- record: &Record,
-) -> Result<(), std::io::Error> {
- let level = record.level();
-
- write!(
- w,
- "🚀 {} [deploy] [{}] {}",
- make_emoji(level),
- style(level, level.to_string()),
- record.args()
- )
-}
-
-pub enum LoggerType {
- Deploy,
- Activate,
- Wait,
-}
-
-pub fn init_logger(
- debug_logs: bool,
- log_dir: Option<&str>,
- logger_type: LoggerType,
-) -> Result<(), FlexiLoggerError> {
- let logger_formatter = match logger_type {
- LoggerType::Deploy => logger_formatter_deploy,
- LoggerType::Activate => logger_formatter_activate,
- LoggerType::Wait => logger_formatter_wait,
- };
-
- if let Some(log_dir) = log_dir {
- let mut logger = Logger::with_env_or_str("debug")
- .log_to_file()
- .format_for_stderr(logger_formatter)
- .set_palette("196;208;51;7;8".to_string())
- .directory(log_dir)
- .duplicate_to_stderr(match debug_logs {
- true => Duplicate::Debug,
- false => Duplicate::Info,
- })
- .print_message();
-
- match logger_type {
- LoggerType::Activate => logger = logger.discriminant("activate"),
- LoggerType::Wait => logger = logger.discriminant("wait"),
- LoggerType::Deploy => (),
- }
-
- logger.start()?;
- } else {
- Logger::with_env_or_str(match debug_logs {
- true => "debug",
- false => "info",
- })
- .log_target(LogTarget::StdErr)
- .format(logger_formatter)
- .set_palette("196;208;51;7;8".to_string())
- .start()?;
- }
-
- Ok(())
-}
-
-pub mod data;
-pub mod deploy;
-pub mod push;
-
-#[derive(Debug)]
-pub struct CmdOverrides {
- pub ssh_user: Option,
- pub profile_user: Option,
- pub ssh_opts: Option,
- pub fast_connection: Option,
- pub auto_rollback: Option,
- pub hostname: Option,
- pub magic_rollback: Option,
- pub temp_path: Option,
- pub confirm_timeout: Option,
-}
-
-#[derive(PartialEq, Debug)]
-pub struct DeployFlake<'a> {
- pub repo: &'a str,
- pub node: Option,
- pub profile: Option,
-}
-
-#[derive(Error, Debug)]
-pub enum ParseFlakeError {
- #[error("The given path was too long, did you mean to put something in quotes?")]
- PathTooLong,
- #[error("Unrecognized node or token encountered")]
- Unrecognized,
-}
-pub fn parse_flake(flake: &str) -> Result {
- let flake_fragment_start = flake.find('#');
- let (repo, maybe_fragment) = match flake_fragment_start {
- Some(s) => (&flake[..s], Some(&flake[s + 1..])),
- None => (flake, None),
- };
-
- let mut node: Option = None;
- let mut profile: Option = None;
-
- if let Some(fragment) = maybe_fragment {
- let ast = rnix::parse(fragment);
-
- let first_child = match ast.root().node().first_child() {
- Some(x) => x,
- None => {
- return Ok(DeployFlake {
- repo,
- node: None,
- profile: None,
- })
- }
- };
-
- let mut node_over = false;
-
- for entry in first_child.children_with_tokens() {
- let x: Option = match (entry.kind(), node_over) {
- (TOKEN_DOT, false) => {
- node_over = true;
- None
- }
- (TOKEN_DOT, true) => {
- return Err(ParseFlakeError::PathTooLong);
- }
- (NODE_IDENT, _) => Some(entry.into_node().unwrap().text().to_string()),
- (TOKEN_IDENT, _) => Some(entry.into_token().unwrap().text().to_string()),
- (NODE_STRING, _) => {
- let c = entry
- .into_node()
- .unwrap()
- .children_with_tokens()
- .nth(1)
- .unwrap();
-
- Some(c.into_token().unwrap().text().to_string())
- }
- _ => return Err(ParseFlakeError::Unrecognized),
- };
-
- if !node_over {
- node = x;
- } else {
- profile = x;
- }
- }
- }
-
- Ok(DeployFlake {
- repo,
- node,
- profile,
- })
-}
-
-#[test]
-fn test_parse_flake() {
- assert_eq!(
- parse_flake("../deploy/examples/system").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: None,
- profile: None,
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system#").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: None,
- profile: None,
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system#computer.\"something.nix\"").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: Some("computer".to_string()),
- profile: Some("something.nix".to_string()),
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system#\"example.com\".system").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: Some("example.com".to_string()),
- profile: Some("system".to_string()),
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system#example").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: Some("example".to_string()),
- profile: None
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system#example.system").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: Some("example".to_string()),
- profile: Some("system".to_string())
- }
- );
-
- assert_eq!(
- parse_flake("../deploy/examples/system").unwrap(),
- DeployFlake {
- repo: "../deploy/examples/system",
- node: None,
- profile: None,
- }
- );
-}
-
-#[derive(Debug, Clone)]
-pub struct DeployData<'a> {
- pub node_name: &'a str,
- pub node: &'a data::Node,
- pub profile_name: &'a str,
- pub profile: &'a data::Profile,
-
- pub cmd_overrides: &'a CmdOverrides,
-
- pub merged_settings: data::GenericSettings,
-
- pub debug_logs: bool,
- pub log_dir: Option<&'a str>,
-}
-
-#[derive(Debug)]
-pub struct DeployDefs {
- pub ssh_user: String,
- pub profile_user: String,
- pub profile_path: String,
- pub sudo: Option,
-}
-
-#[derive(Error, Debug)]
-pub enum DeployDataDefsError {
- #[error("Neither `user` nor `sshUser` are set for profile {0} of node {1}")]
- NoProfileUser(String, String),
-}
-
-impl<'a> DeployData<'a> {
- pub fn defs(&'a self) -> Result {
- let ssh_user = match self.merged_settings.ssh_user {
- Some(ref u) => u.clone(),
- None => whoami::username(),
- };
-
- let profile_user = match self.merged_settings.user {
- Some(ref x) => x.clone(),
- None => match self.merged_settings.ssh_user {
- Some(ref x) => x.clone(),
- None => {
- return Err(DeployDataDefsError::NoProfileUser(
- self.profile_name.to_owned(),
- self.node_name.to_owned(),
- ))
- }
- },
- };
-
- let profile_path = match self.profile.profile_settings.profile_path {
- None => match &profile_user[..] {
- "root" => format!("/nix/var/nix/profiles/{}", self.profile_name),
- _ => format!(
- "/nix/var/nix/profiles/per-user/{}/{}",
- profile_user, self.profile_name
- ),
- },
- Some(ref x) => x.clone(),
- };
-
- let sudo: Option = match self.merged_settings.user {
- Some(ref user) if user != &ssh_user => Some(format!("sudo -u {}", user)),
- _ => None,
- };
-
- Ok(DeployDefs {
- ssh_user,
- profile_user,
- profile_path,
- sudo,
- })
- }
-}
-
-pub fn make_deploy_data<'a, 's>(
- top_settings: &'s data::GenericSettings,
- node: &'a data::Node,
- node_name: &'a str,
- profile: &'a data::Profile,
- profile_name: &'a str,
- cmd_overrides: &'a CmdOverrides,
- debug_logs: bool,
- log_dir: Option<&'a str>,
-) -> DeployData<'a> {
- let mut merged_settings = profile.generic_settings.clone();
- merged_settings.merge(node.generic_settings.clone());
- merged_settings.merge(top_settings.clone());
-
- if cmd_overrides.ssh_user.is_some() {
- merged_settings.ssh_user = cmd_overrides.ssh_user.clone();
- }
- if cmd_overrides.profile_user.is_some() {
- merged_settings.user = cmd_overrides.profile_user.clone();
- }
- if let Some(ref ssh_opts) = cmd_overrides.ssh_opts {
- merged_settings.ssh_opts = ssh_opts.split(' ').map(|x| x.to_owned()).collect();
- }
- if let Some(fast_connection) = cmd_overrides.fast_connection {
- merged_settings.fast_connection = Some(fast_connection);
- }
- if let Some(auto_rollback) = cmd_overrides.auto_rollback {
- merged_settings.auto_rollback = Some(auto_rollback);
- }
- if let Some(magic_rollback) = cmd_overrides.magic_rollback {
- merged_settings.magic_rollback = Some(magic_rollback);
- }
-
- DeployData {
- profile,
- profile_name,
- node,
- node_name,
-
- cmd_overrides,
-
- merged_settings,
-
- debug_logs,
- log_dir,
- }
-}
-
-#[derive(Error, Debug)]
-pub enum DeployPathToActivatePathError {
- #[error("Deploy path did not have a parent directory")]
- PathTooShort,
- #[error("Deploy path was not valid utf8")]
- InvalidUtf8,
-}
diff --git a/src/utils/push.rs b/src/utils/push.rs
deleted file mode 100644
index 503e062..0000000
--- a/src/utils/push.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-FileCopyrightText: 2020 Serokell
-//
-// SPDX-License-Identifier: MPL-2.0
-
-use std::process::Stdio;
-use tokio::process::Command;
-use std::path::Path;
-
-use thiserror::Error;
-
-#[derive(Error, Debug)]
-pub enum PushProfileError {
- #[error("Failed to calculate activate bin path from deploy bin path: {0}")]
- DeployPathToActivatePathError(#[from] super::DeployPathToActivatePathError),
- #[error("Failed to run Nix build command: {0}")]
- BuildError(std::io::Error),
- #[error("Nix build command resulted in a bad exit code: {0:?}")]
- BuildExitError(Option),
- #[error("Activation script deploy-rs-activate does not exist in profile.\n\
- Did you forget to use deploy-rs#lib.<...>.activate.<...> on your profile path?")]
- DeployRsActivateDoesntExist,
- #[error("Activation script activate-rs does not exist in profile.\n\
- Is there a mismatch in deploy-rs used in the flake you're deploying and deploy-rs command you're running?")]
- ActivateRsDoesntExist,
- #[error("Failed to run Nix sign command: {0}")]
- SignError(std::io::Error),
- #[error("Nix sign command resulted in a bad exit code: {0:?}")]
- SignExitError(Option),
- #[error("Failed to run Nix copy command: {0}")]
- CopyError(std::io::Error),
- #[error("Nix copy command resulted in a bad exit code: {0:?}")]
- CopyExitError(Option),
-}
-
-pub async fn push_profile(
- supports_flakes: bool,
- check_sigs: bool,
- repo: &str,
- deploy_data: &super::DeployData<'_>,
- deploy_defs: &super::DeployDefs,
- keep_result: bool,
- result_path: Option<&str>,
- extra_build_args: &[String],
-) -> Result<(), PushProfileError> {
- info!(
- "Building profile `{}` for node `{}`",
- deploy_data.profile_name, deploy_data.node_name
- );
-
- let mut build_c = if supports_flakes {
- Command::new("nix")
- } else {
- Command::new("nix-build")
- };
-
- let mut build_command = if supports_flakes {
- build_c.arg("build").arg(format!(
- "{}#deploy.nodes.\"{}\".profiles.\"{}\".path",
- repo, deploy_data.node_name, deploy_data.profile_name
- ))
- } else {
- build_c.arg(&repo).arg("-A").arg(format!(
- "deploy.nodes.\"{}\".profiles.\"{}\".path",
- deploy_data.node_name, deploy_data.profile_name
- ))
- };
-
- build_command = match (keep_result, supports_flakes) {
- (true, _) => {
- let result_path = result_path.unwrap_or("./.deploy-gc");
-
- build_command.arg("--out-link").arg(format!(
- "{}/{}/{}",
- result_path, deploy_data.node_name, deploy_data.profile_name
- ))
- }
- (false, false) => build_command.arg("--no-out-link"),
- (false, true) => build_command.arg("--no-link"),
- };
-
- for extra_arg in extra_build_args {
- build_command = build_command.arg(extra_arg);
- }
-
- let build_exit_status = build_command
- // Logging should be in stderr, this just stops the store path from printing for no reason
- .stdout(Stdio::null())
- .status()
- .await
- .map_err(PushProfileError::BuildError)?;
-
- match build_exit_status.code() {
- Some(0) => (),
- a => return Err(PushProfileError::BuildExitError(a)),
- };
-
- if ! Path::new(format!("{}/deploy-rs-activate", deploy_data.profile.profile_settings.path).as_str()).exists() {
- return Err(PushProfileError::DeployRsActivateDoesntExist);
- }
-
- if ! Path::new(format!("{}/activate-rs", deploy_data.profile.profile_settings.path).as_str()).exists() {
- return Err(PushProfileError::ActivateRsDoesntExist);
- }
-
-
-
- if let Ok(local_key) = std::env::var("LOCAL_KEY") {
- info!(
- "Signing key present! Signing profile `{}` for node `{}`",
- deploy_data.profile_name, deploy_data.node_name
- );
-
- let sign_exit_status = Command::new("nix")
- .arg("sign-paths")
- .arg("-r")
- .arg("-k")
- .arg(local_key)
- .arg(&deploy_data.profile.profile_settings.path)
- .status()
- .await
- .map_err(PushProfileError::SignError)?;
-
- match sign_exit_status.code() {
- Some(0) => (),
- a => return Err(PushProfileError::SignExitError(a)),
- };
- }
-
- debug!(
- "Copying profile `{}` to node `{}`",
- deploy_data.profile_name, deploy_data.node_name
- );
-
- let mut copy_command_ = Command::new("nix");
- let mut copy_command = copy_command_.arg("copy");
-
- if deploy_data.merged_settings.fast_connection != Some(true) {
- copy_command = copy_command.arg("--substitute-on-destination");
- }
-
- if !check_sigs {
- copy_command = copy_command.arg("--no-check-sigs");
- }
-
- let ssh_opts_str = deploy_data
- .merged_settings
- .ssh_opts
- // This should provide some extra safety, but it also breaks for some reason, oh well
- // .iter()
- // .map(|x| format!("'{}'", x))
- // .collect::>()
- .join(" ");
-
- let hostname = match deploy_data.cmd_overrides.hostname {
- Some(ref x) => x,
- None => &deploy_data.node.node_settings.hostname,
- };
-
- let copy_exit_status = copy_command
- .arg("--to")
- .arg(format!("ssh://{}@{}", deploy_defs.ssh_user, hostname))
- .arg(&deploy_data.profile.profile_settings.path)
- .env("NIX_SSHOPTS", ssh_opts_str)
- .status()
- .await
- .map_err(PushProfileError::CopyError)?;
-
- match copy_exit_status.code() {
- Some(0) => (),
- a => return Err(PushProfileError::CopyExitError(a)),
- };
-
- Ok(())
-}
--
cgit v1.2.3