mirror of
https://github.com/serokell/deploy-rs.git
synced 2024-09-11 02:35:39 +03:00
Merge pull request #231 from serokell/rvem/#201-dont-hardcode-profile-directory
[#201] Deduce profile directory during activation
This commit is contained in:
commit
31c32fb295
163
Cargo.lock
generated
163
Cargo.lock
generated
@ -131,6 +131,7 @@ name = "deploy-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"dirs",
|
||||
"flexi_logger",
|
||||
"fork",
|
||||
"futures-util",
|
||||
@ -149,6 +150,27 @@ dependencies = [
|
||||
"yn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.13"
|
||||
@ -157,7 +179,7 @@ checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.1.57",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@ -238,6 +260,17 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
@ -332,9 +365,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.141"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
@ -470,6 +503,12 @@ version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "2.4.0"
|
||||
@ -568,6 +607,26 @@ version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall 0.2.16",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.3"
|
||||
@ -698,7 +757,7 @@ checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.1.57",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@ -925,13 +984,13 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -940,7 +999,16 @@ version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -949,13 +1017,28 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -964,42 +1047,84 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.0"
|
||||
|
@ -12,6 +12,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3.0.0-beta.2", features = [ "wrap_help" ] }
|
||||
dirs = "5.0.1"
|
||||
flexi_logger = "0.16"
|
||||
fork = "0.1"
|
||||
futures-util = "0.3.6"
|
||||
|
@ -125,8 +125,11 @@ This is the core of how `deploy-rs` was designed, any number of these can run on
|
||||
path = deploy-rs.lib.x86_64-linux.activate.custom pkgs.hello "./bin/hello";
|
||||
|
||||
# An optional path to where your profile should be installed to, this is useful if you want to use a common profile name across multiple users, but would have conflicts in your node's profile list.
|
||||
# This will default to `"/nix/var/nix/profiles/$PROFILE_NAME` if `user` is root (see: generic options), and `/nix/var/nix/profiles/per-user/$USER/$PROFILE_NAME` if it is not.
|
||||
profilePath = "/nix/var/nix/profiles/per-user/someuser/someprofile";
|
||||
# This will default to `"/nix/var/nix/profiles/system` if `user` is `root` and profile name is `system`,
|
||||
# `/nix/var/nix/profiles/per-user/root/$PROFILE_NAME` if profile name is different.
|
||||
# For non-root profiles will default to /nix/var/nix/profiles/per-user/$USER/$PROFILE_NAME if `/nix/var/nix/profiles/per-user/$USER` already exists,
|
||||
# and `${XDG_STATE_HOME:-$HOME/.local/state}/nix/profiles/$PROFILE_NAME` otherwise.
|
||||
profilePath = "/home/someuser/.local/state/nix/profiles/someprofile";
|
||||
|
||||
# ...generic options... (see lower section)
|
||||
}
|
||||
|
@ -15,9 +15,10 @@ use tokio::time::timeout;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use notify::{RecommendedWatcher, RecursiveMode, Watcher, recommended_watcher};
|
||||
use notify::{recommended_watcher, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
@ -47,11 +48,24 @@ enum SubCommand {
|
||||
|
||||
/// Activate a profile
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(group(
|
||||
clap::ArgGroup::new("profile")
|
||||
.required(true)
|
||||
.multiple(false)
|
||||
.args(&["profile-path","profile-user"])
|
||||
))]
|
||||
struct ActivateOpts {
|
||||
/// The closure to activate
|
||||
closure: String,
|
||||
/// The profile path to install into
|
||||
profile_path: String,
|
||||
#[clap(long)]
|
||||
profile_path: Option<String>,
|
||||
/// The profile user if explicit profile path is not specified
|
||||
#[clap(long, requires = "profile-name")]
|
||||
profile_user: Option<String>,
|
||||
/// The profile name
|
||||
#[clap(long, requires = "profile-user")]
|
||||
profile_name: Option<String>,
|
||||
|
||||
/// Maximum time to wait for confirmation after activation
|
||||
#[clap(long)]
|
||||
@ -78,7 +92,7 @@ struct ActivateOpts {
|
||||
temp_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Activate a profile
|
||||
/// Wait for profile activation
|
||||
#[derive(Clap, Debug)]
|
||||
struct WaitOpts {
|
||||
/// The closure to wait for
|
||||
@ -89,11 +103,18 @@ struct WaitOpts {
|
||||
temp_path: PathBuf,
|
||||
}
|
||||
|
||||
/// Activate a profile
|
||||
/// Revoke profile activation
|
||||
#[derive(Clap, Debug)]
|
||||
struct RevokeOpts {
|
||||
/// The profile path to revoke
|
||||
profile_path: String,
|
||||
/// The profile path to install into
|
||||
#[clap(long)]
|
||||
profile_path: Option<String>,
|
||||
/// The profile user if explicit profile path is not specified
|
||||
#[clap(long, requires = "profile-name")]
|
||||
profile_user: Option<String>,
|
||||
/// The profile name
|
||||
#[clap(long, requires = "profile-user")]
|
||||
profile_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -315,8 +336,8 @@ pub async fn wait(temp_path: PathBuf, closure: String) -> Result<(), WaitError>
|
||||
// 'lock_path' may not exist yet when some other files are created in 'temp_path'
|
||||
// x is already supposed to be canonical path
|
||||
Ok(lock_path) if x == &lock_path => created.try_send(Ok(())),
|
||||
_ => Ok (())
|
||||
}
|
||||
_ => Ok(()),
|
||||
},
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
@ -459,6 +480,61 @@ async fn revoke(profile_path: String) -> Result<(), DeactivateError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum GetProfilePathError {
|
||||
#[error("Failed to deduce HOME directory for user {0}")]
|
||||
NoUserHome(String),
|
||||
}
|
||||
|
||||
fn get_profile_path(
|
||||
profile_path: Option<String>,
|
||||
profile_user: Option<String>,
|
||||
profile_name: Option<String>,
|
||||
) -> Result<String, GetProfilePathError> {
|
||||
match (profile_path, profile_user, profile_name) {
|
||||
(Some(profile_path), None, None) => Ok(profile_path),
|
||||
(None, Some(profile_user), Some(profile_name)) => {
|
||||
let nix_state_dir = env::var("NIX_STATE_DIR").unwrap_or("/nix/var/nix".to_string());
|
||||
// As per https://nixos.org/manual/nix/stable/command-ref/files/profiles#profiles
|
||||
match &profile_user[..] {
|
||||
"root" => {
|
||||
match &profile_name[..] {
|
||||
// NixOS system profile belongs to the root user, but isn't stored in the 'per-user/root'
|
||||
"system" => Ok(format!("{}/profiles/system", nix_state_dir)),
|
||||
_ => Ok(format!(
|
||||
"{}/profiles/per-user/root/{}",
|
||||
nix_state_dir, profile_name
|
||||
)),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let old_user_profiles_dir =
|
||||
format!("{}/profiles/per-user/{}", nix_state_dir, profile_user);
|
||||
// To stay backward compatible
|
||||
if Path::new(&old_user_profiles_dir).exists() {
|
||||
Ok(format!("{}/{}", old_user_profiles_dir, profile_name))
|
||||
} else {
|
||||
// https://github.com/NixOS/nix/blob/2.17.0/src/libstore/profiles.cc#L308
|
||||
// This is basically the equivalent of calling 'dirs::state_dir()'.
|
||||
// However, this function returns 'None' on macOS, while nix will actually
|
||||
// check env variables, so we imitate nix implementation below instead of
|
||||
// using 'dirs::state_dir()' directly.
|
||||
let state_dir = env::var("XDG_STATE_HOME").or_else(|_| {
|
||||
dirs::home_dir()
|
||||
.map(|h| {
|
||||
format!("{}/.local/state", h.as_path().display().to_string())
|
||||
})
|
||||
.ok_or(GetProfilePathError::NoUserHome(profile_user))
|
||||
})?;
|
||||
Ok(format!("{}/nix/profiles/{}", state_dir, profile_name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("impossible"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Ensure that this process stays alive after the SSH connection dies
|
||||
@ -483,7 +559,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let r = match opts.subcmd {
|
||||
SubCommand::Activate(activate_opts) => activate(
|
||||
activate_opts.profile_path,
|
||||
get_profile_path(
|
||||
activate_opts.profile_path,
|
||||
activate_opts.profile_user,
|
||||
activate_opts.profile_name,
|
||||
)?,
|
||||
activate_opts.closure,
|
||||
activate_opts.auto_rollback,
|
||||
activate_opts.temp_path,
|
||||
@ -499,9 +579,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.await
|
||||
.map_err(|x| Box::new(x) as Box<dyn std::error::Error>),
|
||||
|
||||
SubCommand::Revoke(revoke_opts) => revoke(revoke_opts.profile_path)
|
||||
.await
|
||||
.map_err(|x| Box::new(x) as Box<dyn std::error::Error>),
|
||||
SubCommand::Revoke(revoke_opts) => revoke(get_profile_path(
|
||||
revoke_opts.profile_path,
|
||||
revoke_opts.profile_user,
|
||||
revoke_opts.profile_name,
|
||||
)?)
|
||||
.await
|
||||
.map_err(|x| Box::new(x) as Box<dyn std::error::Error>),
|
||||
};
|
||||
|
||||
match r {
|
||||
|
@ -9,11 +9,11 @@ use std::path::Path;
|
||||
use thiserror::Error;
|
||||
use tokio::process::Command;
|
||||
|
||||
use crate::DeployDataDefsError;
|
||||
use crate::{DeployDataDefsError, ProfileInfo};
|
||||
|
||||
struct ActivateCommandData<'a> {
|
||||
sudo: &'a Option<String>,
|
||||
profile_path: &'a str,
|
||||
profile_info: &'a ProfileInfo,
|
||||
closure: &'a str,
|
||||
auto_rollback: bool,
|
||||
temp_path: &'a Path,
|
||||
@ -37,8 +37,21 @@ fn build_activate_command(data: &ActivateCommandData) -> String {
|
||||
}
|
||||
|
||||
self_activate_command = format!(
|
||||
"{} activate '{}' '{}' --temp-path '{}'",
|
||||
self_activate_command, data.closure, data.profile_path, data.temp_path.display()
|
||||
"{} activate '{}' {} --temp-path '{}'",
|
||||
self_activate_command,
|
||||
data.closure,
|
||||
match data.profile_info {
|
||||
ProfileInfo::ProfilePath { profile_path } =>
|
||||
format!("--profile-path '{}'", profile_path),
|
||||
ProfileInfo::ProfileUserAndName {
|
||||
profile_user,
|
||||
profile_name,
|
||||
} => format!(
|
||||
"--profile-user {} --profile-name {}",
|
||||
profile_user, profile_name
|
||||
),
|
||||
},
|
||||
data.temp_path.display()
|
||||
);
|
||||
|
||||
self_activate_command = format!(
|
||||
@ -72,7 +85,9 @@ fn build_activate_command(data: &ActivateCommandData) -> String {
|
||||
#[test]
|
||||
fn test_activation_command_builder() {
|
||||
let sudo = Some("sudo -u test".to_string());
|
||||
let profile_path = "/blah/profiles/test";
|
||||
let profile_info = &ProfileInfo::ProfilePath {
|
||||
profile_path: "/blah/profiles/test".to_string(),
|
||||
};
|
||||
let closure = "/nix/store/blah/etc";
|
||||
let auto_rollback = true;
|
||||
let dry_activate = false;
|
||||
@ -86,7 +101,7 @@ fn test_activation_command_builder() {
|
||||
assert_eq!(
|
||||
build_activate_command(&ActivateCommandData {
|
||||
sudo: &sudo,
|
||||
profile_path,
|
||||
profile_info,
|
||||
closure,
|
||||
auto_rollback,
|
||||
temp_path,
|
||||
@ -97,7 +112,7 @@ fn test_activation_command_builder() {
|
||||
dry_activate,
|
||||
boot,
|
||||
}),
|
||||
"sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt activate '/nix/store/blah/etc' '/blah/profiles/test' --temp-path '/tmp' --confirm-timeout 30 --magic-rollback --auto-rollback"
|
||||
"sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt activate '/nix/store/blah/etc' --profile-path '/blah/profiles/test' --temp-path '/tmp' --confirm-timeout 30 --magic-rollback --auto-rollback"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
@ -123,7 +138,9 @@ fn build_wait_command(data: &WaitCommandData) -> String {
|
||||
|
||||
self_activate_command = format!(
|
||||
"{} wait '{}' --temp-path '{}'",
|
||||
self_activate_command, data.closure, data.temp_path.display(),
|
||||
self_activate_command,
|
||||
data.closure,
|
||||
data.temp_path.display(),
|
||||
);
|
||||
|
||||
if let Some(sudo_cmd) = &data.sudo {
|
||||
@ -157,7 +174,7 @@ fn test_wait_command_builder() {
|
||||
struct RevokeCommandData<'a> {
|
||||
sudo: &'a Option<String>,
|
||||
closure: &'a str,
|
||||
profile_path: &'a str,
|
||||
profile_info: ProfileInfo,
|
||||
debug_logs: bool,
|
||||
log_dir: Option<&'a str>,
|
||||
}
|
||||
@ -173,7 +190,21 @@ fn build_revoke_command(data: &RevokeCommandData) -> String {
|
||||
self_activate_command = format!("{} --log-dir {}", self_activate_command, log_dir);
|
||||
}
|
||||
|
||||
self_activate_command = format!("{} revoke '{}'", self_activate_command, data.profile_path);
|
||||
self_activate_command = format!(
|
||||
"{} revoke {}",
|
||||
self_activate_command,
|
||||
match &data.profile_info {
|
||||
ProfileInfo::ProfilePath { profile_path } =>
|
||||
format!("--profile-path '{}'", profile_path),
|
||||
ProfileInfo::ProfileUserAndName {
|
||||
profile_user,
|
||||
profile_name,
|
||||
} => format!(
|
||||
"--profile-user {} --profile-name {}",
|
||||
profile_user, profile_name
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
if let Some(sudo_cmd) = &data.sudo {
|
||||
self_activate_command = format!("{} {}", sudo_cmd, self_activate_command);
|
||||
@ -186,7 +217,9 @@ fn build_revoke_command(data: &RevokeCommandData) -> String {
|
||||
fn test_revoke_command_builder() {
|
||||
let sudo = Some("sudo -u test".to_string());
|
||||
let closure = "/nix/store/blah/etc";
|
||||
let profile_path = "/nix/var/nix/per-user/user/profile";
|
||||
let profile_info = ProfileInfo::ProfilePath {
|
||||
profile_path: "/nix/var/nix/per-user/user/profile".to_string(),
|
||||
};
|
||||
let debug_logs = true;
|
||||
let log_dir = Some("/tmp/something.txt");
|
||||
|
||||
@ -194,11 +227,11 @@ fn test_revoke_command_builder() {
|
||||
build_revoke_command(&RevokeCommandData {
|
||||
sudo: &sudo,
|
||||
closure,
|
||||
profile_path,
|
||||
profile_info,
|
||||
debug_logs,
|
||||
log_dir
|
||||
}),
|
||||
"sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt revoke '/nix/var/nix/per-user/user/profile'"
|
||||
"sudo -u test /nix/store/blah/etc/activate-rs --debug-logs --log-dir /tmp/something.txt revoke --profile-path '/nix/var/nix/per-user/user/profile'"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
@ -271,6 +304,8 @@ pub enum DeployProfileError {
|
||||
|
||||
#[error("Error confirming deployment: {0}")]
|
||||
Confirm(#[from] ConfirmProfileError),
|
||||
#[error("Deployment data invalid: {0}")]
|
||||
InvalidDeployDataDefs(#[from] DeployDataDefsError),
|
||||
}
|
||||
|
||||
pub async fn deploy_profile(
|
||||
@ -299,7 +334,7 @@ pub async fn deploy_profile(
|
||||
|
||||
let self_activate_command = build_activate_command(&ActivateCommandData {
|
||||
sudo: &deploy_defs.sudo,
|
||||
profile_path: &deploy_defs.profile_path,
|
||||
profile_info: &deploy_data.get_profile_info()?,
|
||||
closure: &deploy_data.profile.profile_settings.path,
|
||||
auto_rollback,
|
||||
temp_path: temp_path,
|
||||
@ -439,7 +474,7 @@ pub async fn revoke(
|
||||
let self_revoke_command = build_revoke_command(&RevokeCommandData {
|
||||
sudo: &deploy_defs.sudo,
|
||||
closure: &deploy_data.profile.profile_settings.path,
|
||||
profile_path: &deploy_data.get_profile_path()?,
|
||||
profile_info: deploy_data.get_profile_info()?,
|
||||
debug_logs: deploy_data.debug_logs,
|
||||
log_dir: deploy_data.log_dir,
|
||||
});
|
||||
|
38
src/lib.rs
38
src/lib.rs
@ -332,9 +332,17 @@ pub struct DeployData<'a> {
|
||||
pub struct DeployDefs {
|
||||
pub ssh_user: String,
|
||||
pub profile_user: String,
|
||||
pub profile_path: String,
|
||||
pub sudo: Option<String>,
|
||||
}
|
||||
enum ProfileInfo {
|
||||
ProfilePath {
|
||||
profile_path: String,
|
||||
},
|
||||
ProfileUserAndName {
|
||||
profile_user: String,
|
||||
profile_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DeployDataDefsError {
|
||||
@ -351,8 +359,6 @@ impl<'a> DeployData<'a> {
|
||||
|
||||
let profile_user = self.get_profile_user()?;
|
||||
|
||||
let profile_path = self.get_profile_path()?;
|
||||
|
||||
let sudo: Option<String> = match self.merged_settings.user {
|
||||
Some(ref user) if user != &ssh_user => Some(format!("{} {}", self.get_sudo(), user)),
|
||||
_ => None,
|
||||
@ -361,26 +367,10 @@ impl<'a> DeployData<'a> {
|
||||
Ok(DeployDefs {
|
||||
ssh_user,
|
||||
profile_user,
|
||||
profile_path,
|
||||
sudo,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_profile_path(&'a self) -> Result<String, DeployDataDefsError> {
|
||||
let profile_user = self.get_profile_user()?;
|
||||
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(),
|
||||
};
|
||||
Ok(profile_path)
|
||||
}
|
||||
|
||||
fn get_profile_user(&'a self) -> Result<String, DeployDataDefsError> {
|
||||
let profile_user = match self.merged_settings.user {
|
||||
Some(ref x) => x.clone(),
|
||||
@ -403,6 +393,16 @@ impl<'a> DeployData<'a> {
|
||||
None => "sudo -u".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_profile_info(&'a self) -> Result<ProfileInfo, DeployDataDefsError> {
|
||||
match self.profile.profile_settings.profile_path {
|
||||
Some(ref profile_path) => Ok(ProfileInfo::ProfilePath { profile_path: profile_path.to_string() }),
|
||||
None => {
|
||||
let profile_user = self.get_profile_user()?;
|
||||
Ok(ProfileInfo::ProfileUserAndName { profile_user, profile_name: self.profile_name.to_string() })
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_deploy_data<'a, 's>(
|
||||
|
Loading…
Reference in New Issue
Block a user