Skip to content

Commit

Permalink
repair: add sequoia subcommand to migrate build users to the new 35…
Browse files Browse the repository at this point in the history
…1+ UID range (#1143)

* repair: use target_lexicon::OperatingSystem over target_os cfg

* repair: make repair actions a collection

* Make some things pub for ease of reuse

* fixup: make write_receipt() take a reference instead of ownership

* fixup: make write_receipt() atomic and member of InstallPlan

* CreateUser: enable skipping the completion check

This is useful for when you don't care if it's been completed or not and
want to rerun the commands. Especially useful on macOS, where `dscl .
-create` is idempotent.

* repair: add `sequoia` subcommand that can migrate build users to the new 351+ UID range

* fixup: should not be able to specify uid base

* fixup: nicer wording for human consumption

* fixup: don't worry about incompatible receipts

* fixup: prompt before some repair commands

* fixup: set user_base outside of branch

* fixup: store a timestamped, pre-repair copy of the receipt

* fixup: note whether or not the receipt will be updated

* fixup: note that uninstallation will work even if the receipt could not be updated
  • Loading branch information
cole-h authored Sep 12, 2024
1 parent fe3e66b commit ded6eb7
Show file tree
Hide file tree
Showing 7 changed files with 611 additions and 82 deletions.
8 changes: 4 additions & 4 deletions src/action/base/add_user_to_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ Create an operating system level user in the given group
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(tag = "action_name", rename = "add_user_to_group")]
pub struct AddUserToGroup {
name: String,
uid: u32,
groupname: String,
gid: u32,
pub(crate) name: String,
pub(crate) uid: u32,
pub(crate) groupname: String,
pub(crate) gid: u32,
}

impl AddUserToGroup {
Expand Down
53 changes: 28 additions & 25 deletions src/action/base/create_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Create an operating system level user in the given group
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(tag = "action_name", rename = "create_user")]
pub struct CreateUser {
name: String,
uid: u32,
groupname: String,
gid: u32,
pub(crate) name: String,
pub(crate) uid: u32,
pub(crate) groupname: String,
pub(crate) gid: u32,
comment: String,
}

Expand All @@ -29,6 +29,7 @@ impl CreateUser {
groupname: String,
gid: u32,
comment: String,
check_completed: bool,
) -> Result<StatefulAction<Self>, ActionError> {
let this = Self {
name: name.clone(),
Expand All @@ -50,29 +51,31 @@ impl CreateUser {
},
}

// Ensure user does not exists
if let Some(user) = User::from_name(name.as_str())
.map_err(|e| ActionErrorKind::GettingUserId(name.clone(), e))
.map_err(Self::error)?
{
if user.uid.as_raw() != uid {
return Err(Self::error(ActionErrorKind::UserUidMismatch(
name.clone(),
user.uid.as_raw(),
uid,
)));
}
if check_completed {
// Ensure user does not exist
if let Some(user) = User::from_name(name.as_str())
.map_err(|e| ActionErrorKind::GettingUserId(name.clone(), e))
.map_err(Self::error)?
{
if user.uid.as_raw() != uid {
return Err(Self::error(ActionErrorKind::UserUidMismatch(
name.clone(),
user.uid.as_raw(),
uid,
)));
}

if user.gid.as_raw() != gid {
return Err(Self::error(ActionErrorKind::UserGidMismatch(
name.clone(),
user.gid.as_raw(),
gid,
)));
}
if user.gid.as_raw() != gid {
return Err(Self::error(ActionErrorKind::UserGidMismatch(
name.clone(),
user.gid.as_raw(),
gid,
)));
}

tracing::debug!("Creating user `{}` already complete", this.name);
return Ok(StatefulAction::completed(this));
tracing::debug!("Creating user `{}` already complete", this.name);
return Ok(StatefulAction::completed(this));
}
}

Ok(StatefulAction::uncompleted(this))
Expand Down
17 changes: 9 additions & 8 deletions src/action/common/create_users_and_groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ use tracing::{span, Span};
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(tag = "action_name", rename = "create_users_and_group")]
pub struct CreateUsersAndGroups {
nix_build_user_count: u32,
nix_build_group_name: String,
nix_build_group_id: u32,
nix_build_user_prefix: String,
nix_build_user_id_base: u32,
create_group: StatefulAction<CreateGroup>,
create_users: Vec<StatefulAction<CreateUser>>,
add_users_to_groups: Vec<StatefulAction<AddUserToGroup>>,
pub(crate) nix_build_group_name: String,
pub(crate) nix_build_group_id: u32,
pub(crate) nix_build_user_count: u32,
pub(crate) nix_build_user_prefix: String,
pub(crate) nix_build_user_id_base: u32,
pub(crate) create_group: StatefulAction<CreateGroup>,
pub(crate) create_users: Vec<StatefulAction<CreateUser>>,
pub(crate) add_users_to_groups: Vec<StatefulAction<AddUserToGroup>>,
}

impl CreateUsersAndGroups {
Expand All @@ -37,6 +37,7 @@ impl CreateUsersAndGroups {
settings.nix_build_group_name.clone(),
settings.nix_build_group_id,
format!("Nix build user {index}"),
true,
)
.await
.map_err(Self::error)?,
Expand Down
2 changes: 1 addition & 1 deletion src/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl ActionDescription {
}

/// A 'tag' name an action has that corresponds to the one we serialize in [`typetag]`
pub struct ActionTag(&'static str);
pub struct ActionTag(pub &'static str);

impl std::fmt::Display for ActionTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down
Loading

0 comments on commit ded6eb7

Please sign in to comment.