stockholm/shell.nix

320 lines
9.4 KiB
Nix
Raw Normal View History

2017-06-30 09:04:58 +00:00
let
lib = import ./lib;
pkgs = import <nixpkgs> { overlays = [(import ./krebs/5pkgs)]; };
2017-06-29 20:06:13 +00:00
2017-07-22 21:44:23 +00:00
#
# high level commands
#
2017-09-14 22:33:34 +00:00
cmds.deploy = pkgs.withGetopt {
2017-12-05 21:12:57 +00:00
diff = { default = /* sh */ "false"; switch = true; };
2017-09-14 22:33:34 +00:00
force-populate = { default = /* sh */ "false"; switch = true; };
quiet = { default = /* sh */ "false"; switch = true; };
source_file = {
default = /* sh */ "$user/1systems/$system/source.nix";
long = "source";
};
system = {};
target.default = /* sh */ "$system";
user.default = /* sh */ "$LOGNAME";
} (opts: pkgs.writeDash "cmds.deploy" ''
2017-06-29 20:06:13 +00:00
set -efu
. ${init.env}
. ${init.proxy "deploy" opts}
2017-06-29 20:06:13 +00:00
2017-12-05 21:12:57 +00:00
if \test ${opts.diff.ref} = true; then
system_profile=/nix/var/nix/profiles/system
system_drv_cur=/etc/system.drv
system_drv_new=$(
${pkgs.nix}/bin/nix-instantiate \
-Q \
-I "$target_path" \
-E '
(import <nixpkgs/nixos/lib/eval-config.nix> {
modules = [ <nixos-config> ];
}).config.system.build.toplevel
'
)
if \test -e "$system_drv_cur"; then
system_drv_cur_c=$(${pkgs.coreutils}/bin/readlink -f "$system_drv_cur")
system_drv_new_c=$(${pkgs.coreutils}/bin/readlink -f "$system_drv_new")
if \test "$system_drv_cur_c" = "$system_drv_new_c"; then
echo "$0: system up to date" >&2
exit 0
fi
system_drv_cur=$system_drv_cur_c \
system_drv_new=$system_drv_new_c \
${pkgs.utillinux}/bin/script \
--command '
${pkgs.haskellPackages.nix-diff}/bin/nix-diff \
"$system_drv_cur" "$system_drv_new"
' \
--quiet \
--return \
/dev/null
printf 'deploy? [N/y] ' >&2
read -r REPLY
if \test "$REPLY" != y; then
echo "$0: abort!" >&2
exit 1
fi
else
echo "$0: --${opts.diff.long} has no effect because "$system_drv_cur" doesn't exist" >&2
fi
new_system=$(${pkgs.nix}/bin/nix-store --realize "$system_drv_new")
${pkgs.nix}/bin/nix-env -p "$system_profile" --set "$new_system"
PATH=${lib.makeBinPath [
pkgs.systemd
]} \
"$system_profile"/bin/switch-to-configuration switch
${pkgs.coreutils}/bin/ln -fns "$system_drv_new" "$system_drv_cur"
exit
fi
2017-09-21 19:08:34 +00:00
# Use system's nixos-rebuild, which is not self-contained
export PATH=/run/current-system/sw/bin
exec ${utils.with-whatsupnix} \
nixos-rebuild switch \
--show-trace \
-I "$target_path"
2017-09-14 22:33:34 +00:00
'');
cmds.install = pkgs.withGetopt {
force-populate = { default = /* sh */ "false"; switch = true; };
quiet = { default = /* sh */ "false"; switch = true; };
source_file = {
default = /* sh */ "$user/1systems/$system/source.nix";
long = "source";
};
system = {};
target = {};
user.default = /* sh */ "$LOGNAME";
} (opts: pkgs.writeBash "cmds.install" ''
2017-07-23 20:46:30 +00:00
set -efu
. ${init.env}
if \test "''${using_proxy-}" != true; then
${pkgs.openssh}/bin/ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"$target_user@$target_host" -p "$target_port" \
env target_path=$(quote "$target_path") \
sh -s prepare < ${./krebs/4lib/infest/prepare.sh}
# TODO inline prepare.sh?
fi
. ${init.proxy "install" opts}
2017-07-23 20:46:30 +00:00
# Reset PATH because we need access to nixos-install.
# TODO provide nixos-install instead of relying on prepare.sh
export PATH="$OLD_PATH"
# these variables get defined by nix-shell (i.e. nix-build) from
# XDG_RUNTIME_DIR and reference the wrong directory (/run/user/0),
# which only exists on / and not at /mnt.
export NIX_BUILD_TOP=/tmp
export TEMPDIR=/tmp
export TEMP=/tmp
export TMPDIR=/tmp
export TMP=/tmp
export XDG_RUNTIME_DIR=/tmp
export NIXOS_CONFIG="$target_path/nixos-config"
cd
exec nixos-install
2017-09-14 22:33:34 +00:00
'');
cmds.test = pkgs.withGetopt {
force-populate = { default = /* sh */ "false"; switch = true; };
quiet = { default = /* sh */ "false"; switch = true; };
source_file = {
default = /* sh */ "$user/1systems/$system/source.nix";
long = "source";
};
system = {};
target = {};
user.default = /* sh */ "$LOGNAME";
} (opts: pkgs.writeDash "cmds.test" /* sh */ ''
2017-06-29 20:06:13 +00:00
set -efu
export dummy_secrets=true
2017-06-29 20:06:13 +00:00
. ${init.env}
. ${init.proxy "test" opts}
2017-06-29 20:06:13 +00:00
exec ${utils.build} config.system.build.toplevel
2017-09-14 22:33:34 +00:00
'');
2017-06-29 20:06:13 +00:00
2017-07-22 21:44:23 +00:00
#
# low level commands
#
# usage: get-source SOURCE_FILE
cmds.get-source = pkgs.writeDash "cmds.get-source" ''
set -efu
exec ${pkgs.nix}/bin/nix-instantiate \
--eval \
--json \
--readonly-mode \
--show-trace \
--strict \
"$1"
'';
# usage: parse-target [--default=TARGET] TARGET
# TARGET = [USER@]HOST[:PORT][/PATH]
cmds.parse-target = pkgs.withGetopt {
default_target = {
long = "default";
short = "d";
};
} (opts: pkgs.writeDash "cmds.parse-target" ''
2017-07-22 22:04:54 +00:00
set -efu
target=$1; shift
for arg; do echo "$0: bad argument: $arg" >&2; done
if \test $# != 0; then exit 2; fi
exec ${pkgs.jq}/bin/jq \
-enr \
--arg default_target "$default_target" \
--arg target "$target" \
-f ${pkgs.writeText "cmds.parse-target.jq" ''
def parse: match("^(?:([^@]+)@)?([^:/]+)?(?::([0-9]+))?(/.*)?$") | {
user: .captures[0].string,
host: .captures[1].string,
port: .captures[2].string,
path: .captures[3].string,
};
def sanitize: with_entries(select(.value != null));
($default_target | parse) + ($target | parse | sanitize) |
. + { local: (.user == env.LOGNAME and .host == env.HOSTNAME) }
''}
'');
2017-07-22 22:04:54 +00:00
2017-06-29 20:06:13 +00:00
init.env = pkgs.writeText "init.env" /* sh */ ''
2017-08-10 08:58:06 +00:00
export quiet
2017-06-29 20:06:13 +00:00
export system
export target
2017-07-13 21:39:48 +00:00
export user
2017-06-29 20:06:13 +00:00
default_target=root@$system:22/var/src
export target_object="$(parse-target "$target" -d "$default_target")"
2017-06-29 20:06:13 +00:00
export target_user="$(echo $target_object | ${pkgs.jq}/bin/jq -r .user)"
export target_host="$(echo $target_object | ${pkgs.jq}/bin/jq -r .host)"
export target_port="$(echo $target_object | ${pkgs.jq}/bin/jq -r .port)"
export target_path="$(echo $target_object | ${pkgs.jq}/bin/jq -r .path)"
export target_local="$(echo $target_object | ${pkgs.jq}/bin/jq -r .local)"
'';
2017-06-29 20:06:13 +00:00
init.proxy = command: opts: pkgs.writeText "init.proxy" /* sh */ ''
if \test "''${using_proxy-}" != true; then
source=$(get-source "$source_file")
qualified_target=$target_user@$target_host:$target_port$target_path
2017-08-10 08:47:08 +00:00
if \test "$force_populate" = true; then
2017-07-27 18:43:17 +00:00
echo "$source" | populate --force "$qualified_target"
else
echo "$source" | populate "$qualified_target"
fi
if \test "$target_local" != true; then
exec ${pkgs.openssh}/bin/ssh \
"$target_user@$target_host" -p "$target_port" \
cd "$target_path/stockholm" \; \
NIX_PATH=$(quote "$target_path") \
STOCKHOLM_VERSION=$(quote "$STOCKHOLM_VERSION") \
nix-shell --run "$(quote "
2017-09-14 22:33:34 +00:00
${lib.concatStringsSep " " (lib.mapAttrsToList
(name: opt: /* sh */ "${opt.varname}=\$(quote ${opt.ref})")
opts
)} \
using_proxy=true \
${lib.shell.escape command} \
$WITHGETOPT_ORIG_ARGS \
")"
fi
2017-06-29 20:06:13 +00:00
fi
'';
2017-06-29 20:06:13 +00:00
2017-06-30 02:56:21 +00:00
utils.build = pkgs.writeDash "utils.build" ''
2017-06-29 20:06:13 +00:00
set -efu
2017-08-10 08:58:06 +00:00
${utils.with-whatsupnix} \
2017-06-29 20:06:13 +00:00
${pkgs.nix}/bin/nix-build \
--no-out-link \
--show-trace \
2017-06-30 07:43:33 +00:00
-E "with import <stockholm>; $1" \
2017-06-29 20:06:13 +00:00
-I "$target_path" \
'';
2017-08-10 08:58:06 +00:00
utils.with-whatsupnix = pkgs.writeDash "utils.with-whatsupnix" ''
set -efu
if \test "$quiet" = true; then
"$@" -Q 2>&1 | ${pkgs.whatsupnix}/bin/whatsupnix
else
exec "$@"
fi
2017-06-29 20:06:13 +00:00
'';
2017-06-30 07:43:33 +00:00
shell.get-version = pkgs.writeDash "shell.get-version" ''
2017-06-29 20:06:13 +00:00
set -efu
version=git.$(${pkgs.git}/bin/git describe --always --dirty)
case $version in (*-dirty)
version=$version@$HOSTNAME
esac
date=$(${pkgs.coreutils}/bin/date +%y.%m)
echo "$date.$version"
'';
2017-06-30 07:44:28 +00:00
shell.cmdspkg = pkgs.writeOut "shell.cmdspkg" (lib.mapAttrs' (name: link:
lib.nameValuePair "/bin/${name}" { inherit link; }
) cmds);
2017-06-29 20:06:13 +00:00
in pkgs.stdenv.mkDerivation {
name = "stockholm";
2017-06-30 01:16:24 +00:00
shellHook = /* sh */ ''
2017-07-23 20:46:30 +00:00
export OLD_PATH="$PATH"
2017-08-15 21:15:39 +00:00
export NIX_PATH=stockholm=${toString ./.}:nixpkgs=${toString <nixpkgs>}
if test -e /nix/var/nix/daemon-socket/socket; then
export NIX_REMOTE=daemon
fi
2017-06-29 20:06:13 +00:00
export PATH=${lib.makeBinPath [
pkgs.populate
2017-10-17 18:01:53 +00:00
pkgs.quote
2017-06-30 07:43:33 +00:00
shell.cmdspkg
2017-06-29 20:06:13 +00:00
]}
eval "$(declare -F | ${pkgs.gnused}/bin/sed s/declare/unset/)"
shopt -u no_empty_cmd_completion
unalias -a
enable -n \
. [ alias bg bind break builtin caller cd command compgen complete \
compopt continue dirs disown eval exec false fc fg getopts hash \
help history jobs kill let local logout mapfile popd printf pushd \
pwd read readarray readonly shift source suspend test times trap \
true typeset ulimit umask unalias wait
exitHandler() {
:
}
export HOSTNAME="$(${pkgs.nettools}/bin/hostname)"
2017-06-30 07:43:33 +00:00
export STOCKHOLM_VERSION="''${STOCKHOLM_VERSION-$(${shell.get-version})}"
2017-06-29 20:06:13 +00:00
PS1='\[\e[38;5;162m\]\w\[\e[0m\] '
'';
}