From 89e012eb49f3891ebe51ed48822fc88de2487662 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Thu, 24 Jun 2021 14:08:51 -0400
Subject: [PATCH] Some initial pieces for coercing nodes into updating
 themselves

---
 .gitlab-ci.yml                  |  3 +--
 ci-tools/deploy-to-staging      | 27 +++++++++++++++++++++++++++
 nixos/modules/deployment.nix    | 18 ++++++++++++++++++
 nixos/modules/update-deployment | 19 +++++++++++++++++++
 4 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100644 ci-tools/deploy-to-staging
 create mode 100644 nixos/modules/deployment.nix
 create mode 100644 nixos/modules/update-deployment

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b91f7d5f..4e68fd45 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -46,8 +46,7 @@ deploy-to-staging:
     name: "staging"
     url: "https://privatestorage-staging.com/"
   script:
-    - echo "Hello $GITLAB_USER_LOGIN from $CI_JOB_NAME. I was triggered by $CI_PIPELINE_SOURCE "
-    - echo "and would like to deploy the $CI_COMMIT_BRANCH branch to the $CI_ENVIRONMENT_NAME environment."
+    - "./ci-tools/deploy-to-staging"
 
 deploy-to-production:
   stage: "deploy"
diff --git a/ci-tools/deploy-to-staging b/ci-tools/deploy-to-staging
new file mode 100644
index 00000000..47cdafa4
--- /dev/null
+++ b/ci-tools/deploy-to-staging
@@ -0,0 +1,27 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p jp
+
+set -euxo pipefail
+
+GRIDNAME="staging"
+
+# Tell one node to update itself.
+update_yourself() {
+    node=$1
+    shift
+
+    ssh -i deploy_key "${node}"
+}
+
+# Find the names of all hosts that belong to this grid.  This list includes
+# one extra string, "network", which is morph configuration stuff and we need
+# to filter out later.
+NODES=$(nix eval --json '(builtins.attrNames (import ./morph/${GRIDNAME}/grid.nix))')
+
+# Tell every system in the network to update itself.
+for node in ${NODES}; do
+    if [ "${node}" = "network" ]; then
+	continue
+    fi
+    update_yourself "${node}"
+fi
diff --git a/nixos/modules/deployment.nix b/nixos/modules/deployment.nix
new file mode 100644
index 00000000..a12ff054
--- /dev/null
+++ b/nixos/modules/deployment.nix
@@ -0,0 +1,18 @@
+# A NixOS module which enables remotely-triggered deployment updates.
+{ config, ... }:
+let
+  # Compute an authorized_keys line that allows the holder of a certain key to
+  # execute a certain command *only*.
+  restrictedKey = pubKey: command: "restrict,command=\"${command}\" ${pubKey}";
+in {
+  options = {
+  };
+
+  config = {
+    users.users.deployment = {
+      openssh.authorizedKeys.keys = [
+        restrictedKey cfg.deployKey ./update-deployment
+      ];
+    };
+  };
+}
diff --git a/nixos/modules/update-deployment b/nixos/modules/update-deployment
new file mode 100644
index 00000000..7685423e
--- /dev/null
+++ b/nixos/modules/update-deployment
@@ -0,0 +1,19 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -i bash -p morph
+
+set -euxo pipefail
+
+CHECKOUT="/run/user/$(id --user)/PrivateStorageio"
+GRIDNAME="staging"
+REPO="https://whetstone.privatestorage.io/privatestorage/PrivateStorageio.git"
+
+if [ -e "${CHECKOUT}" ]; then
+    git -C "${CHECKOUT}" pull
+else
+    git clone "${REPO}" "${CHECKOUT}"
+    # Check out the right branch ... which also happens to be named after this
+    # grid (or maybe this grid is named after the branch).
+    git -C "${CHECKOUT}" checkout "${GRIDNAME}"
+fi
+
+morph deploy "${CHECKOUT}"/morph/grid/"${GRIDNAME}"/grid.nix switch --on "$(hostname)"
-- 
GitLab