ops, cluster: consolidate NixOS provisioning

This moves the diff-and-activate logic from cluster/nix/provision.nix
into ops/{provision,machines}.nix that can be used for both cluster
machines and bgpwtf machines.

The provisioning scripts now live per-NixOS-config, and anything under
ops.machines.$fqdn now has a .passthru.hscloud.provision derivation
which is that script. When ran, it will attempt to deploy onto the
target machine.

There's also a top-level tool at `ops.provision` which builds all
configurations / machines and can be called with the machine name/fqdn
to call the corresponding provisioner script.

clustercfg is changed to use the new provisioning logic.

Change-Id: I258abce9e8e3db42af35af102f32ab7963046353
diff --git a/cluster/clustercfg/clustercfg.py b/cluster/clustercfg/clustercfg.py
index 0adef40..d852d6a 100644
--- a/cluster/clustercfg/clustercfg.py
+++ b/cluster/clustercfg/clustercfg.py
@@ -206,10 +206,12 @@
         ca_admitomatic = ca.CA(ss, certs_root, 'admitomatic', 'admitomatic webhook CA')
         ca_admitomatic.make_cert('admitomatic-webhook', ou='Admitomatic Webhook', hosts=['admitomatic.admitomatic.svc'])
 
-    subprocess.check_call(["nix", "run",
-                           "-f", local_root,
-                           "cluster.nix.provision",
-                           "-c", "provision-{}".format(fqdn.split('.')[0])])
+    toplevel = subprocess.check_output([
+        "nix-build",
+        local_root,
+        "-A", "ops.machines.\"" + fqdn + "\".config.passthru.hscloud.provision",
+    ]).decode().strip()
+    subprocess.check_call([toplevel])
 
 
 def usage():
diff --git a/cluster/nix/provision.nix b/cluster/nix/provision.nix
deleted file mode 100644
index 7ab7e71..0000000
--- a/cluster/nix/provision.nix
+++ /dev/null
@@ -1,49 +0,0 @@
-{ hscloud, pkgs, ... }:
-
-with builtins;
-
-let 
-  machines = (import ./defs-machines.nix);
-  configurations = builtins.listToAttrs (map (machine: {
-    name = machine.fqdn;
-    value = pkgs.nixos ({ config, pkgs, ... }: {
-      networking.hostName = machine.name;
-      imports = [
-        ./modules/base.nix
-        ./modules/kubernetes.nix
-      ];
-    });
-  }) machines);
-
-  scriptForMachine = machine: let
-    configuration = configurations."${machine.fqdn}";
-  in ''
-   set -e
-   remote=root@${machine.fqdn}
-   echo "Configuration for ${machine.fqdn} is ${configuration.toplevel}"
-   nix copy --no-check-sigs -s --to ssh://$remote ${configuration.toplevel}
-   echo "/etc/systemd/system diff:"
-   ssh $remote diff -ur /var/run/current-system/etc/systemd/system ${configuration.toplevel}/etc/systemd/system || true
-   echo ""
-   echo ""
-   ssh $remote ${configuration.toplevel}/bin/switch-to-configuration dry-activate
-   read -p "Do you want to switch to this configuration? " -n 1 -r
-   echo
-   if [[ $REPLY =~ ^[Yy]$ ]]; then
-       ssh $remote ${configuration.toplevel}/bin/switch-to-configuration switch
-   fi
-  '';
-
-  provisioners = (map (machine:
-    pkgs.writeScriptBin "provision-${machine.name}" (scriptForMachine machine)
-  ) machines);
-
-  provision = pkgs.writeScriptBin "provision" (
-    ''
-      echo "Available provisioniers:"
-    '' + (concatStringsSep "\n" (map (machine: "echo '  provision-${machine.name}'") machines)));
-in
-pkgs.symlinkJoin {
-  name = "provision";
-  paths = [ provision ] ++ provisioners;
-}