7
7
"testing"
8
8
9
9
"github.com/google/go-cmp/cmp"
10
+ "github.com/metal-stack/metal-go/api/models"
10
11
"github.com/metal-stack/metal-hammer/pkg/api"
12
+ "github.com/metal-stack/metal-lib/pkg/pointer"
11
13
"github.com/metal-stack/metal-lib/pkg/testcommon"
12
14
"github.com/metal-stack/v"
13
15
"github.com/spf13/afero"
@@ -210,6 +212,7 @@ func Test_installer_writeResolvConf(t *testing.T) {
210
212
tests := []struct {
211
213
name string
212
214
fsMocks func (fs afero.Fs )
215
+ config * api.InstallerConfig
213
216
want string
214
217
wantErr error
215
218
}{
@@ -227,6 +230,14 @@ nameserver 8.8.4.4
227
230
name : "resolv.conf gets written, file is not present" ,
228
231
want : `nameserver 8.8.8.8
229
232
nameserver 8.8.4.4
233
+ ` ,
234
+ wantErr : nil ,
235
+ },
236
+ {
237
+ name : "overwrite resolv.conf with custom DNS" ,
238
+ config : & api.InstallerConfig {DNSServers : []* models.V1DNSServer {{IP : pointer .Pointer ("1.2.3.4" )}, {IP : pointer .Pointer ("5.6.7.8" )}}},
239
+ want : `nameserver 1.2.3.4
240
+ nameserver 5.6.7.8
230
241
` ,
231
242
wantErr : nil ,
232
243
},
@@ -235,14 +246,19 @@ nameserver 8.8.4.4
235
246
tt := tt
236
247
t .Run (tt .name , func (t * testing.T ) {
237
248
i := & installer {
238
- log : slog .Default (),
239
- fs : afero .NewMemMapFs (),
249
+ log : slog .Default (),
250
+ fs : afero .NewMemMapFs (),
251
+ config : & api.InstallerConfig {},
240
252
}
241
253
242
254
if tt .fsMocks != nil {
243
255
tt .fsMocks (i .fs )
244
256
}
245
257
258
+ if tt .config != nil {
259
+ i .config = tt .config
260
+ }
261
+
246
262
err := i .writeResolvConf ()
247
263
if diff := cmp .Diff (tt .wantErr , err , testcommon .ErrorStringComparer ()); diff != "" {
248
264
t .Errorf ("error diff (+got -want):\n %s" , diff )
@@ -258,6 +274,207 @@ nameserver 8.8.4.4
258
274
}
259
275
}
260
276
277
+ func Test_installer_writeNTPConf (t * testing.T ) {
278
+ tests := []struct {
279
+ name string
280
+ fsMocks func (fs afero.Fs )
281
+ oss operatingsystem
282
+ role string
283
+ ntpServers []* models.V1NTPServer
284
+ ntpPath string
285
+ want string
286
+ wantErr error
287
+ }{
288
+ {
289
+ name : "configure custom ntp for ubuntu machine" ,
290
+ fsMocks : func (fs afero.Fs ) {
291
+ require .NoError (t , afero .WriteFile (fs , "/etc/systemd/timesyncd.conf" , []byte ("" ), 0644 ))
292
+ },
293
+ ntpPath : "/etc/systemd/timesyncd.conf" ,
294
+ oss : osUbuntu ,
295
+ role : "machine" ,
296
+ ntpServers : []* models.V1NTPServer {{Address : pointer .Pointer ("custom.1.ntp.org" )}, {Address : pointer .Pointer ("custom.2.ntp.org" )}},
297
+ want : `[Time]
298
+ NTP=custom.1.ntp.org custom.2.ntp.org
299
+ ` ,
300
+ wantErr : nil ,
301
+ },
302
+ {
303
+ name : "use default ntp for ubuntu machine" ,
304
+ fsMocks : func (fs afero.Fs ) {
305
+ require .NoError (t , afero .WriteFile (fs , "/etc/systemd/timesyncd.conf" , []byte ("" ), 0644 ))
306
+ },
307
+ ntpPath : "/etc/systemd/timesyncd.conf" ,
308
+ oss : osUbuntu ,
309
+ role : "machine" ,
310
+ want : "" ,
311
+ wantErr : nil ,
312
+ },
313
+ {
314
+ name : "configure custom ntp for debian machine" ,
315
+ fsMocks : func (fs afero.Fs ) {
316
+ require .NoError (t , afero .WriteFile (fs , "/etc/systemd/timesyncd.conf" , []byte ("" ), 0644 ))
317
+ },
318
+ ntpPath : "/etc/systemd/timesyncd.conf" ,
319
+ oss : osDebian ,
320
+ role : "machine" ,
321
+ ntpServers : []* models.V1NTPServer {{Address : pointer .Pointer ("custom.1.ntp.org" )}, {Address : pointer .Pointer ("custom.2.ntp.org" )}},
322
+ want : `[Time]
323
+ NTP=custom.1.ntp.org custom.2.ntp.org
324
+ ` ,
325
+ wantErr : nil ,
326
+ },
327
+ {
328
+ name : "use default ntp for debian machine" ,
329
+ fsMocks : func (fs afero.Fs ) {
330
+ require .NoError (t , afero .WriteFile (fs , "/etc/systemd/timesyncd.conf" , []byte ("" ), 0644 ))
331
+ },
332
+ ntpPath : "/etc/systemd/timesyncd.conf" ,
333
+ oss : osDebian ,
334
+ role : "machine" ,
335
+ want : "" ,
336
+ wantErr : nil ,
337
+ },
338
+ {
339
+ name : "configure ntp for almalinux machine" ,
340
+ fsMocks : func (fs afero.Fs ) {
341
+ require .NoError (t , afero .WriteFile (fs , "/etc/chrony.conf" , []byte ("" ), 0644 ))
342
+ },
343
+ oss : osAlmalinux ,
344
+ ntpPath : "/etc/chrony.conf" ,
345
+ role : "machine" ,
346
+ ntpServers : []* models.V1NTPServer {{Address : pointer .Pointer ("custom.1.ntp.org" )}, {Address : pointer .Pointer ("custom.2.ntp.org" )}},
347
+ want : `# Welcome to the chrony configuration file. See chrony.conf(5) for more
348
+ # information about usable directives.
349
+
350
+ # In case no custom NTP server is provided
351
+ # Cloudflare offers a free public time service that allows us to use their
352
+ # anycast network of 180+ locations to synchronize time from their closest server.
353
+ # See https://blog.cloudflare.com/secure-time/
354
+ pool custom.1.ntp.org iburst
355
+ pool custom.2.ntp.org iburst
356
+
357
+ # This directive specify the location of the file containing ID/key pairs for
358
+ # NTP authentication.
359
+ keyfile /etc/chrony/chrony.keys
360
+
361
+ # This directive specify the file into which chronyd will store the rate
362
+ # information.
363
+ driftfile /var/lib/chrony/chrony.drift
364
+
365
+ # Uncomment the following line to turn logging on.
366
+ #log tracking measurements statistics
367
+
368
+ # Log files location.
369
+ logdir /var/log/chrony
370
+
371
+ # Stop bad estimates upsetting machine clock.
372
+ maxupdateskew 100.0
373
+
374
+ # This directive enables kernel synchronisation (every 11 minutes) of the
375
+ # real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
376
+ rtcsync
377
+
378
+ # Step the system clock instead of slewing it if the adjustment is larger than
379
+ # one second, but only in the first three clock updates.
380
+ makestep 1 3` ,
381
+ wantErr : nil ,
382
+ },
383
+ {
384
+ name : "use default ntp for almalinux machine" ,
385
+ fsMocks : func (fs afero.Fs ) {
386
+ require .NoError (t , afero .WriteFile (fs , "/etc/chrony.conf" , []byte ("" ), 0644 ))
387
+ },
388
+ oss : osAlmalinux ,
389
+ ntpPath : "/etc/chrony.conf" ,
390
+ role : "machine" ,
391
+ want : "" ,
392
+ wantErr : nil ,
393
+ },
394
+ {
395
+ name : "configure custom ntp for firewall" ,
396
+ fsMocks : func (fs afero.Fs ) {
397
+ require .NoError (t , afero .WriteFile (fs , "/etc/chrony/chrony.conf" , []byte ("" ), 0644 ))
398
+ },
399
+ ntpPath : "/etc/chrony/chrony.conf" ,
400
+ role : "firewall" ,
401
+ ntpServers : []* models.V1NTPServer {{Address : pointer .Pointer ("custom.1.ntp.org" )}, {Address : pointer .Pointer ("custom.2.ntp.org" )}},
402
+ want : `# Welcome to the chrony configuration file. See chrony.conf(5) for more
403
+ # information about usable directives.
404
+
405
+ # In case no custom NTP server is provided
406
+ # Cloudflare offers a free public time service that allows us to use their
407
+ # anycast network of 180+ locations to synchronize time from their closest server.
408
+ # See https://blog.cloudflare.com/secure-time/
409
+ pool custom.1.ntp.org iburst
410
+ pool custom.2.ntp.org iburst
411
+
412
+ # This directive specify the location of the file containing ID/key pairs for
413
+ # NTP authentication.
414
+ keyfile /etc/chrony/chrony.keys
415
+
416
+ # This directive specify the file into which chronyd will store the rate
417
+ # information.
418
+ driftfile /var/lib/chrony/chrony.drift
419
+
420
+ # Uncomment the following line to turn logging on.
421
+ #log tracking measurements statistics
422
+
423
+ # Log files location.
424
+ logdir /var/log/chrony
425
+
426
+ # Stop bad estimates upsetting machine clock.
427
+ maxupdateskew 100.0
428
+
429
+ # This directive enables kernel synchronisation (every 11 minutes) of the
430
+ # real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
431
+ rtcsync
432
+
433
+ # Step the system clock instead of slewing it if the adjustment is larger than
434
+ # one second, but only in the first three clock updates.
435
+ makestep 1 3` ,
436
+ wantErr : nil ,
437
+ },
438
+ {
439
+ name : "use default ntp for firewall" ,
440
+ fsMocks : func (fs afero.Fs ) {
441
+ require .NoError (t , afero .WriteFile (fs , "/etc/chrony/chrony.conf" , []byte ("" ), 0644 ))
442
+ },
443
+ ntpPath : "/etc/chrony/chrony.conf" ,
444
+ role : "firewall" ,
445
+ want : "" ,
446
+ wantErr : nil ,
447
+ },
448
+ }
449
+ for _ , tt := range tests {
450
+ tt := tt
451
+ t .Run (tt .name , func (t * testing.T ) {
452
+ i := & installer {
453
+ log : slog .Default (),
454
+ fs : afero .NewMemMapFs (),
455
+ config : & api.InstallerConfig {Role : tt .role , NTPServers : tt .ntpServers },
456
+ oss : tt .oss ,
457
+ }
458
+
459
+ if tt .fsMocks != nil {
460
+ tt .fsMocks (i .fs )
461
+ }
462
+
463
+ err := i .writeNTPConf ()
464
+ if diff := cmp .Diff (tt .wantErr , err , testcommon .ErrorStringComparer ()); diff != "" {
465
+ t .Errorf ("error diff (+got -want):\n %s" , diff )
466
+ }
467
+
468
+ content , err := afero .ReadFile (i .fs , tt .ntpPath )
469
+ require .NoError (t , err )
470
+
471
+ if diff := cmp .Diff (tt .want , string (content )); diff != "" {
472
+ t .Errorf ("error diff (+got -want):\n %s" , diff )
473
+ }
474
+ })
475
+ }
476
+ }
477
+
261
478
func Test_installer_fixPermissions (t * testing.T ) {
262
479
tests := []struct {
263
480
name string
0 commit comments