1 // SPDX-License-Identifier: GPL-3.0-or-later
2 // Copyright (C) 2021-2024 Simon Ruderich
15 "ruderich.org/simon/safcm"
16 "ruderich.org/simon/safcm/testutil"
19 func TestHostSyncReq(t *testing.T) {
20 cwd, err := os.Getwd()
24 defer os.Chdir(cwd) //nolint:errcheck
36 // NOTE: Also update MsgSyncReq in safcm-remote test cases
37 // changing the MsgSyncReq struct!
52 Files: map[string]*safcm.File{
56 Mode: fs.ModeDir | 0755 | fs.ModeSetgid,
59 TriggerCommands: []string{
66 Mode: fs.ModeDir | 0755,
73 Mode: 0100 | fs.ModeSetuid | fs.ModeSetgid | fs.ModeSticky,
84 Data: []byte("Welcome to Host ONE\n\n\n\n\n\nall\n\n\nhost1.example.org\n\n\n\n"),
88 Path: "/etc/rc.local",
92 Data: []byte("#!/bin/sh\n"),
93 TriggerCommands: []string{
99 Path: "/etc/resolv.conf",
105 Data: []byte("nameserver ::1\n"),
106 TriggerCommands: []string{
107 "echo resolv.conf updated",
113 Mode: os.ModeSymlink | 0777,
116 Data: []byte("doesnt-exist"),
126 Commands: []*safcm.Command{
129 Cmd: "echo command one",
133 Cmd: "echo -n command two",
138 "3 false host groups: all group group3 host1.example.org remove",
139 "3 false host group priorities (descending): host1.example.org",
146 "project-conflict-file",
151 "3 false host groups: all dns host1.example.org",
152 "3 false host group priorities (descending): host1.example.org",
154 fmt.Errorf("groups dns and all both provide \"/etc/resolv.conf\"\nUse 'group_priority' in config.yaml to declare preference"),
157 "conflict: file from detected group",
158 "project-conflict-file",
165 "3 false host groups: all detected_other host2.example.org other",
166 "3 false host group priorities (descending): host2.example.org",
168 fmt.Errorf("groups other and all both provide \"/etc/resolv.conf\"\nUse 'group_priority' in config.yaml to declare preference"),
173 "project-conflict-dir",
178 "3 false host groups: all dns host1.example.org",
179 "3 false host group priorities (descending): host1.example.org",
181 fmt.Errorf("groups dns and all both provide \"/etc\"\nUse 'group_priority' in config.yaml to declare preference"),
184 "conflict: dir from detected group",
185 "project-conflict-dir",
192 "3 false host groups: all detected_other host2.example.org other",
193 "3 false host group priorities (descending): host2.example.org",
195 fmt.Errorf("groups other and all both provide \"/etc\"\nUse 'group_priority' in config.yaml to declare preference"),
200 "project-group-cycle",
205 fmt.Errorf("groups.yaml: cycle while expanding group \"group-b\""),
210 "project-group_priority",
214 Groups: []string{"all", "group-b", "group-a", "host1.example.org"},
215 Files: map[string]*safcm.File{
217 OrigGroup: "host1.example.org",
219 Mode: fs.ModeDir | 0755,
224 OrigGroup: "host1.example.org",
226 Mode: fs.ModeDir | 0755,
230 "/etc/dir-to-file": {
231 OrigGroup: "group-a",
232 Path: "/etc/dir-to-file",
236 Data: []byte("dir-to-file: from group-a\n"),
238 "/etc/dir-to-filex": {
239 OrigGroup: "group-b",
240 Path: "/etc/dir-to-filex",
244 Data: []byte("dir-to-filex\n"),
246 "/etc/dir-to-link": {
247 OrigGroup: "group-a",
248 Path: "/etc/dir-to-link",
249 Mode: fs.ModeSymlink | 0777,
252 Data: []byte("target"),
254 "/etc/dir-to-linkx": {
255 OrigGroup: "group-b",
256 Path: "/etc/dir-to-linkx",
260 Data: []byte("dir-to-linkx\n"),
262 "/etc/file-to-dir": {
263 OrigGroup: "group-a",
264 Path: "/etc/file-to-dir",
265 Mode: fs.ModeDir | 0755,
269 "/etc/file-to-dir/file": {
270 OrigGroup: "group-a",
271 Path: "/etc/file-to-dir/file",
275 Data: []byte("file: from group-a\n"),
277 "/etc/file-to-dir/dir": {
278 OrigGroup: "group-a",
279 Path: "/etc/file-to-dir/dir",
280 Mode: fs.ModeDir | 0755,
284 "/etc/file-to-dir/dir/file2": {
285 OrigGroup: "group-a",
286 Path: "/etc/file-to-dir/dir/file2",
290 Data: []byte("file2: from group-a\n"),
293 OrigGroup: "host1.example.org",
298 Data: []byte("motd: from host1\n"),
303 "3 false host groups: all group-a group-b host1.example.org",
304 "3 false host group priorities (descending): host1.example.org group-a group-b all",
305 `4 false files: "/etc": group group-a overwrites triggers from group group-b`,
306 `4 false files: "/etc": group host1.example.org overwrites triggers from group group-a`,
312 "group_priority (single group)",
313 "project-group_priority-single",
317 Groups: []string{"all", "group-b", "group-a", "host1.example.org"},
318 Files: map[string]*safcm.File{
320 OrigGroup: "group-a",
322 Mode: fs.ModeDir | 0755,
327 OrigGroup: "group-a",
332 Data: []byte("file.txt: from group-a\n"),
337 "3 false host groups: all group-a group-b host1.example.org",
338 "3 false host group priorities (descending): host1.example.org group-a",
344 for _, tc := range tests {
345 t.Run(tc.name, func(t *testing.T) {
346 err = os.Chdir(filepath.Join(cwd,
347 "testdata", tc.project))
352 // `safcm fixperms` in case user has strict umask
353 log.SetOutput(io.Discard)
354 err := MainFixperms()
358 log.SetOutput(os.Stderr)
360 cfg, allHosts, allGroups, err := LoadBaseFiles()
367 host: allHosts.Map[tc.host],
370 allGroups: allGroups,
371 logFunc: func(level safcm.LogLevel, escaped bool, msg string) {
372 events = append(events,
373 fmt.Sprintf("%d %v %s", level, escaped, msg))
377 res, err := s.hostSyncReq(tc.detected)
378 testutil.AssertEqual(t, "res", res, tc.exp)
379 testutil.AssertErrorEqual(t, "err", err, tc.expErr)
380 testutil.AssertEqual(t, "events",
381 events, tc.expEvents)