aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/activate.rs54
-rw-r--r--src/main.rs220
-rw-r--r--src/utils/data.rs10
-rw-r--r--src/utils/deploy.rs17
-rw-r--r--src/utils/push.rs2
5 files changed, 163 insertions, 140 deletions
diff --git a/src/activate.rs b/src/activate.rs
new file mode 100644
index 0000000..c446ee0
--- /dev/null
+++ b/src/activate.rs
@@ -0,0 +1,54 @@
+use clap::Clap;
+
+extern crate pretty_env_logger;
+#[macro_use]
+extern crate log;
+
+#[macro_use]
+extern crate serde_derive;
+
+#[macro_use]
+mod utils;
+
+/// Activation portion of the simple Rust Nix deploy tool
+#[derive(Clap, Debug)]
+#[clap(version = "1.0", author = "notgne2 <gen2@gen2.space>")]
+struct Opts {
+ profile_path: String,
+ closure: String,
+
+ /// Command for activating the given profile
+ #[clap(long)]
+ activate_cmd: Option<String>,
+
+ /// Command for bootstrapping
+ #[clap(long)]
+ bootstrap_cmd: Option<String>,
+
+ /// Auto rollback if failure
+ #[clap(long)]
+ auto_rollback: bool,
+}
+
+
+#[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();
+
+ utils::activate::activate(
+ opts.profile_path,
+ opts.closure,
+ opts.activate_cmd,
+ opts.bootstrap_cmd,
+ opts.auto_rollback,
+ )
+ .await?;
+
+ Ok(())
+} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index e084f0f..6dcb885 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,17 +19,6 @@ mod utils;
#[derive(Clap, Debug)]
#[clap(version = "1.0", author = "notgne2 <gen2@gen2.space>")]
struct Opts {
- /// Log verbosity
- #[clap(short, long, parse(from_occurrences))]
- verbose: i32,
-
- #[clap(subcommand)]
- subcmd: SubCommand,
-}
-
-/// Deploy profiles
-#[derive(Clap, Debug)]
-struct DeployOpts {
/// The flake to deploy
#[clap(default_value = ".")]
flake: String,
@@ -38,31 +27,6 @@ struct DeployOpts {
checksigs: bool,
}
-/// Activate a profile on your current machine
-#[derive(Clap, Debug)]
-struct ActivateOpts {
- profile_path: String,
- closure: String,
-
- /// Command for activating the given profile
- #[clap(short, long)]
- activate_cmd: Option<String>,
-
- /// Command for bootstrapping
- #[clap(short, long)]
- bootstrap_cmd: Option<String>,
-
- /// Auto rollback if failure
- #[clap(short, long)]
- auto_rollback: bool,
-}
-
-#[derive(Clap, Debug)]
-enum SubCommand {
- Deploy(DeployOpts),
- Activate(ActivateOpts),
-}
-
#[inline]
async fn push_all_profiles(
node: &utils::data::Node,
@@ -150,6 +114,7 @@ async fn deploy_all_profiles(
node_name,
&merged_settings,
&deploy_data,
+ merged_settings.auto_rollback,
)
.await?;
}
@@ -157,6 +122,7 @@ async fn deploy_all_profiles(
Ok(())
}
+/// Returns if the available Nix installation supports flakes
async fn test_flake_support() -> Result<bool, Box<dyn std::error::Error>> {
Ok(Command::new("nix")
.arg("eval")
@@ -169,6 +135,7 @@ async fn test_flake_support() -> Result<bool, Box<dyn std::error::Error>> {
.success())
}
+/// Evaluates the Nix in the given `repo` and return the processed Data from it
async fn get_deployment_data(
supports_flakes: bool,
repo: &str,
@@ -216,108 +183,95 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let opts: Opts = Opts::parse();
- match opts.subcmd {
- SubCommand::Deploy(deploy_opts) => {
- let deploy_flake = utils::parse_flake(deploy_opts.flake.as_str());
-
- let supports_flakes = test_flake_support().await?;
-
- let data = get_deployment_data(supports_flakes, deploy_flake.repo).await?;
-
- match (deploy_flake.node, deploy_flake.profile) {
- (Some(node_name), Some(profile_name)) => {
- let node = match data.nodes.get(node_name) {
- Some(x) => x,
- None => good_panic!("No node was found named `{}`", node_name),
- };
- let profile = match node.profiles.get(profile_name) {
- Some(x) => x,
- None => good_panic!("No profile was found named `{}`", profile_name),
- };
-
- let mut merged_settings = data.generic_settings.clone();
- merged_settings.merge(node.generic_settings.clone());
- merged_settings.merge(profile.generic_settings.clone());
-
- let deploy_data =
- utils::make_deploy_data(profile_name, node_name, &merged_settings).await?;
-
- utils::push::push_profile(
- profile,
- profile_name,
- node,
- node_name,
- supports_flakes,
- deploy_opts.checksigs,
- deploy_flake.repo,
- &merged_settings,
- &deploy_data,
- )
- .await?;
-
- utils::deploy::deploy_profile(
- profile,
- profile_name,
- node,
- node_name,
- &merged_settings,
- &deploy_data,
- )
- .await?;
- }
- (Some(node_name), None) => {
- let node = match data.nodes.get(node_name) {
- Some(x) => x,
- None => good_panic!("No node was found named `{}`", node_name),
- };
-
- push_all_profiles(
- node,
- node_name,
- supports_flakes,
- deploy_flake.repo,
- &data.generic_settings,
- deploy_opts.checksigs,
- )
- .await?;
-
- deploy_all_profiles(node, node_name, &data.generic_settings).await?;
- }
- (None, None) => {
- info!("Deploying all profiles on all nodes");
-
- for (node_name, node) in &data.nodes {
- push_all_profiles(
- node,
- node_name,
- supports_flakes,
- deploy_flake.repo,
- &data.generic_settings,
- deploy_opts.checksigs,
- )
- .await?;
- }
-
- for (node_name, node) in &data.nodes {
- deploy_all_profiles(node, node_name, &data.generic_settings).await?;
- }
- }
- (None, Some(_)) => good_panic!(
- "Profile provided without a node, this is not (currently) supported"
- ),
+ 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).await?;
+
+ match (deploy_flake.node, deploy_flake.profile) {
+ (Some(node_name), Some(profile_name)) => {
+ let node = match data.nodes.get(node_name) {
+ Some(x) => x,
+ None => good_panic!("No node was found named `{}`", node_name),
+ };
+ let profile = match node.profiles.get(profile_name) {
+ Some(x) => x,
+ None => good_panic!("No profile was found named `{}`", profile_name),
};
+
+ let mut merged_settings = data.generic_settings.clone();
+ merged_settings.merge(node.generic_settings.clone());
+ merged_settings.merge(profile.generic_settings.clone());
+
+ let deploy_data =
+ utils::make_deploy_data(profile_name, node_name, &merged_settings).await?;
+
+ utils::push::push_profile(
+ profile,
+ profile_name,
+ node,
+ node_name,
+ supports_flakes,
+ opts.checksigs,
+ deploy_flake.repo,
+ &merged_settings,
+ &deploy_data,
+ )
+ .await?;
+
+ utils::deploy::deploy_profile(
+ profile,
+ profile_name,
+ node,
+ node_name,
+ &merged_settings,
+ &deploy_data,
+ merged_settings.auto_rollback,
+ )
+ .await?;
}
- SubCommand::Activate(activate_opts) => {
- utils::activate::activate(
- activate_opts.profile_path,
- activate_opts.closure,
- activate_opts.activate_cmd,
- activate_opts.bootstrap_cmd,
- activate_opts.auto_rollback,
+ (Some(node_name), None) => {
+ let node = match data.nodes.get(node_name) {
+ Some(x) => x,
+ None => good_panic!("No node was found named `{}`", node_name),
+ };
+
+ push_all_profiles(
+ node,
+ node_name,
+ supports_flakes,
+ deploy_flake.repo,
+ &data.generic_settings,
+ opts.checksigs,
)
.await?;
+
+ deploy_all_profiles(node, node_name, &data.generic_settings).await?;
}
- }
+ (None, None) => {
+ info!("Deploying all profiles on all nodes");
+
+ for (node_name, node) in &data.nodes {
+ push_all_profiles(
+ node,
+ node_name,
+ supports_flakes,
+ deploy_flake.repo,
+ &data.generic_settings,
+ opts.checksigs,
+ )
+ .await?;
+ }
+
+ for (node_name, node) in &data.nodes {
+ deploy_all_profiles(node, node_name, &data.generic_settings).await?;
+ }
+ }
+ (None, Some(_)) => {
+ good_panic!("Profile provided without a node, this is not (currently) supported")
+ }
+ };
Ok(())
}
diff --git a/src/utils/data.rs b/src/utils/data.rs
index b28b6cd..0753508 100644
--- a/src/utils/data.rs
+++ b/src/utils/data.rs
@@ -14,10 +14,12 @@ pub struct GenericSettings {
)]
#[merge(strategy = merge::vec::append)]
pub ssh_opts: Vec<String>,
- #[serde(rename(deserialize = "fastConnection"))]
- pub fast_connection: Option<bool>,
- #[serde(rename(deserialize = "autoRollback"))]
- pub auto_rollback: Option<String>,
+ #[serde(rename(deserialize = "fastConnection"), default)]
+ #[merge(strategy = merge::bool::overwrite_false)]
+ pub fast_connection: bool,
+ #[serde(rename(deserialize = "autoRollback"), default)]
+ #[merge(strategy = merge::bool::overwrite_false)]
+ pub auto_rollback: bool,
}
#[derive(Deserialize, Debug, Clone)]
diff --git a/src/utils/deploy.rs b/src/utils/deploy.rs
index 900743c..42bd0b4 100644
--- a/src/utils/deploy.rs
+++ b/src/utils/deploy.rs
@@ -9,6 +9,7 @@ pub async fn deploy_profile(
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 `{}`",
@@ -16,8 +17,16 @@ pub async fn deploy_profile(
);
let mut self_activate_command = format!(
- "{} activate '{}' '{}'",
- deploy_data.current_exe.as_path().to_str().unwrap(),
+ "{} '{}' '{}'",
+ deploy_data
+ .current_exe
+ .as_path()
+ .parent()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .to_owned()
+ + "/activate",
deploy_data.profile_path,
profile.profile_settings.path,
);
@@ -40,6 +49,10 @@ pub async fn deploy_profile(
);
}
+ if auto_rollback {
+ self_activate_command = format!("{} --auto-rollback", self_activate_command);
+ }
+
let mut c = Command::new("ssh");
let mut ssh_command = c.arg(format!(
"ssh://{}@{}",
diff --git a/src/utils/push.rs b/src/utils/push.rs
index 54ae013..0e1b9ba 100644
--- a/src/utils/push.rs
+++ b/src/utils/push.rs
@@ -74,7 +74,7 @@ pub async fn push_profile(
let mut copy_command_ = Command::new("nix");
let mut copy_command = copy_command_.arg("copy");
- if let Some(true) = merged_settings.fast_connection {
+ if merged_settings.fast_connection {
copy_command = copy_command.arg("--substitute-on-destination");
}