diff options
Diffstat (limited to 'krebs')
-rw-r--r-- | krebs/3modules/backup.nix | 23 | ||||
-rw-r--r-- | krebs/3modules/build.nix | 126 | ||||
-rw-r--r-- | krebs/3modules/tv/default.nix | 2 | ||||
-rw-r--r-- | krebs/3modules/urlwatch.nix | 69 |
4 files changed, 116 insertions, 104 deletions
diff --git a/krebs/3modules/backup.nix b/krebs/3modules/backup.nix index 0aa86dec9..97082f56a 100644 --- a/krebs/3modules/backup.nix +++ b/krebs/3modules/backup.nix @@ -117,6 +117,14 @@ let "$dst_user@$dst_host" \ -T "$with_dst_path_lock_script" } + rsh="ssh -F /dev/null -i $identity ''${dst_port:+-p $dst_port}" + local_rsync() { + rsync "$@" + } + remote_rsync=${shell.escape (concatStringsSep " && " [ + "mkdir -m 0700 -p ${shell.escape plan.dst.path}/current" + "exec flock -n ${shell.escape plan.dst.path} rsync" + ])} ''; pull = '' identity=${shell.escape plan.dst.host.ssh.privkey.path} @@ -131,6 +139,12 @@ let dst_shell() { eval "$with_dst_path_lock_script" } + rsh="ssh -F /dev/null -i $identity ''${src_port:+-p $src_port}" + local_rsync() { + mkdir -m 0700 -p ${shell.escape plan.dst.path}/current + flock -n ${shell.escape plan.dst.path} rsync "$@" + } + remote_rsync=rsync ''; }} # Note that this only works because we trust date +%s to produce output @@ -140,13 +154,10 @@ let with_dst_path_lock_script="exec env start_date=$(date +%s) "${shell.escape "flock -n ${shell.escape plan.dst.path} /bin/sh" } - rsync >&2 \ + local_rsync >&2 \ -aAXF --delete \ - -e "ssh -F /dev/null -i $identity ''${dst_port:+-p $dst_port}" \ - --rsync-path ${shell.escape (concatStringsSep " && " [ - "mkdir -m 0700 -p ${shell.escape plan.dst.path}/current" - "exec flock -n ${shell.escape plan.dst.path} rsync" - ])} \ + --rsh="$rsh" \ + --rsync-path="$remote_rsync" \ --link-dest="$dst_path/current" \ "$src/" \ "$dst/.partial" diff --git a/krebs/3modules/build.nix b/krebs/3modules/build.nix index a1f446188..b8ea34ae2 100644 --- a/krebs/3modules/build.nix +++ b/krebs/3modules/build.nix @@ -20,35 +20,19 @@ let type = types.user; }; - options.krebs.build.source = let - raw = types.either types.str types.path; - url = types.submodule { + options.krebs.build.source = mkOption { + type = with types; attrsOf (either str (submodule { options = { - url = mkOption { - type = types.str; - }; - rev = mkOption { - type = types.str; - }; - dev = mkOption { - type = types.str; - }; + url = str; + rev = str; }; - }; - in mkOption { - type = types.attrsOf (types.either types.str url); - apply = let f = mapAttrs (_: value: { - string = value; - path = toString value; - set = f value; - }.${typeOf value}); in f; + })); default = {}; }; options.krebs.build.populate = mkOption { type = types.str; default = let - source = config.krebs.build.source; target-user = maybeEnv "target_user" "root"; target-host = maybeEnv "target_host" config.krebs.build.host.name; target-port = maybeEnv "target_port" "22"; @@ -58,12 +42,13 @@ let set -eu verbose() { - printf '+%s\n' "$(printf ' %q' "$@")" >&2 + printf '%s%s\n' "$PS5$(printf ' %q' "$@")" >&2 "$@" } - echo ${shell.escape git-script} \ - | ssh -p ${shell.escape target-port} \ + { printf 'PS5=%q%q\n' @ "$PS5" + echo ${shell.escape git-script} + } | verbose ssh -p ${shell.escape target-port} \ ${shell.escape "${target-user}@${target-host}"} -T unset tmpdir @@ -75,24 +60,21 @@ let tmpdir=$(mktemp -dt stockholm.XXXXXXXX) chmod 0755 "$tmpdir" - ${concatStringsSep "\n" - (mapAttrsToList - (name: spec: let dst = removePrefix "symlink:" (get-url spec); in - "verbose ln -s ${shell.escape dst} $tmpdir/${shell.escape name}") - symlink-specs)} + ${concatStringsSep "\n" (mapAttrsToList (name: symlink: '' + verbose ln -s ${shell.escape symlink.target} \ + "$tmpdir"/${shell.escape name} + '') source-by-method.symlink)} verbose proot \ - -b $tmpdir:${shell.escape target-path} \ - ${concatStringsSep " \\\n " - (mapAttrsToList - (name: spec: - "-b ${shell.escape "${get-url spec}:${target-path}/${name}"}") - file-specs)} \ + -b "$tmpdir":${shell.escape target-path} \ + ${concatStringsSep " \\\n " (mapAttrsToList (name: file: + "-b ${shell.escape "${file.path}:${target-path}/${name}"}" + ) source-by-method.file)} \ rsync \ -f ${shell.escape "P /*"} \ - ${concatMapStringsSep " \\\n " - (name: "-f ${shell.escape "R /${name}"}") - (attrNames file-specs)} \ + ${concatMapStringsSep " \\\n " (name: + "-f ${shell.escape "R /${name}"}" + ) (attrNames source-by-method.file)} \ --delete \ -vFrlptD \ -e ${shell.escape "ssh -p ${target-port}"} \ @@ -100,36 +82,12 @@ let ${shell.escape "${target-user}@${target-host}:${target-path}"} ''; - get-schema = uri: - if substring 0 1 uri == "/" - then "file" - else head (splitString ":" uri); - - has-schema = schema: uri: get-schema uri == schema; - - get-url = spec: { - string = spec; - path = toString spec; - set = get-url spec.url; - }.${typeOf spec}; - - git-specs = - filterAttrs (_: spec: has-schema "https" (get-url spec)) source // - filterAttrs (_: spec: has-schema "http" (get-url spec)) source // - filterAttrs (_: spec: has-schema "git" (get-url spec)) source; - - file-specs = - filterAttrs (_: spec: has-schema "file" (get-url spec)) source; - - symlink-specs = - filterAttrs (_: spec: has-schema "symlink" (get-url spec)) source; - git-script = '' #! /bin/sh set -efu verbose() { - printf '+%s\n' "$(printf ' %q' "$@")" >&2 + printf '%s%s\n' "$PS5$(printf ' %q' "$@")" >&2 "$@" } @@ -162,20 +120,42 @@ let git clean -dxf )} - ${concatStringsSep "\n" - (mapAttrsToList - (name: spec: toString (map shell.escape [ - "verbose" - "fetch_git" - "${target-path}/${name}" - spec.url - spec.rev - ])) - git-specs)} + ${concatStringsSep "\n" (mapAttrsToList (name: git: '' + verbose fetch_git ${concatMapStringsSep " " shell.escape [ + "${target-path}/${name}" + git.url + git.rev + ]} + '') source-by-method.git)} ''; in out; }; }; + source-by-method = let + known-methods = ["git" "file" "symlink"]; + in genAttrs known-methods (const {}) // recursiveUpdate source-by-scheme { + git = source-by-scheme.http or {} // + source-by-scheme.https or {}; + }; + + source-by-scheme = foldl' (out: { k, v }: recursiveUpdate out { + ${v.scheme}.${k} = v; + }) {} (mapAttrsToList (k: v: { inherit k v; }) normalized-source); + + normalized-source = mapAttrs (name: let f = x: getAttr (typeOf x) { + path = f (toString x); + string = f { + url = if substring 0 1 x == "/" then "file://${x}" else x; + }; + set = let scheme = head (splitString ":" x.url); in recursiveUpdate x { + inherit scheme; + } // { + symlink.target = removePrefix "symlink:" x.url; + file.path = # TODO file://host/... + assert hasPrefix "file:///" x.url; + removePrefix "file://" x.url; + }.${scheme} or {}; + }; in f) config.krebs.build.source; in out diff --git a/krebs/3modules/tv/default.nix b/krebs/3modules/tv/default.nix index f8d3d8671..300fce017 100644 --- a/krebs/3modules/tv/default.nix +++ b/krebs/3modules/tv/default.nix @@ -352,7 +352,7 @@ with config.krebs.lib; pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGer9e2+Lew7vnisgBbsFNECEIkpNJgEaqQqgb9inWkQ mv@vod"; }; tv = { - mail = "tv@wu.retiolum"; + mail = "tv@nomic.retiolum"; pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAQDFR//RnCvEZAt0F6ExDsatKZ/DDdifanuSL360mqOhaFieKI34RoOwfQT9T+Ga52Vh5V2La6esvlph686EdgzeKLvDoxEwFM9ZYFBcMrNzu4bMTlgE7YUYw5JiORyXNfznBGnme6qpuvx9ibYhUyiZo99kM8ys5YrUHrP2JXQJMezDFZHxT4GFMOuSdh/1daGoKKD6hYL/jEHX8CI4E3BSmKK6ygYr1fVX0K0Tv77lIi5mLXucjR7CytWYWYnhM6DC3Hxpv2zRkPgf3k0x/Y1hrw3V/r0Me5h90pd2C8pFaWA2ZoUT/fmyVqvx1tZPYToU/O2dMItY0zgx2kR0yD+6g7Aahz3R+KlXkV8k5c8bbTbfGnZWDR1ZlbLRM9Yt5vosfwapUD90MmVkpmR3wUkO2sUKi80QfC7b4KvSDXQ+MImbGxMaU5Bnsq1PqLN95q+uat3nlAVBAELkcx51FlE9CaIS65y4J7FEDg8BE5JeuCNshh62VSYRXVSFt8bk3f/TFGgzC8OIo14BhVmiRQQ503Z1sROyf5xLX2a/EJavMm1i2Bs2TH6ROKY9z5Pz8hT5US0r381V8oG7TZyLF9HTtoy3wCYsgWA5EmLanjAsVU2YEeAA0rxzdtYP8Y2okFiJ6u+M4HQZ3Wg3peSodyp3vxdYce2vk4EKeqEFuuS82850DYb7Et7fmp+wQQUT8Q/bMO0DreWjHoMM5lE4LJ4ME6AxksmMiFtfo/4Fe2q9D+LAqZ+ANOcv9M+8Rn6ngiYmuRNd0l/a02q1PEvO6vTfXgcl4f7Z1IULHPEaDNZHCJS1K5RXYFqYQ6OHsTmOm7hnwaRAS97+VFMo1i5uvTx9nYaAcY7yzq3Ckfb67dMBKApGOpJpkvPgfrP7bgBO5rOZXM1opXqVPb09nljAhhAhyCTh1e/8+mJrBo0cLQ/LupQzVxGDgm3awSMPxsZAN45PSWz76zzxdDa1MMo51do+VJHfs7Wl0NcXAQrniOBYL9Wqt0qNkn1gY5smkkISGeQ/vxNap4MmzeZE7b5fpOy+2fpcRVQLpc4nooQzJvSVTFz+25lgZ6iHf45K87gQFMIAri1Pf/EDDpL87az+bRWvWi+BA2kMe1kf+Ay1LyMz8r+g51H0ma0bNFh6+fbWMfUiD9JCepIObclnUJ4NlWfcgHxTf17d/4tl6z4DTcLpCCk8Da77JouSHgvtcRbRlFV1OfhWZLXUsrlfpaQTiItv6TGIr3k7+7b66o3Qw/GQVs5GmYifaIZIz8n8my4XjkaMBd0SZfBzzvFjHMq6YUP9+SbjvReqofuoO+5tW1wTYZXitFFBfwuHlXm6w77K5QDBW6olT7pat41/F5eGxLcz tv@wu"; }; tv-nomic = { diff --git a/krebs/3modules/urlwatch.nix b/krebs/3modules/urlwatch.nix index cd4976a21..ed1a21260 100644 --- a/krebs/3modules/urlwatch.nix +++ b/krebs/3modules/urlwatch.nix @@ -3,7 +3,6 @@ # TODO multiple users # TODO inform about unused caches # cache = url: "${cfg.dataDir}/.urlwatch/cache/${hashString "sha1" url}" -# TODO hooks.py with config.krebs.lib; let @@ -32,6 +31,14 @@ let Content of the From: header of the generated mails. ''; }; + # TODO hooks :: attrsOf hook + hooksFile = mkOption { + type = with types; nullOr path; + default = null; + description = '' + File to use as hooks.py module. + ''; + }; mailto = mkOption { type = types.str; default = config.krebs.build.user.mail; @@ -48,7 +55,7 @@ let ''; }; urls = mkOption { - type = with types; listOf str; + type = with types; listOf (either str subtypes.job); default = []; description = "URL to watch."; example = [ @@ -56,7 +63,10 @@ let ]; apply = map (x: getAttr (typeOf x) { set = x; - string.url = x; + string = { + url = x; + filter = null; + }; }); }; verbose = mkOption { @@ -68,9 +78,12 @@ let }; }; - urlsFile = toFile "urls" (concatMapStringsSep "\n---\n" toJSON cfg.urls); + urlsFile = pkgs.writeText "urls" + (concatMapStringsSep "\n---\n" toJSON cfg.urls); + + hooksFile = cfg.hooksFile; - configFile = toFile "urlwatch.yaml" (toJSON { + configFile = pkgs.writeText "urlwatch.yaml" (toJSON { display = { error = true; new = true; @@ -127,10 +140,10 @@ let User = user.name; PermissionsStartOnly = "true"; PrivateTmp = "true"; + SyslogIdentifier = "urlwatch"; Type = "oneshot"; ExecStartPre = - pkgs.writeScript "urlwatch-prestart" '' - #! /bin/sh + pkgs.writeDash "urlwatch-prestart" '' set -euf dataDir=$HOME @@ -140,31 +153,29 @@ let chown ${user.name}: "$dataDir" fi ''; - ExecStart = pkgs.writeScript "urlwatch" '' - #! /bin/sh + ExecStart = pkgs.writeDash "urlwatch" '' set -euf - from=${escapeShellArg cfg.from} - mailto=${escapeShellArg cfg.mailto} - urlsFile=${escapeShellArg urlsFile} - configFile=${escapeShellArg configFile} cd /tmp urlwatch \ ${optionalString cfg.verbose "-v"} \ - --urls="$urlsFile" \ - --config="$configFile" \ + --config=${shell.escape configFile} \ + ${optionalString (hooksFile != null) + "--hooks=${shell.escape hooksFile}" + } \ + --urls=${shell.escape urlsFile} \ > changes || : if test -s changes; then - date=$(date -R) - subject=$(sed -n 's/^\(CHANGED\|ERROR\|NEW\): //p' changes \ - | tr \\n \ ) { - echo "Date: $date" - echo "From: $from" - echo "Subject: $subject" - echo "To: $mailto" + echo Date: $(date -R) + echo From: ${shell.escape cfg.from} + echo Subject: $( + sed -n 's/^\(CHANGED\|ERROR\|NEW\): //p' changes \ + | tr '\n' ' ' + ) + echo To: ${shell.escape cfg.mailto} echo cat changes } | /var/setuid-wrappers/sendmail -t @@ -181,5 +192,15 @@ let name = "urlwatch"; uid = genid name; }; -in -out + + subtypes.job = types.submodule { + options = { + url = mkOption { + type = types.str; + }; + filter = mkOption { + type = with types; nullOr str; # TODO nullOr subtypes.filter + }; + }; + }; +in out |