1{ pkgs, lib, ... }:
2
3let
4 apikey = "testapikey";
5in
6{
7 name = "octoprint";
8 meta.maintainers = with lib.maintainers; [ gador ];
9
10 nodes.machine =
11 { pkgs, ... }:
12 {
13 environment.systemPackages = with pkgs; [ jq ];
14 services.octoprint = {
15 enable = true;
16 extraConfig = {
17 server = {
18 firstRun = false;
19 };
20 api = {
21 enabled = true;
22 key = apikey;
23 };
24 plugins = {
25 # these need internet access and pollute the output with connection failed errors
26 _disabled = [
27 "softwareupdate"
28 "announcements"
29 "pluginmanager"
30 ];
31 };
32 };
33 };
34 };
35
36 testScript = ''
37 import json
38
39 @polling_condition
40 def octoprint_running():
41 machine.succeed("pgrep octoprint")
42
43 with subtest("Wait for octoprint service to start"):
44 machine.wait_for_unit("octoprint.service")
45 machine.wait_until_succeeds("pgrep octoprint")
46
47 with subtest("Wait for final boot"):
48 # this appears whe octoprint is almost finished starting
49 machine.wait_for_file("/var/lib/octoprint/uploads")
50
51 # octoprint takes some time to start. This makes sure we'll retry just in case it takes longer
52 # retry-all-errors in necessary, since octoprint will report a 404 error when not yet ready
53 curl_cmd = "curl --retry-all-errors --connect-timeout 5 --max-time 10 --retry 5 --retry-delay 0 \
54 --retry-max-time 40 -X GET --header 'X-API-Key: ${apikey}' "
55
56 # used to fail early, in case octoprint first starts and then crashes
57 with octoprint_running: # type: ignore[union-attr]
58 with subtest("Check for web interface"):
59 machine.wait_until_succeeds("curl -s localhost:5000")
60
61 with subtest("Check API"):
62 version = json.loads(machine.succeed(curl_cmd + "localhost:5000/api/version"))
63 server = json.loads(machine.succeed(curl_cmd + "localhost:5000/api/server"))
64 assert version["server"] == str("${pkgs.octoprint.version}")
65 assert server["safemode"] == None
66 '';
67}