1# verifies:
2# 1. jenkins service starts on master node
3# 2. jenkins user can be extended on both master and slave
4# 3. jenkins service not started on slave node
5# 4. declarative jobs can be added and removed
6
7import ./make-test-python.nix (
8 { pkgs, ... }:
9 {
10 name = "jenkins";
11 meta = with pkgs.lib.maintainers; {
12 maintainers = [
13 bjornfor
14 coconnor
15 domenkozar
16 ];
17 };
18
19 nodes = {
20
21 master =
22 { ... }:
23 {
24 services.jenkins = {
25 enable = true;
26 jobBuilder = {
27 enable = true;
28 nixJobs = [
29 {
30 job = {
31 name = "job-1";
32 builders = [
33 {
34 shell = ''
35 echo "Running job-1"
36 '';
37 }
38 ];
39 };
40 }
41
42 {
43 job = {
44 name = "folder-1";
45 project-type = "folder";
46 };
47 }
48
49 {
50 job = {
51 name = "folder-1/job-2";
52 builders = [
53 {
54 shell = ''
55 echo "Running job-2"
56 '';
57 }
58 ];
59 };
60 }
61 ];
62 };
63 };
64
65 specialisation.noJenkinsJobs.configuration = {
66 services.jenkins.jobBuilder.nixJobs = pkgs.lib.mkForce [ ];
67 };
68
69 # should have no effect
70 services.jenkinsSlave.enable = true;
71
72 users.users.jenkins.extraGroups = [ "users" ];
73
74 systemd.services.jenkins.serviceConfig.TimeoutStartSec = "6min";
75
76 # Increase disk space to prevent this issue:
77 #
78 # WARNING h.n.DiskSpaceMonitorDescriptor#markNodeOfflineOrOnline: Making Built-In Node offline temporarily due to the lack of disk space
79 virtualisation.diskSize = 2 * 1024;
80 };
81
82 slave =
83 { ... }:
84 {
85 services.jenkinsSlave.enable = true;
86
87 users.users.jenkins.extraGroups = [ "users" ];
88 };
89
90 };
91
92 testScript =
93 { nodes, ... }:
94 let
95 configWithoutJobs = "${nodes.master.system.build.toplevel}/specialisation/noJenkinsJobs";
96 jenkinsPort = nodes.master.services.jenkins.port;
97 jenkinsUrl = "http://localhost:${toString jenkinsPort}";
98 in
99 ''
100 start_all()
101
102 master.wait_for_unit("default.target")
103
104 assert "Authentication required" in master.succeed("curl http://localhost:8080")
105
106 for host in master, slave:
107 groups = host.succeed("sudo -u jenkins groups")
108 assert "jenkins" in groups
109 assert "users" in groups
110
111 slave.fail("systemctl is-enabled jenkins.service")
112
113 slave.succeed("java -fullversion")
114
115 with subtest("jobs are declarative"):
116 # Check that jobs are created on disk.
117 master.wait_until_succeeds("test -f /var/lib/jenkins/jobs/job-1/config.xml")
118 master.wait_until_succeeds("test -f /var/lib/jenkins/jobs/folder-1/config.xml")
119 master.wait_until_succeeds("test -f /var/lib/jenkins/jobs/folder-1/jobs/job-2/config.xml")
120
121 # Verify that jenkins also sees the jobs.
122 out = master.succeed("${pkgs.jenkins}/bin/jenkins-cli -s ${jenkinsUrl} -auth admin:$(cat /var/lib/jenkins/secrets/initialAdminPassword) list-jobs")
123 jobs = [x.strip() for x in out.splitlines()]
124 # Seeing jobs inside folders requires the Folders plugin
125 # (https://plugins.jenkins.io/cloudbees-folder/), which we don't have
126 # in this vanilla jenkins install, so limit ourself to non-folder jobs.
127 assert jobs == ['job-1'], f"jobs != ['job-1']: {jobs}"
128
129 master.succeed(
130 "${configWithoutJobs}/bin/switch-to-configuration test >&2"
131 )
132
133 # Check that jobs are removed from disk.
134 master.wait_until_fails("test -f /var/lib/jenkins/jobs/job-1/config.xml")
135 master.wait_until_fails("test -f /var/lib/jenkins/jobs/folder-1/config.xml")
136 master.wait_until_fails("test -f /var/lib/jenkins/jobs/folder-1/jobs/job-2/config.xml")
137
138 # Verify that jenkins also sees the jobs as removed.
139 out = master.succeed("${pkgs.jenkins}/bin/jenkins-cli -s ${jenkinsUrl} -auth admin:$(cat /var/lib/jenkins/secrets/initialAdminPassword) list-jobs")
140 jobs = [x.strip() for x in out.splitlines()]
141 assert jobs == [], f"jobs != []: {jobs}"
142 '';
143 }
144)