]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - cmd/safcm/config/groups_test.go
safcm: don't color output if stderr is redirected
[safcm/safcm.git] / cmd / safcm / config / groups_test.go
1 // Copyright (C) 2021  Simon Ruderich
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 package config
17
18 import (
19         "fmt"
20         "os"
21         "path/filepath"
22         "testing"
23
24         "ruderich.org/simon/safcm/testutil"
25 )
26
27 func TestLoadGroups(t *testing.T) {
28         cwd, err := os.Getwd()
29         if err != nil {
30                 t.Fatal(err)
31         }
32         defer os.Chdir(cwd)
33
34         err = os.Chdir("../testdata/project")
35         if err != nil {
36                 t.Fatal(err)
37         }
38         hosts, err := LoadHosts()
39         if err != nil {
40                 t.Fatal(err)
41         }
42         err = os.Chdir(cwd)
43         if err != nil {
44                 t.Fatal(err)
45         }
46
47         tests := []struct {
48                 path   string
49                 cfg    *Config
50                 hosts  *Hosts
51                 exp    map[string][]string
52                 expErr error
53         }{
54
55                 {
56                         "../testdata/project",
57                         &Config{
58                                 GroupPriority: []string{
59                                         "detected_linux",
60                                         "detected_freebsd",
61                                 },
62                         },
63                         hosts,
64                         map[string][]string{
65                                 "group": {
66                                         "detected_linux",
67                                         "detected_freebsd",
68                                         "host1.example.org",
69                                 },
70                                 "group:remove": {
71                                         "host2",
72                                         "detected_mips",
73                                 },
74                                 "group2": {
75                                         "all",
76                                 },
77                                 "group2:remove": {
78                                         "remove",
79                                 },
80                                 "group3": {
81                                         "host1.example.org",
82                                 },
83                                 "group3:remove": {
84                                         "host2",
85                                 },
86                                 "all_except_some": {
87                                         "all",
88                                 },
89                                 "all_except_some:remove": {
90                                         "host1.example.org",
91                                         "group2",
92                                 },
93                                 "remove": {
94                                         "host1.example.org",
95                                         "host2",
96                                         "host3.example.net",
97                                 },
98                                 "remove:remove": {
99                                         "host2",
100                                 },
101                         },
102                         nil,
103                 },
104
105                 {
106                         "../testdata/project",
107                         &Config{
108                                 GroupPriority: []string{
109                                         "detected_freebsd",
110                                         "does-not-exist",
111                                 },
112                         },
113                         hosts,
114                         nil,
115                         fmt.Errorf("config.yaml: group_priority: group \"does-not-exist\" does not exist"),
116                 },
117                 {
118                         "../testdata/project",
119                         &Config{
120                                 GroupPriority: []string{
121                                         "detected_freebsd",
122                                         "special:group",
123                                 },
124                         },
125                         hosts,
126                         nil,
127                         fmt.Errorf("config.yaml: group_priority: invalid group name \"special:group\""),
128                 },
129                 {
130                         "../testdata/project",
131                         &Config{
132                                 GroupPriority: []string{
133                                         "detected_freebsd",
134                                         "group:remove",
135                                 },
136                         },
137                         hosts,
138                         nil,
139                         fmt.Errorf("config.yaml: group_priority: invalid group name \"group:remove\""),
140                 },
141
142                 {
143                         "../testdata/group-invalid-all",
144                         &Config{},
145                         hosts,
146                         nil,
147                         fmt.Errorf("groups.yaml: group \"all\": conflict with pre-defined group \"all\""),
148                 },
149                 {
150                         "../testdata/group-invalid-all-remove",
151                         &Config{},
152                         hosts,
153                         nil,
154                         fmt.Errorf("groups.yaml: group \"all:remove\": conflict with pre-defined group \"all:remove\""),
155                 },
156                 {
157                         "../testdata/group-invalid-conflict",
158                         &Config{},
159                         hosts,
160                         nil,
161                         fmt.Errorf("groups.yaml: group \"host2\": conflict with existing host"),
162                 },
163                 {
164                         "../testdata/group-invalid-conflict-remove",
165                         &Config{},
166                         hosts,
167                         nil,
168                         fmt.Errorf("groups.yaml: group \"host2:remove\": conflict with existing host"),
169                 },
170                 {
171                         "../testdata/group-invalid-detected",
172                         &Config{},
173                         &Hosts{},
174                         nil,
175                         fmt.Errorf("groups.yaml: group \"detected_linux\": name must not start with \"detected\" (reserved for detected groups)"),
176                 },
177                 {
178                         "../testdata/group-invalid-member",
179                         &Config{},
180                         &Hosts{},
181                         nil,
182                         fmt.Errorf("groups.yaml: group \"group1\": member \"special:member\" must not contain \":\""),
183                 },
184                 {
185                         "../testdata/group-invalid-missing",
186                         &Config{},
187                         &Hosts{},
188                         nil,
189                         fmt.Errorf("groups.yaml: group \"group2\": member \"does-not-exist\" not found"),
190                 },
191                 {
192                         "../testdata/group-invalid-name",
193                         &Config{},
194                         &Hosts{},
195                         nil,
196                         fmt.Errorf("groups.yaml: group \"invalid.group.name\": name contains invalid characters (must match ^[a-z0-9_-]+$)"),
197                 },
198         }
199
200         for _, tc := range tests {
201                 t.Run(tc.path, func(t *testing.T) {
202                         err := os.Chdir(filepath.Join(cwd, tc.path))
203                         if err != nil {
204                                 t.Fatal(err)
205                         }
206
207                         res, err := LoadGroups(tc.cfg, tc.hosts)
208                         testutil.AssertEqual(t, "res", res, tc.exp)
209                         testutil.AssertErrorEqual(t, "err", err, tc.expErr)
210                 })
211         }
212 }
213
214 func TestResolveHostGroups(t *testing.T) {
215         cwd, err := os.Getwd()
216         if err != nil {
217                 t.Fatal(err)
218         }
219         defer os.Chdir(cwd)
220
221         err = os.Chdir("../testdata/project")
222         if err != nil {
223                 t.Fatal(err)
224         }
225         allHosts, err := LoadHosts()
226         if err != nil {
227                 t.Fatal(err)
228         }
229         allGroups, err := LoadGroups(&Config{}, allHosts)
230         if err != nil {
231                 t.Fatal(err)
232         }
233
234         tests := []struct {
235                 name     string
236                 host     string
237                 detected []string
238                 exp      []string
239                 expErr   error
240         }{
241
242                 {
243                         "host1",
244                         "host1.example.org",
245                         nil,
246                         []string{
247                                 "all",
248                                 "group",
249                                 "group3",
250                                 "host1.example.org",
251                                 "remove",
252                         },
253                         nil,
254                 },
255                 {
256                         "host2",
257                         "host2",
258                         nil,
259                         []string{
260                                 "all",
261                                 "group2",
262                                 "host2",
263                         },
264                         nil,
265                 },
266                 {
267                         "host3",
268                         "host3.example.net",
269                         nil,
270                         []string{
271                                 "all",
272                                 "all_except_some",
273                                 "host3.example.net",
274                                 "remove",
275                         },
276                         nil,
277                 },
278                 {
279                         "unknown host",
280                         "unknown",
281                         nil,
282                         []string{
283                                 "all",
284                                 "group2",
285                                 "unknown",
286                         },
287                         nil,
288                 },
289
290                 {
291                         "host1, detected_mips",
292                         "host1.example.org",
293                         []string{
294                                 "detected_mips",
295                         },
296                         []string{
297                                 "all",
298                                 "detected_mips",
299                                 "group3",
300                                 "host1.example.org",
301                                 "remove",
302                         },
303                         nil,
304                 },
305                 {
306                         "host2, detected_linux",
307                         "host2",
308                         []string{
309                                 "detected_linux",
310                         },
311                         []string{
312                                 "all",
313                                 "detected_linux",
314                                 "group2",
315                                 "host2",
316                         },
317                         nil,
318                 },
319         }
320
321         for _, tc := range tests {
322                 t.Run(tc.name, func(t *testing.T) {
323                         res, err := ResolveHostGroups(tc.host, allGroups,
324                                 tc.detected)
325                         testutil.AssertEqual(t, "res", res, tc.exp)
326                         testutil.AssertErrorEqual(t, "err", err, tc.expErr)
327                 })
328         }
329 }
330
331 func TestTransitivelyDetectedGroups(t *testing.T) {
332         tests := []struct {
333                 name   string
334                 groups map[string][]string
335                 exp    map[string]bool
336         }{
337
338                 {
339                         "no detected",
340                         map[string][]string{
341                                 "group-a": {
342                                         "a",
343                                         "b",
344                                         "group-b",
345                                 },
346                                 "group-a:remove": {
347                                         "d",
348                                 },
349                                 "group-b": {
350                                         "c",
351                                         "d",
352                                 },
353                         },
354                         map[string]bool{},
355                 },
356
357                 {
358                         "detected as direct member",
359                         map[string][]string{
360                                 "group-a": {
361                                         "a",
362                                         "b",
363                                         "detected_foo",
364                                 },
365                                 "group-b": {
366                                         "c",
367                                         "d",
368                                 },
369                         },
370                         map[string]bool{
371                                 "group-a": true,
372                         },
373                 },
374
375                 {
376                         "detected as direct :remove member",
377                         map[string][]string{
378                                 "group-a": {
379                                         "a",
380                                         "b",
381                                         "group-b",
382                                 },
383                                 "group-a:remove": {
384                                         "d",
385                                         "detected_foo",
386                                 },
387                                 "group-b": {
388                                         "c",
389                                         "d",
390                                 },
391                         },
392                         map[string]bool{
393                                 "group-a": true,
394                         },
395                 },
396
397                 {
398                         "detected as transitive member",
399                         map[string][]string{
400                                 "group-a": {
401                                         "group-b",
402                                 },
403                                 "group-b": {
404                                         "group-c",
405                                 },
406                                 "group-c": {
407                                         "group-d",
408                                         "detected_bar",
409                                 },
410                                 "group-d": {
411                                         "group-e",
412                                 },
413                                 "group-e": {
414                                         "detected_foo",
415                                 },
416                                 "group-f": {
417                                         "a",
418                                         "b",
419                                 },
420                         },
421                         map[string]bool{
422                                 "group-a": true,
423                                 "group-b": true,
424                                 "group-c": true,
425                                 "group-d": true,
426                                 "group-e": true,
427                         },
428                 },
429
430                 {
431                         "detected as transitive :remove member",
432                         map[string][]string{
433                                 "group-a": {
434                                         "group-b",
435                                 },
436                                 "group-b": {
437                                         "group-c",
438                                 },
439                                 "group-c": {
440                                         "group-d",
441                                 },
442                                 "group-d": {
443                                         "group-e",
444                                 },
445                                 "group-e": {
446                                         "all",
447                                 },
448                                 "group-e:remove": {
449                                         "detected_foo",
450                                 },
451                                 "group-f": {
452                                         "a",
453                                         "b",
454                                 },
455                         },
456                         map[string]bool{
457                                 "group-a": true,
458                                 "group-b": true,
459                                 "group-c": true,
460                                 "group-d": true,
461                                 "group-e": true,
462                         },
463                 },
464         }
465
466         for _, tc := range tests {
467                 t.Run(tc.name, func(t *testing.T) {
468                         res := TransitivelyDetectedGroups(tc.groups)
469                         testutil.AssertEqual(t, "res", res, tc.exp)
470                 })
471         }
472 }