sh: functions -> bin/

This commit is contained in:
tv 2015-05-21 01:56:08 +02:00
parent b95a514bcc
commit 36670f3e1c
48 changed files with 639 additions and 620 deletions

10
bin/_cac_curl_api_v1 Executable file
View File

@ -0,0 +1,10 @@
#! /bin/sh
set -euf
exec _cac_exec curl -fsS "$1" "https://panel.cloudatcost.com/api/v1/$2.php" $(
shift 2
set -- "$@" login="$cac_login" key="$cac_key"
for arg; do
echo -d $(printf '%s' "$arg" | urlencode)
done
)

8
bin/_cac_exec Executable file
View File

@ -0,0 +1,8 @@
#! /bin/sh
set -euf
if test -z "${cac_via-}"; then
exec "$@"
else
exec ssh -q "$cac_via" -t "$@"
fi

3
bin/_cac_get_api_v1 Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_curl_api_v1 -G "$@"

3
bin/_cac_post_api_v1 Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_curl_api_v1 -XPOST "$@"

5
bin/bre-escape Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh
# bre-escape : lines string |> lines bre-escaped-string
set -euf
sed 's:[\.\[\\\*\^\$]:\\&:g'

15
bin/bre-invert-word Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
# bre-invert-word : string -> BRE
set -euf
# TODO escape chars in the resulting BRE.
awk -v input="$1" '
BEGIN {
split(input,s,"")
for (i in s) {
c=s[i]
printf "\\|%s[^%s]", y, c
y = y c
}
}
'

5
bin/cac-cloudpro-build Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh
set -euf
# default os=26 is CentOS-7-64bit
exec _cac_post_api_v1 cloudpro/build cpu="$1" ram="$2" storage="$3" os="${4-26}"

3
bin/cac-cloudpro-delete Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 cloudpro/delete sid="$1"

3
bin/cac-cloudpro-resources Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_get_api_v1 cloudpro/resources

3
bin/cac-console Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 console sid="$1"

15
bin/cac-get-server-by Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
set -euf
cac-listservers \
| jq \
--arg k "$1" \
--arg v "$2" \
'
map(select(.[$k]==$v)) |
if (. | length) == 1 then
.[0]
else
.
end
'

12
bin/cac-listservers Executable file
View File

@ -0,0 +1,12 @@
#! /bin/sh
set -euf
listservers=$(_cac_get_api_v1 listservers)
status=$(echo "$listservers" | jq -r .status)
if [ "$status" = ok ]; then
echo "$listservers" | jq -r .data
else
echo "$0: bad listservers status: $status" >&2
exit 1
fi

3
bin/cac-listtasks Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_get_api_v1 listtasks

4
bin/cac-listtemplates Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
set -euf
exec _cac_get_api_v1 listtemplates

3
bin/cac-powerop Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 powerop sid="$1" action="$2"

3
bin/cac-rdns Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 rdns sid="$1" hostname="$2"

3
bin/cac-renameserver Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 renameserver sid="$1" name="$2"

3
bin/cac-runmode Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
set -euf
exec _cac_post_api_v1 rdns sid="$1" mode="$2"

17
bin/cac-ssh Executable file
View File

@ -0,0 +1,17 @@
#! /bin/sh
set -euf
server=$1
shift
address=$(echo $server | jq -r .ip)
target=root@$address
SSHPASS=$(echo $server | jq -r .rootpass)
export SSHPASS
exec sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"$target" \
"$@"

28
bin/cacnixos-networking Executable file
View File

@ -0,0 +1,28 @@
#! /bin/sh
# cacnixos-networking : cac-server x hostname -> nixos-module
# TODO use label for hostname
set -euf
server=$1
hostname=$2
address=$(echo $server | jq -r .ip)
gateway=$(echo $server | jq -r .gateway)
nameserver=8.8.8.8
netmask=$(echo $server | jq -r .netmask)
prefix=$(netmask-to-prefix $netmask)
printf '{...}:\n'
printf '{\n'
printf ' networking.hostName = "%s";\n' $hostname
printf ' networking.interfaces.enp2s1.ip4 = [\n'
printf ' {\n'
printf ' address = "%s";\n' $address
printf ' prefixLength = %d;\n' $prefix
printf ' }\n'
printf ' ];\n'
printf ' networking.defaultGateway = "%s";\n' $gateway
printf ' networking.nameservers = [\n'
printf ' "%s"\n' $nameserver
printf ' ];\n'
printf '}\n'

6
bin/filter-secrets Executable file
View File

@ -0,0 +1,6 @@
#! /bin/sh
# filter_secrets : lines string |> lines secrets-file-candidate
set -euf
# Notice how false positives are possible.
sed -n 's:^\(.*/\)\?\(secrets/.*\):'"${PWD//:/\\:}"'/\2:p'

10
bin/import-statements Executable file
View File

@ -0,0 +1,10 @@
#! /bin/sh
# import-statements : lines (path ":" string) |> lines (path ":" relpath)
set -euf
sed -n '
s@^\([^:]\+:\)\('"$(bre-invert-word import)"'\)*\<import\s\+@\1@
t1;d
:1; s@^\([^:]\+:\)\(\.*/\S*\)@\1\2\n@
t2;d
:2; P;D
'

150
bin/infest-CentOS-7-64bit Executable file
View File

@ -0,0 +1,150 @@
#! /bin/sh
set -euf
server=$1
hostname=$2
address=$(echo $server | jq -r .ip)
RSYNC_RSH='sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
SSHPASS=$(echo $server | jq -r .rootpass)
export SSHPASS
export RSYNC_RSH
main="modules/$hostname/default.nix"
target="root@$address"
cacnixos-networking "$server" $hostname \
> modules/$hostname/networking.nix
echo '(
set -xeuf
type bzip2 || yum install -y bzip2
type rsync || yum install -y rsync
)' \
| sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"root@$address" \
/bin/sh
make-rsync-filter "$main" \
| rsync -f '. -' -zvrlptD --delete-excluded ./ "$target":/etc/nixos/
#
#
#
echo '(
set -xeuf
groupadd -g 30000 nixbld || :
for i in `seq 1 10`; do
useradd -c "foolsgarden Nix build user $i" \
-d /var/empty \
-s /sbin/nologin \
-g 30000 \
-G 30000 \
-l -u $(expr 30000 + $i) \
nixbld$i || :
rm -f /var/spool/mail/nixbld$i
done
#curl https://nixos.org/nix/install | sh
nix_tar=$nix_basename.tar.bz2
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
curl -O -C - $nix_url || :
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
curl -O $nix_url || :
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
echo $0: cannot download $nix_url >&2
exit 5
fi
fi
fi
if ! test -d $nix_basename; then
tar jxf $nix_basename.tar.bz2
fi
nix_find=$nix_basename.find.txt
if ! echo $nix_find_sha1sum $nix_find | sha1sum -c; then
find $nix_basename | sort > $nix_find
if ! echo $nix_find_sha1sum $nix_find | sha1sum -c; then
echo $0: cannot unpack $nix_basename.tar.bz2 >&2
# TODO we could retry
exit 6
fi
fi
mkdir -p bin
PATH=$HOME/bin:$PATH
export PATH
# generate fake sudo because
# sudo: sorry, you must have a tty to run sudo
{
echo "#! /bin/sh"
echo "exec env \"\$@\""
} > bin/sudo
chmod +x bin/sudo
./$nix_basename/install
. /root/.nix-profile/etc/profile.d/nix.sh
nixpkgs_expr="import <nixpkgs> { system = builtins.currentSystem; }"
nixpkgs_path=$(
find /nix/store -mindepth 1 -maxdepth 1 -name *-nixpkgs-* -type d
)
for i in nixos-generate-config nixos-install; do
nix-env \
--arg config "{ nix.package = ($nixpkgs_expr).nix; }" \
--arg pkgs "$nixpkgs_expr" \
--arg modulesPath "throw \"no modulesPath\"" \
-f $nixpkgs_path/nixpkgs/nixos/modules/installer/tools/tools.nix \
-iA config.system.build.$i
done
# TODO following fail when aborted in-between
if ! test -d /int; then
mkdir -p /int
mount --bind /int /mnt
fi
if ! test -d /mnt/boot; then
mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot
fi
mkdir -p /mnt/etc/nixos
rsync -zvrlptD --delete-excluded /etc/nixos/ /mnt/etc/nixos/
mkdir -m 0444 -p /mnt/var/empty
ln -s $main /mnt/etc/nixos/configuration.nix
nixos-install \
-I secrets=/etc/nixos/secrets
find / \
1> /root/pre-rsync-find.out \
2> /root/pre-rsync-find.err
rsync -va --force /int/ /
# find / -type f -mtime +1 -exec rm -v {} \; 2>&1 > rm.log
# ^ too aggressive, kills journal which is bad
# shutdown -r now
# nix-channel --add https://nixos.org/channels/nixos-unstable nixos
# nix-channel --remove nixpkgs
# nix-channel --update
)' \
| sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"root@$address" \
-T /usr/bin/env \
nix_url="$nix_url" \
nix_basename="$(basename $nix_url .tar.bz2)" \
nix_sha256="$nix_sha256" \
nix_find_sha1sum="$nix_find_sha1sum" \
main="$main" \
/bin/sh

21
bin/infest-cac Executable file
View File

@ -0,0 +1,21 @@
#! /bin/sh
set -euf
server=$(cac-get-server-by servername "$1")
hostname=$2
serverstatus=$(echo $server | jq -r .status)
case $serverstatus in
'Powered On') : ;;
*)
echo $0: bad server status: $serverstatus >&2
exit 2
esac
template=$(echo $server | jq -r .template)
case $template in
'CentOS-7-64bit') infest-"$template" "$server" "$hostname";;
*)
echo $0: bad template: $template >&2
exit 3
esac

18
bin/json-assert-type Executable file
View File

@ -0,0 +1,18 @@
#! /bin/sh
set -euf
formal_type=$1
actual_value=$2
actual_type=$(echo $actual_value | jq -r type)
if [ "$actual_type" != "$formal_type" ]; then
backtrace
printf 'error: expected %s, got %s\n' \
"$formal_type" \
"$actual_type" \
>&2
exit 1
fi
echo "$actual_value"

7
bin/list-hosts Executable file
View File

@ -0,0 +1,7 @@
#! /bin/sh
# list-hosts : lines tinc-host-file
set -euf
# Precondition: $PWD/hosts is the correct repository :)
git -C hosts ls-tree --name-only HEAD \
| awk '{print ENVIRON["PWD"]"/hosts/"$$0}'

20
bin/list-module-imports Executable file
View File

@ -0,0 +1,20 @@
#! /bin/sh
# list-module-imports : nix-file -> lines nix-file
set -euf
if echo "$1" | grep -q ^/; then
:
else
set -- "./$1"
fi
imports=$(nix-instantiate \
-I secrets=secrets \
--strict \
--json \
--eval \
-E \
"with builtins; with import ./lib/modules.nix; map toString (list-imports $1)")
echo "$imports" \
| jq -r .[]

12
bin/ls-bre Executable file
View File

@ -0,0 +1,12 @@
#! /bin/sh
# ls-bre : directory -> BRE
# Create a BRE from the files in a directory.
set -euf
ls "$1" \
| tr \\n / \
| sed '
s:[\.\[\\\*\^\$]:\\&:g
s:/$::
s:/:\\|:g
'

10
bin/make-parent-dirs Executable file
View File

@ -0,0 +1,10 @@
#! /bin/sh
# make-parent-dirs : lines path |> lines directory
# List all parent directories of a path.
set -euf
set -- "$(sed -n 's|/[^/]*$||p' | grep . | sort | uniq)"
if echo "$1" | grep -q .; then
echo "$1"
echo "$1" | make-parent-dirs
fi

6
bin/make-relative-to Executable file
View File

@ -0,0 +1,6 @@
#! /bin/sh
# make-relative-to : lines path |> directory -> lines path
# Non-matching paths won't get altered.
set -euf
sed "s:^$(echo "$1/" | bre-escape | sed 's/:/\\:/g')::"

33
bin/make-rsync-filter Executable file
View File

@ -0,0 +1,33 @@
#! /bin/sh
# make-rsync-filter : nixos-config -> rsync-filter
set -euf
main=$1
hosts=$(list-hosts)
module_imports=$(list-module-imports "$main")
other_imports=$(
echo "$module_imports" \
| xargs grep -H . \
| import-statements \
| slash-path-relpath \
| undot-paths \
| sort \
| uniq \
| sed '/\.nix$/!s:$:/default.nix:' \
)
secrets=$(echo "$module_imports" | xargs cat | quoted-strings | filter-secrets)
# TODO collect all other paths from *_imports
abs_deps=$(
echo "$hosts"
echo "$module_imports"
echo "$other_imports"
echo "$secrets"
)
rel_deps=$(echo "$abs_deps" | make-relative-to "$PWD")
filter=$(echo "$rel_deps" | make-rsync-whitelist)
echo "$filter"

15
bin/make-rsync-whitelist Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
# make-rsync-whitelist : lines relpath |> liens rsync-filter
set -euf
set -- "$(cat)"
# include all files in stdin and their directories
{
echo "$1"
echo "$1" | make-parent-dirs | sort | uniq
} \
| sed 's|^|+ /|'
# exclude everything else
echo '- *'

12
bin/netmask-to-prefix Executable file
View File

@ -0,0 +1,12 @@
#! /bin/sh
set -euf
netmask=$1
binaryNetmask=$(echo $1 | sed 's/^/obase=2;/;s/\./;/g' | bc | tr -d \\n)
binaryPrefix=$(echo $binaryNetmask | sed -n 's/^\(1*\)0*$/\1/p')
if ! echo $binaryPrefix | grep -q .; then
echo $0: bad netmask: $netmask >&2
exit 4
fi
printf %s $binaryPrefix | tr -d 0 | wc -c

13
bin/nixpkgs-rev Executable file
View File

@ -0,0 +1,13 @@
#! /bin/sh
# nixpkgs-rev : nixos-config -> git_rev
set -euf
nix-instantiate \
-I nixos-config="$1" \
--eval \
--json \
-E \
'
(import <nixos-config> {config={}; pkgs={};}).nixpkgs.rev
' \
2> /dev/null \
| jq -r . 2> /dev/null

13
bin/nixpkgs-url Executable file
View File

@ -0,0 +1,13 @@
#! /bin/sh
# nixpkgs-url : nixos-config -> git_url
set -euf
nix-instantiate \
-I nixos-config="$1" \
--eval \
--json \
-E \
'
(import <nixos-config> {config={}; pkgs={};}).nixpkgs.url
' \
2> /dev/null \
| jq -r . 2> /dev/null

15
bin/quoted-strings Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
# quoted_strings : lines string |> lines string
# Extract all (double-) quoted strings from stdin.
#
# 0. find begin of string or skip line
# 1. find end of string or skip line
# 2. print string and continue after string
set -euf
sed '
s:[^"]*":: ;t1;d
:1; s:\(\([^"]\|\\"\)*\)":\1\n: ;t2;d
:2; P;D
' \
| sed 's:\\":":g'

8
bin/slash-path-relpath Executable file
View File

@ -0,0 +1,8 @@
#! /bin/sh
# slash_path_relpath : lines (path ":" relpath) |> lines path
#
# Example: "/foo/bar: baz" => "/foo/baz"
#
set -euf
sed -n 's@/[^/]\+:@/@p'

26
bin/ssh-deploy Executable file
View File

@ -0,0 +1,26 @@
#! /bin/sh
# ssh-deploy : nixos-config x [user@]hostname -> ()
set -xeuf
main=$1
target=$2
nixpkgs_dir=/var/nixpkgs # TODO make configurable
git_url=$(nixpkgs-url $main)
git_rev=$(nixpkgs-rev $main)
if [ "$git_url" = '' ] || [ "$git_rev" = '' ]; then
echo "specify nixpkgs.url and nixpkgs.rev in $main !"
exit 23
fi
filter=$(make-rsync-filter "$main")
echo "$filter" \
| rsync -f '. -' -zvrlptD --delete-excluded ./ "$target":/etc/nixos/
ssh-fetch-git "$target" "$nixpkgs_dir" "$git_url" "$git_rev"
ssh "$target" nixos-rebuild switch \
-I nixos-config=/etc/nixos/"$main" \
-I nixpkgs="$nixpkgs_dir" \
-I secrets=/etc/nixos/secrets \

35
bin/ssh-fetch-git Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
# ssh-fetch-git : [user@]hostname x remote_dir x git_url x git_rev -> ()
set -euf
target=$1
remote_dir=$2
git_url=$3
git_rev=$4
echo '
set -euf
if [ ! -d "$remote_dir" ]; then
mkdir -p "$remote_dir"
fi
cd "$remote_dir"
git init -q
if ! current_url=$(git config remote.src.url); then
git remote add src "$git_url"
elif [ $current_url != $git_url ]; then
git remote set-url src "$git_url"
fi
git fetch src
git checkout "$git_rev"
' \
| ssh "$target" env \
remote_dir="$remote_dir" \
git_rev="$git_rev" \
git_url="$git_url" \
/bin/sh

14
bin/undot-paths Executable file
View File

@ -0,0 +1,14 @@
#! /bin/sh
# undot_paths : lines path |> lines path
# Remove all dots (. and ..) from input paths.
set -euf
sed '
:0
s://\+:/:g
s:/\.\(/\|$\):\1:g
s:/[^/]\+/\.\.\(/\|$\):\1:g
s:^/\(\.\./\)\+:/:
t0
s:^$:/:
'

35
bin/urlencode Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
set -euf
exec sed '
s/%/%25/g
s/ /%20/g
s/!/%21/g
s/"/%22/g
s/#/%23/g
s/\$/%24/g
s/\&/%26/g
s/'\''/%27/g
s/(/%28/g
s/)/%29/g
s/\*/%2a/g
s/+/%2b/g
s/,/%2c/g
s/-/%2d/g
s/\./%2e/g
s/\//%2f/g
s/:/%3a/g
s/;/%3b/g
s//%3e/g
s/?/%3f/g
s/@/%40/g
s/\[/%5b/g
s/\\/%5c/g
s/\]/%5d/g
s/\^/%5e/g
s/_/%5f/g
s/`/%60/g
s/{/%7b/g
s/|/%7c/g
s/}/%7d/g
s/~/%7e/g
'

5
deploy
View File

@ -4,7 +4,8 @@
# #
set -euf set -euf
. ./lib/prelude.sh PATH="$PWD/bin${PATH+:$PATH}"
export PATH
user=root user=root
host=$1 host=$1
@ -12,4 +13,4 @@ host=$1
config=./modules/$host/default.nix config=./modules/$host/default.nix
target=${2-$user@$host} target=${2-$user@$host}
verbose deploy "$config" "$target" exec ssh-deploy "$config" "$target"

188
infest
View File

@ -1,187 +1,15 @@
#! /bin/sh #! /bin/sh
set -xeuf #
# usage: ./infest cac-servername hostname
#
set -euf
. ./lib/prelude.sh PATH="$PWD/bin${PATH+:$PATH}"
. ./lib/cac.sh export PATH
. ./lib/cacnixos.sh
nix_url=https://nixos.org/releases/nix/nix-1.8/nix-1.8-x86_64-linux.tar.bz2 nix_url=https://nixos.org/releases/nix/nix-1.8/nix-1.8-x86_64-linux.tar.bz2
nix_sha256=52fab207b4ce4d098a12d85357d0353e972c492bab0aa9e08e1600363e76fefb nix_sha256=52fab207b4ce4d098a12d85357d0353e972c492bab0aa9e08e1600363e76fefb
nix_find_sha1sum=86f8775bd4f0841edd4c816df861cebf509d58c3 nix_find_sha1sum=86f8775bd4f0841edd4c816df861cebf509d58c3
export nix_url nix_sha256 nix_find_sha1sum
# This is somewhat required because cloudatcost requires whitelisting exec infest-cac "$@"
# of hosts. If you whitelist your localhost, then leave this empty.
# cac_via=
#
# cac_key=
# cac_login=
# cac_servername=
# hostname=
main() {
server=$(cac_getserver_by_servername "$cac_servername")
serverstatus=$(echo $server | jq -r .status)
case $serverstatus in
'Powered On') : ;;
*)
echo $0: bad server status: $serverstatus >&2
exit 2
esac
template=$(echo $server | jq -r .template)
case $template in
'CentOS-7-64bit') infest_centos7_64bit "$server";;
*)
echo $0: bad template: $template >&2
exit 3
esac
}
infest_centos7_64bit() {
server=$1
address=$(echo $server | jq -r .ip)
RSYNC_RSH='sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
SSHPASS=$(echo $server | jq -r .rootpass)
export SSHPASS
export RSYNC_RSH
main="modules/$hostname/default.nix"
target="root@$address"
cacnixos_networking "$server" $hostname \
> modules/$hostname/networking.nix
echo '(
set -xeuf
type bzip2 || yum install -y bzip2
type rsync || yum install -y rsync
)' \
| sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"root@$address" \
/bin/sh
rsync_filter "$main" \
| rsync -f '. -' -zvrlptD --delete-excluded ./ "$target":/etc/nixos/
#
#
#
echo '(
set -xeuf
groupadd -g 30000 nixbld || :
for i in `seq 1 10`; do
useradd -c "foolsgarden Nix build user $i" \
-d /var/empty \
-s /sbin/nologin \
-g 30000 \
-G 30000 \
-l -u $(expr 30000 + $i) \
nixbld$i || :
rm -f /var/spool/mail/nixbld$i
done
#curl https://nixos.org/nix/install | sh
nix_tar=$nix_basename.tar.bz2
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
curl -O -C - $nix_url || :
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
curl -O $nix_url || :
if ! echo $nix_sha256 $nix_tar | sha256sum -c; then
echo $0: cannot download $nix_url >&2
exit 5
fi
fi
fi
if ! test -d $nix_basename; then
tar jxf $nix_basename.tar.bz2
fi
nix_find=$nix_basename.find.txt
if ! echo $nix_find_sha1sum $nix_find | sha1sum -c; then
find $nix_basename | sort > $nix_find
if ! echo $nix_find_sha1sum $nix_find | sha1sum -c; then
echo $0: cannot unpack $nix_basename.tar.bz2 >&2
# TODO we could retry
exit 6
fi
fi
mkdir -p bin
PATH=$HOME/bin:$PATH
export PATH
# generate fake sudo because
# sudo: sorry, you must have a tty to run sudo
{
echo "#! /bin/sh"
echo "exec env \"\$@\""
} > bin/sudo
chmod +x bin/sudo
./$nix_basename/install
. /root/.nix-profile/etc/profile.d/nix.sh
nixpkgs_expr="import <nixpkgs> { system = builtins.currentSystem; }"
nixpkgs_path=$(
find /nix/store -mindepth 1 -maxdepth 1 -name *-nixpkgs-* -type d
)
for i in nixos-generate-config nixos-install; do
nix-env \
--arg config "{ nix.package = ($nixpkgs_expr).nix; }" \
--arg pkgs "$nixpkgs_expr" \
--arg modulesPath "throw \"no modulesPath\"" \
-f $nixpkgs_path/nixpkgs/nixos/modules/installer/tools/tools.nix \
-iA config.system.build.$i
done
# TODO following fail when aborted in-between
if ! test -d /int; then
mkdir -p /int
mount --bind /int /mnt
fi
if ! test -d /mnt/boot; then
mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot
fi
mkdir -p /mnt/etc/nixos
rsync -zvrlptD --delete-excluded /etc/nixos/ /mnt/etc/nixos/
mkdir -m 0444 -p /mnt/var/empty
ln -s $main /mnt/etc/nixos/configuration.nix
nixos-install \
-I secrets=/etc/nixos/secrets
rsync -va --force /int/ /
# find / -type f -mtime +1 -exec rm -v {} \; 2>&1 > rm.log
# ^ too aggressive, kills journal which is bad
# shutdown -r now
# nix-channel --add https://nixos.org/channels/nixos-unstable nixos
# nix-channel --remove nixpkgs
# nix-channel --update
)' \
| sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"root@$address" \
-T /usr/bin/env \
nix_url="$nix_url" \
nix_basename="$(basename $nix_url .tar.bz2)" \
nix_sha256="$nix_sha256" \
nix_find_sha1sum="$nix_find_sha1sum" \
main="$main" \
/bin/sh
}
main "$@"

View File

@ -1,105 +0,0 @@
. ./lib/url.sh
cac_ssh() {(
server=$1
shift
address=$(echo $server | jq -r .ip)
target=root@$address
SSHPASS=$(echo $server | jq -r .rootpass)
export SSHPASS
exec sshpass -e ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
"$target" \
"$@"
)}
cac_getserver_by_servername() {(
serverlist=$(cac_listservers)
echo $serverlist \
| jq \
--arg name "$1" \
'.[]|select(.servername==$name)'
)}
cac_listservers() {(
listservers=$(_cac_get_api_v1 listservers)
status=$(echo "$listservers" | jq -r .status)
if [ "$status" = ok ]; then
echo "$listservers" | jq -r .data
else
echo "$0: bad listservers status: $status" >&2
exit 1
fi
)}
cac_listtasks() {
_cac_get_api_v1 listtasks
}
cac_listtemplates() {
_cac_get_api_v1 listtemplates
}
cac_console() {
_cac_post_api_v1 console sid="$1"
}
cac_powerop() {
_cac_post_api_v1 powerop sid="$1" action="$2"
}
cac_renameserver() {
_cac_post_api_v1 renameserver sid="$1" name="$2"
}
cac_rnds() {
_cac_post_api_v1 rdns sid="$1" hostname="$2"
}
cac_runmode() {
_cac_post_api_v1 rdns sid="$1" mode="$2"
}
# default os=26 is CentOS-7-64bit
cac_cloudpro_build() {
_cac_post_api_v1 cloudpro/build cpu="$1" ram="$2" storage="$3" os="${4-26}"
}
cac_cloudpro_delete() {
_cac_post_api_v1 cloudpro/delete sid="$1"
}
cac_cloudpro_resources() {
_cac_get_api_v1 cloudpro/resources
}
_cac_get_api_v1() {
_cac_curl_api_v1 -G "$@"
}
_cac_post_api_v1() {
_cac_curl_api_v1 -XPOST "$@"
}
_cac_curl_api_v1() {
_cac_exec curl -fsS "$1" "https://panel.cloudatcost.com/api/v1/$2.php" $(
shift 2
set -- "$@" login="$cac_login" key="$cac_key"
for arg; do
echo -d $(printf '%s' "$arg" | url_encode)
done
)
}
_cac_exec() {
if test -z "${cac_via-}"; then
(exec "$@")
else
ssh -q "$cac_via" -t "$@"
fi
}

View File

@ -1,28 +0,0 @@
. ./lib/net.sh
# cacnixos_networking : cac-server x hostname -> nixos-module
cacnixos_networking() {(
server=$1
hostname=$2
address=$(echo $server | jq -r .ip)
gateway=$(echo $server | jq -r .gateway)
nameserver=8.8.8.8
netmask=$(echo $server | jq -r .netmask)
prefix=$(net_netmask_to_prefix $netmask)
printf '{...}:\n'
printf '{\n'
printf ' networking.hostName = "%s";\n' $hostname
printf ' networking.interfaces.enp2s1.ip4 = [\n'
printf ' {\n'
printf ' address = "%s";\n' $address
printf ' prefixLength = %d;\n' $prefix
printf ' }\n'
printf ' ];\n'
printf ' networking.defaultGateway = "%s";\n' $gateway
printf ' networking.nameservers = [\n'
printf ' "%s"\n' $nameserver
printf ' ];\n'
printf '}\n'
)}

View File

@ -1,9 +0,0 @@
net_netmask_to_prefix() {(
binaryNetmask=$(echo $1 | sed 's/^/obase=2;/;s/\./;/g' | bc | tr -d \\n)
binaryPrefix=$(echo $binaryNetmask | sed -n 's/^\(1*\)0*$/\1/p')
if ! echo $binaryPrefix | grep -q .; then
echo $0: bad netmask: $netmask >&2
exit 4
fi
printf %s $binaryPrefix | tr -d 0 | wc -c
)}

View File

@ -1,261 +0,0 @@
# clone_or_update : [user@]hostname x local_dir x git_url x git_rev -> ()
clone_or_update() {(
target=$1
nixpkgs_dir=$2
git_url=$3
git_rev=$4
echo '
set -euf
if [ ! -d "$nixpkgs_dir" ]; then
mkdir -p "$nixpkgs_dir"
fi
cd "$nixpkgs_dir"
git init -q
if ! current_url=$(git config remote.src.url); then
git remote add src "$git_url"
elif [ $current_url != $git_url ]; then
git remote set-url src "$git_url"
fi
git fetch src
git checkout "$git_rev"
' \
| ssh "$target" env \
nixpkgs_dir="$nixpkgs_dir" \
git_rev="$git_rev" \
git_url="$git_url" \
/bin/sh
)}
# deploy : nixos-config x [user@]hostname -> ()
deploy() {(
main=$1
target=$2
nixpkgs_dir=/var/nixpkgs # TODO make configurable
git_url=$(nixpkgs_url $main)
git_rev=$(nixpkgs_rev $main)
if [ "$git_url" = '' ] || [ "$git_rev" = '' ]; then
echo "specify nixpkgs.url and nixpkgs.rev in $main !"
exit 23
fi
filter=$(rsync_filter "$main")
echo "$filter" \
| rsync -f '. -' -zvrlptD --delete-excluded ./ "$target":/etc/nixos/
clone_or_update "$target" "$nixpkgs_dir" "$git_url" "$git_rev"
ssh "$target" nixos-rebuild switch \
-I nixos-config=/etc/nixos/"$main" \
-I nixpkgs="$nixpkgs_dir" \
-I secrets=/etc/nixos/secrets \
)}
# rsync_filter : nixos-config -> rsync-filter
rsync_filter() {(
main=$1
hosts=$(list_hosts)
module_imports=$(set -euf; list_module_imports "$main")
other_imports=$(
echo "$module_imports" \
| xargs grep -H . \
| import_statements \
| slash_path_relpath \
| undot_paths \
| sort \
| uniq \
| sed '/\.nix$/!s:$:/default.nix:' \
)
secrets=$(echo "$module_imports" | xargs cat | quoted_strings | filter_secrets)
# TODO collect all other paths from *_imports
abs_deps=$(
echo "$hosts"
echo "$module_imports"
echo "$other_imports"
echo "$secrets"
)
rel_deps=$(echo "$abs_deps" | make_relative_to "$PWD")
filter=$(echo "$rel_deps" | make_rsync_whitelist)
echo "$filter"
)}
# list_module_imports : nix-file -> lines nix-file
list_module_imports() {
if echo "$1" | grep -q ^/; then
:
else
set -- "./$1"
fi
imports=$(nix-instantiate \
-I secrets=secrets \
--strict \
--json \
--eval \
-E \
"with builtins; with import ./lib/modules.nix; map toString (list-imports $1)")
echo "$imports" \
| jq -r .[]
}
# list_hosts : lines tinc-host-file
# Precondition: $PWD/hosts is the correct repository :)
list_hosts() {
git -C hosts ls-tree --name-only HEAD \
| awk '{print ENVIRON["PWD"]"/hosts/"$$0}'
}
# filter_secrets : lines string |> lines secrets-file-candidate
# Notice how false positives are possible.
filter_secrets() {
sed -n 's:^\(.*/\)\?\(secrets/.*\):'"${PWD//:/\\:}"'/\2:p'
}
# import_statements : lines (path ":" string) |> lines (path ":" relpath)
import_statements() {
sed -n '
s@^\([^:]\+:\)\('"$(bre_invert_word import)"'\)*\<import\s\+@\1@
t1;d
:1; s@^\([^:]\+:\)\(\.*/\S*\)@\1\2\n@
t2;d
:2; P;D
'
}
# slash_path_relpath : lines (path ":" relpath) |> lines path
#
# Example: "/foo/bar: baz" => "/foo/baz"
#
slash_path_relpath() {
sed -n 's@/[^/]\+:@/@p'
}
# undot_paths : lines path |> lines path
# Remove all dots (. and ..) from input paths.
undot_paths() {
sed '
:0
s://\+:/:g
s:/\.\(/\|$\):\1:g
s:/[^/]\+/\.\.\(/\|$\):\1:g
s:^/\(\.\./\)\+:/:
t0
s:^$:/:
'
}
# quoted_strings : lines string |> lines string
# Extract all (double-) quoted strings from stdin.
#
# 0. find begin of string or skip line
# 1. find end of string or skip line
# 2. print string and continue after string
quoted_strings() {
sed '
s:[^"]*":: ;t1;d
:1; s:\(\([^"]\|\\"\)*\)":\1\n: ;t2;d
:2; P;D
' \
| sed 's:\\":":g'
}
# bre_escape : lines string |> lines bre-escaped-string
bre_escape() {
sed 's:[\.\[\\\*\^\$]:\\&:g'
}
# bre_invert_word : string -> BRE
# TODO escape chars in the resulting BRE.
bre_invert_word() {
awk -v input="$1" '
BEGIN {
split(input,s,"")
for (i in s) {
c=s[i]
printf "\\|%s[^%s]", y, c
y = y c
}
}
'
}
# ls_bre : directory -> BRE
# Create a BRE from the files in a directory.
ls_bre() {
ls "$1" \
| tr \\n / \
| sed '
s:[\.\[\\\*\^\$]:\\&:g
s:/$::
s:/:\\|:g
'
}
# make_relative_to : lines path |> directory -> lines path
# Non-matching paths won't get altered.
make_relative_to() {
sed "s:^$(echo "$1/" | bre_escape | sed 's/:/\\:/g')::"
}
# make_rsync_whitelist : lines relpath |> liens rsync-filter
make_rsync_whitelist() {
set -- "$(cat)"
# include all files in stdin and their directories
{
echo "$1"
echo "$1" | make_parent_dirs | sort | uniq
} \
| sed 's|^|+ /|'
# exclude everything else
echo '- *'
}
# make_parent_dirs : lines path |> lines directory
# List all parent directories of a path.
make_parent_dirs() {
set -- "$(sed -n 's|/[^/]*$||p' | grep . | sort | uniq)"
if echo "$1" | grep -q .; then
echo "$1"
echo "$1" | make_parent_dirs
fi
}
# nixpkgs_url : nixos-config -> git_url
nixpkgs_url() {
nix-instantiate \
-I nixos-config="$1" \
--eval \
--json \
-E '(import <nixos-config> {config={}; pkgs={};}).nixpkgs.url' 2> /dev/null \
| jq -r .
}
# nixpkgs_rev : nixos-config -> git_rev
nixpkgs_rev() {
nix-instantiate \
-I nixos-config="$1" \
--eval \
--json \
-E '(import <nixos-config> {config={}; pkgs={};}).nixpkgs.rev' 2> /dev/null \
| jq -r . 2> /dev/null
}
# verbose COMMAND [ARGS...]
verbose() {
echo "$@" >&2
"$@"
}

View File

@ -1,35 +0,0 @@
url_encode() {
sed '
s/%/%25/g
s/ /%20/g
s/!/%21/g
s/"/%22/g
s/#/%23/g
s/\$/%24/g
s/\&/%26/g
s/'\''/%27/g
s/(/%28/g
s/)/%29/g
s/\*/%2a/g
s/+/%2b/g
s/,/%2c/g
s/-/%2d/g
s/\./%2e/g
s/\//%2f/g
s/:/%3a/g
s/;/%3b/g
s//%3e/g
s/?/%3f/g
s/@/%40/g
s/\[/%5b/g
s/\\/%5c/g
s/\]/%5d/g
s/\^/%5e/g
s/_/%5f/g
s/`/%60/g
s/{/%7b/g
s/|/%7c/g
s/}/%7d/g
s/~/%7e/g
'
}