From 7f6c58f210bb4b2e2bfcfc27a78bcb2268f2b423 Mon Sep 17 00:00:00 2001
From: Robert Hensing <robert@roberthensing.nl>
Date: Mon, 24 Jun 2024 09:26:53 +0200
Subject: [PATCH 1/2] nixos-module: Test check that termination signal is sent

---
 tests/flake-module.nix                        |  8 ++--
 .../arion-compose.nix                         | 26 +++++++++++-
 .../nixos-virtualization-arion-test/test.nix  | 40 +++++++++++++++++--
 3 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/tests/flake-module.nix b/tests/flake-module.nix
index 09f1c01..5c11fff 100644
--- a/tests/flake-module.nix
+++ b/tests/flake-module.nix
@@ -13,10 +13,10 @@
           };
 
         # Currently broken; kafka can't reach zookeeper
-        # nixosModuleWithPodman =
-        #   import ./nixos-virtualization-arion-test/test.nix final {
-        #     virtualisation.arion.backend = "podman-socket";
-        #   };
+        nixosModuleWithPodman =
+          import ./nixos-virtualization-arion-test/test.nix final {
+            virtualisation.arion.backend = "podman-socket";
+          };
 
         testWithPodman =
           nixosTest (import ./arion-test { usePodman = true; pkgs = final; });
diff --git a/tests/nixos-virtualization-arion-test/arion-compose.nix b/tests/nixos-virtualization-arion-test/arion-compose.nix
index 4597f81..df27243 100644
--- a/tests/nixos-virtualization-arion-test/arion-compose.nix
+++ b/tests/nixos-virtualization-arion-test/arion-compose.nix
@@ -1,4 +1,4 @@
-{ pkgs, ... }: {
+{ lib, pkgs, ... }: {
   project.name = "whale";
 
   docker-compose.raw = {
@@ -59,4 +59,28 @@
       "start-foreground"
     ];
   };
+
+  services.stop-probe = {
+    image.command = [
+      (lib.getExe (pkgs.writeScriptBin "stop-probe" ''
+        #!${pkgs.runtimeShell}
+        touch /diagnostics/stop-probe-started
+        onSIGTERM() {
+          echo "Handling SIGTERM"
+          touch /diagnostics/stop-probe-terminated-cleanly
+          echo "Bye!"
+        }
+        echo "Registering SIGTERM handler"
+        trap onSIGTERM SIGTERM
+        sleep 3600
+      ''))
+    ];
+    service.useHostStore = true;
+    service.volumes = [
+      "/tmp/shared:/diagnostics"
+    ];
+    service.environment = {
+      "PATH" = lib.makeBinPath [ pkgs.busybox ];
+    };
+  };
 }
diff --git a/tests/nixos-virtualization-arion-test/test.nix b/tests/nixos-virtualization-arion-test/test.nix
index 2a472dd..212a4b0 100644
--- a/tests/nixos-virtualization-arion-test/test.nix
+++ b/tests/nixos-virtualization-arion-test/test.nix
@@ -1,6 +1,6 @@
 pkgs: module:
 
-pkgs.nixosTest {
+pkgs.testers.runNixOSTest ({ lib, ... }:{
   name = "test-basic-arion-kafka";
   nodes = {
     machine = { ... }: {
@@ -16,10 +16,13 @@ pkgs.nixosTest {
       };
     };
   };
-  testScript = ''
+  testScript = { nodes, ... }: ''
     machine.wait_for_unit("sockets.target")
     machine.wait_for_unit("arion-whale.service")
 
+    ${# TODO: make the kafka service work on podman-socket; some networking issue
+      lib.optionalString (nodes.machine.virtualisation.arion.backend != "podman-socket") ''
+
     machine.succeed("""
       (echo "hello"; echo "world") \
         | ${pkgs.apacheKafka}/bin/kafka-console-producer.sh \
@@ -35,6 +38,35 @@ pkgs.nixosTest {
         ) | grep --line-buffered hello | { read; kill $(<pid); rm pid; }
       ) 2>/dev/console
     """)
-    
+
+    # make sure logs were captured
+    machine.succeed("""
+      # Check that messages were logged with field "CONTAINER_NAME" set to "whale-zookeeper-1"
+      journalctl --output json | ${pkgs.jq}/bin/jq 'select(.CONTAINER_NAME=="whale-zookeeper-1") | .MESSAGE' | grep -F 'org.apache.zookeeper'
+    """)
+
+    ''}
+
+    machine.wait_until_succeeds("""
+      journalctl --grep 'Registering SIGTERM handler' >/dev/null
+    """)
+
+    # explore the shared mounts, as they're undocumented
+    machine.succeed("""
+      mount >&2
+      touch /tmp/xchg/this-is-xchg
+      touch /tmp/shared/this-is-shared
+    """)
+
+    machine.shutdown()
+
+    # show what's in machine.shared_dir by running `ls` on the host
+    dir = machine.shared_dir
+    import os
+    print(f'Contents of {dir}:')
+    os.system(f'ls -l {dir}')
+    # dir/stop-probe-terminated-cleanly must exist
+    assert os.path.exists(f'{dir}/stop-probe-terminated-cleanly'), f'{dir}/stop-probe-terminated-cleanly does not exist'
+
   '';
-}
+})

From 0437b5f9a455b5b02c433b818289011d7ed3d3ef Mon Sep 17 00:00:00 2001
From: Robert Hensing <robert@roberthensing.nl>
Date: Mon, 24 Jun 2024 09:46:16 +0200
Subject: [PATCH 2/2] nixos-module: Type=oneshot

This may improve the shutdown behavior
---
 nixos-module.nix | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/nixos-module.nix b/nixos-module.nix
index c4f7beb..58d096d 100644
--- a/nixos-module.nix
+++ b/nixos-module.nix
@@ -42,10 +42,22 @@ let
           cfg.docker.client.package
         ];
         environment.ARION_PREBUILT = config.settings.out.dockerComposeYaml;
-        script = ''
-          echo 1>&2 "docker compose file: $ARION_PREBUILT"
-          arion --prebuilt-file "$ARION_PREBUILT" up
-        '';
+        serviceConfig.Type = "oneshot";
+        serviceConfig.RemainAfterExit = true;
+        serviceConfig.ExecStart = [
+          (lib.getExe (pkgs.writeScriptBin "nixos-arion-start" ''
+            #!${pkgs.runtimeShell}
+            echo 1>&2 "starting arion project: $ARION_PREBUILT"
+            arion --prebuilt-file "$ARION_PREBUILT" up --detach
+          ''))
+        ];
+        serviceConfig.ExecStop = [
+          (lib.getExe (pkgs.writeScriptBin "nixos-arion-stop" ''
+            #!${pkgs.runtimeShell}
+            echo 1>&2 "stopping arion project: $ARION_PREBUILT"
+            arion --prebuilt-file "$ARION_PREBUILT" down
+          ''))
+        ];
       };
     };
   };