aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs57
-rw-r--r--src/utils/deploy.rs116
2 files changed, 122 insertions, 51 deletions
diff --git a/src/main.rs b/src/main.rs
index 668b697..f8b03a3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -143,7 +143,7 @@ async fn test_flake_support() -> Result<bool, Box<dyn std::error::Error>> {
async fn get_deployment_data(
supports_flakes: bool,
repo: &str,
- extra_build_args: Vec<String>,
+ extra_build_args: &[String],
) -> Result<utils::data::Data, Box<dyn std::error::Error>> {
let mut c = match supports_flakes {
true => Command::new("nix"),
@@ -156,12 +156,12 @@ async fn get_deployment_data(
}
false => {
c
- .arg("--strict")
- .arg("--read-write-mode")
- .arg("--json")
- .arg("--eval")
- .arg("--E")
- .arg(format!("let r = import {}/.; in if builtins.isFunction r then (r {{}}).deploy else r.deploy", repo))
+ .arg("--strict")
+ .arg("--read-write-mode")
+ .arg("--json")
+ .arg("--eval")
+ .arg("--E")
+ .arg(format!("let r = import {}/.; in if builtins.isFunction r then (r {{}}).deploy else r.deploy", repo))
}
};
@@ -186,23 +186,13 @@ async fn get_deployment_data(
Ok(serde_json::from_str(&data_json)?)
}
-#[tokio::main]
-async fn main() -> Result<(), Box<dyn std::error::Error>> {
- if std::env::var("DEPLOY_LOG").is_err() {
- std::env::set_var("DEPLOY_LOG", "info");
- }
-
- pretty_env_logger::init_custom_env("DEPLOY_LOG");
-
- let opts: Opts = Opts::parse();
-
- let deploy_flake = utils::parse_flake(opts.flake.as_str());
-
- let supports_flakes = test_flake_support().await?;
-
- let data =
- get_deployment_data(supports_flakes, deploy_flake.repo, opts.extra_build_args).await?;
+async fn run_deploy(
+ deploy_flake: utils::DeployFlake<'_>,
+ data: utils::data::Data,
+ supports_flakes: bool,
+ opts: &Opts,
+) -> Result<(), Box<dyn std::error::Error>> {
match (deploy_flake.node, deploy_flake.profile) {
(Some(node_name), Some(profile_name)) => {
let node = match data.nodes.get(node_name) {
@@ -289,3 +279,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ if std::env::var("DEPLOY_LOG").is_err() {
+ std::env::set_var("DEPLOY_LOG", "info");
+ }
+
+ pretty_env_logger::init_custom_env("DEPLOY_LOG");
+
+ let opts: Opts = Opts::parse();
+
+ let deploy_flake = utils::parse_flake(opts.flake.as_str());
+
+ let supports_flakes = test_flake_support().await?;
+
+ let data =
+ get_deployment_data(supports_flakes, deploy_flake.repo, &opts.extra_build_args).await?;
+
+ run_deploy(deploy_flake, data, supports_flakes, &opts).await?;
+
+ Ok(())
+}
diff --git a/src/utils/deploy.rs b/src/utils/deploy.rs
index 42bd0b4..c44c0d3 100644
--- a/src/utils/deploy.rs
+++ b/src/utils/deploy.rs
@@ -2,47 +2,54 @@ use super::data;
use tokio::process::Command;
-pub async fn deploy_profile(
- profile: &data::Profile,
- profile_name: &str,
- node: &data::Node,
- node_name: &str,
- merged_settings: &data::GenericSettings,
- deploy_data: &super::DeployData<'_>,
- auto_rollback: bool,
-) -> Result<(), Box<dyn std::error::Error>> {
- info!(
- "Activating profile `{}` for node `{}`",
- profile_name, node_name
- );
-
- let mut self_activate_command = format!(
- "{} '{}' '{}'",
- deploy_data
- .current_exe
- .as_path()
+fn deploy_path_to_activate_path_str(
+ deploy_path: &std::path::Path,
+) -> Result<String, Box<dyn std::error::Error>> {
+ Ok(format!(
+ "{}/activate",
+ deploy_path
.parent()
- .unwrap()
+ .ok_or("Deploy path too short")?
.to_str()
- .unwrap()
+ .ok_or("Deploy path is not valid utf8")?
.to_owned()
- + "/activate",
- deploy_data.profile_path,
- profile.profile_settings.path,
- );
+ ))
+}
- if let Some(sudo_cmd) = &deploy_data.sudo {
+#[test]
+fn test_activate_path_generation() {
+ match deploy_path_to_activate_path_str(&std::path::PathBuf::from(
+ "/blah/blah/deploy-rs/bin/deploy",
+ )) {
+ Err(_) => panic!(""),
+ Ok(x) => assert_eq!(x, "/blah/blah/deploy-rs/bin/activate".to_string()),
+ }
+}
+
+fn build_activate_command(
+ activate_path_str: String,
+ sudo: &Option<String>,
+ profile_path: &str,
+ closure: &str,
+ activate_cmd: &Option<String>,
+ bootstrap_cmd: &Option<String>,
+ auto_rollback: bool,
+) -> Result<String, Box<dyn std::error::Error>> {
+ let mut self_activate_command =
+ format!("{} '{}' '{}'", activate_path_str, profile_path, closure);
+
+ if let Some(sudo_cmd) = &sudo {
self_activate_command = format!("{} {}", sudo_cmd, self_activate_command);
}
- if let Some(ref bootstrap_cmd) = profile.profile_settings.bootstrap {
+ if let Some(ref bootstrap_cmd) = bootstrap_cmd {
self_activate_command = format!(
"{} --bootstrap-cmd '{}'",
self_activate_command, bootstrap_cmd
);
}
- if let Some(ref activate_cmd) = profile.profile_settings.activate {
+ if let Some(ref activate_cmd) = activate_cmd {
self_activate_command = format!(
"{} --activate-cmd '{}'",
self_activate_command, activate_cmd
@@ -53,6 +60,59 @@ pub async fn deploy_profile(
self_activate_command = format!("{} --auto-rollback", self_activate_command);
}
+ Ok(self_activate_command)
+}
+
+#[test]
+fn test_activation_command_builder() {
+ let activate_path_str = "/blah/bin/activate".to_string();
+ let sudo = Some("sudo -u test".to_string());
+ let profile_path = "/blah/profiles/test";
+ let closure = "/blah/etc";
+ let activate_cmd = Some("$THING/bin/aaaaaaa".to_string());
+ let bootstrap_cmd = None;
+ let auto_rollback = true;
+
+ match build_activate_command(
+ activate_path_str,
+ &sudo,
+ profile_path,
+ closure,
+ &activate_cmd,
+ &bootstrap_cmd,
+ auto_rollback,
+ ) {
+ Err(_) => panic!(""),
+ Ok(x) => assert_eq!(x, "sudo -u test /blah/bin/activate '/blah/profiles/test' '/blah/etc' --activate-cmd '$THING/bin/aaaaaaa' --auto-rollback".to_string()),
+ }
+}
+
+pub async fn deploy_profile(
+ profile: &data::Profile,
+ profile_name: &str,
+ node: &data::Node,
+ node_name: &str,
+ merged_settings: &data::GenericSettings,
+ deploy_data: &super::DeployData<'_>,
+ auto_rollback: bool,
+) -> Result<(), Box<dyn std::error::Error>> {
+ info!(
+ "Activating profile `{}` for node `{}`",
+ profile_name, node_name
+ );
+
+ let activate_path_str = deploy_path_to_activate_path_str(&deploy_data.current_exe)?;
+
+ let self_activate_command = build_activate_command(
+ activate_path_str,
+ &deploy_data.sudo,
+ &deploy_data.profile_path,
+ &profile.profile_settings.path,
+ &profile.profile_settings.activate,
+ &profile.profile_settings.bootstrap,
+ auto_rollback,
+ )?;
+
let mut c = Command::new("ssh");
let mut ssh_command = c.arg(format!(
"ssh://{}@{}",