Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make multi-user installer idempotent #7603

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions scripts/install-multi-user.sh
Original file line number Diff line number Diff line change
Expand Up @@ -441,19 +441,31 @@ $(uninstall_directions)
EOF
fi

# TODO: I think it would be good for this step to accumulate more
# knowledge of older obsolete artifacts, if there are any.
# We could issue a "reminder" here that the user might want
# to clean them up?

problematic_profile_targets=()
for profile_target in "${PROFILE_TARGETS[@]}"; do
# TODO: I think it would be good to accumulate a list of all
# of the copies so that people don't hit this 2 or 3x in
# a row for different files.
if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
# this backup process first released in Nix 2.1
failure <<EOF
# this backup process first released in Nix 2.1
if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ] && ! contains_source_lines "$profile_target"; then
# Identical backup and original happens especially on macOS as it overwrites /etc/zshrc on every update
if cmp -s "$profile_target" "$profile_target$PROFILE_BACKUP_SUFFIX"; then
rm "$profile_target$PROFILE_BACKUP_SUFFIX"
else
problematic_profile_targets+=("$profile_target")
fi
fi
done

if [ "${PROFILE_TARGETS[@]}" ]; then
resolution_explanation=$(cat <<EOF
I back up shell profile/rc scripts before I add Nix to them.
However, at least one of them was already backed up.
Clean them up manually to continue.
EOF
)

for profile_target in "${problematic_profile_targets[@]}"; do
resolution_explanation+=$(cat <<EOF


I need to back up $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX,
but the latter already exists.

Expand All @@ -470,8 +482,11 @@ Here's how to clean up the old backup file:
$profile_target$PROFILE_BACKUP_SUFFIX doesn't mention Nix, run:
mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
EOF
fi
done
)
done

failure "$resolution_explanation"
fi

if is_os_linux && [ ! -e /run/systemd/system ]; then
warning <<EOF
Expand Down Expand Up @@ -816,7 +831,7 @@ install_from_extracted_nix() {
cd "$EXTRACTED_NIX_PATH"

_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
cp -RPp ./store/* "$NIX_ROOT/store/"
cp -RPnp ./store/* "$NIX_ROOT/store/"

_sudo "to make the new store non-writable at $NIX_ROOT/store" \
chmod -R ugo-w "$NIX_ROOT/store/"
Expand Down Expand Up @@ -862,6 +877,11 @@ end
EOF
}

contains_source_lines() {
# This works for both POSIX shells and fish
grep -q "# Nix" "$1" && grep -q "# End Nix" "$1"
}

configure_shell_profile() {
task "Setting up shell profiles: ${PROFILE_TARGETS[*]}"
for profile_target in "${PROFILE_TARGETS[@]}"; do
Expand All @@ -877,7 +897,7 @@ configure_shell_profile() {
fi
fi

if [ -e "$profile_target" ]; then
if [ -e "$profile_target" ] && ! contains_source_lines "$profile_target"; then
shell_source_lines \
| _sudo "extend your $profile_target with nix-daemon settings" \
tee -a "$profile_target"
Expand Down
40 changes: 33 additions & 7 deletions tests/installer/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ let
with nixpkgsFor.${image.system}.native;
runCommand
"installer-test-${imageName}-${testName}"
{ buildInputs = [ qemu_kvm openssh ];
{
buildInputs = [ qemu_kvm openssh ];
image = image.image;
postBoot = image.postBoot or "";
installScript = installScripts.${testName}.script;
Expand Down Expand Up @@ -230,15 +231,40 @@ let
[[ \$(nix-instantiate --eval --expr 'builtins.readFile <myChannel/someFile>') = '"someContent"' ]]
EOF

echo "Running installer again to test for idempotency..."
$ssh "set -eux; $installScript"

echo "Testing Nix installation..."
$ssh <<EOF
set -ex

# FIXME: get rid of this; ideally ssh should just work.
source ~/.bash_profile || true
source ~/.bash_login || true
source ~/.profile || true
source /etc/bashrc || true

nix-env --version
nix --extra-experimental-features nix-command store ping

out=\$(nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > \$out"]; }')
[[ \$(cat \$out) = foobar ]]
EOF

echo "Done!"
touch $out
'';

in

builtins.mapAttrs (imageName: image:
{ ${image.system} = builtins.mapAttrs (testName: test:
makeTest imageName testName
) installScripts;
}
) images
builtins.mapAttrs
(imageName: image:
{
${image.system} = builtins.mapAttrs
(testName: test:
makeTest imageName testName
)
installScripts;
}
)
images