/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos-ctl

  • Committer: Teddy Hogeborn
  • Date: 2019-03-02 02:33:00 UTC
  • Revision ID: teddy@recompile.se-20190302023300-cgss6bf71mwfb0ma
mandos-ctl: Refactor

* mandos-ctl (TableOfClients.__str__): New.
  (TableOfClients.__unicode__): New.
  (print_clients): Remove.
  (main): Create and print TableOfClients object directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
61
61
 
62
62
locale.setlocale(locale.LC_ALL, "")
63
63
 
64
 
tablewords = {
65
 
    "Name": "Name",
66
 
    "Enabled": "Enabled",
67
 
    "Timeout": "Timeout",
68
 
    "LastCheckedOK": "Last Successful Check",
69
 
    "LastApprovalRequest": "Last Approval Request",
70
 
    "Created": "Created",
71
 
    "Interval": "Interval",
72
 
    "Host": "Host",
73
 
    "Fingerprint": "Fingerprint",
74
 
    "KeyID": "Key ID",
75
 
    "CheckerRunning": "Check Is Running",
76
 
    "LastEnabled": "Last Enabled",
77
 
    "ApprovalPending": "Approval Is Pending",
78
 
    "ApprovedByDefault": "Approved By Default",
79
 
    "ApprovalDelay": "Approval Delay",
80
 
    "ApprovalDuration": "Approval Duration",
81
 
    "Checker": "Checker",
82
 
    "ExtendedTimeout": "Extended Timeout",
83
 
    "Expires": "Expires",
84
 
    "LastCheckerStatus": "Last Checker Status",
85
 
}
86
64
defaultkeywords = ("Name", "Enabled", "Timeout", "LastCheckedOK")
87
65
domain = "se.recompile"
88
66
busname = domain + ".Mandos"
291
269
    return value
292
270
 
293
271
 
294
 
def print_clients(clients, keywords):
 
272
class TableOfClients(object):
 
273
    tablewords = {
 
274
        "Name": "Name",
 
275
        "Enabled": "Enabled",
 
276
        "Timeout": "Timeout",
 
277
        "LastCheckedOK": "Last Successful Check",
 
278
        "LastApprovalRequest": "Last Approval Request",
 
279
        "Created": "Created",
 
280
        "Interval": "Interval",
 
281
        "Host": "Host",
 
282
        "Fingerprint": "Fingerprint",
 
283
        "KeyID": "Key ID",
 
284
        "CheckerRunning": "Check Is Running",
 
285
        "LastEnabled": "Last Enabled",
 
286
        "ApprovalPending": "Approval Is Pending",
 
287
        "ApprovedByDefault": "Approved By Default",
 
288
        "ApprovalDelay": "Approval Delay",
 
289
        "ApprovalDuration": "Approval Duration",
 
290
        "Checker": "Checker",
 
291
        "ExtendedTimeout": "Extended Timeout",
 
292
        "Expires": "Expires",
 
293
        "LastCheckerStatus": "Last Checker Status",
 
294
    }
 
295
 
 
296
    def __init__(self, clients, keywords, tablewords=None):
 
297
        self.clients = clients
 
298
        self.keywords = keywords
 
299
        if tablewords is not None:
 
300
            self.tablewords = tablewords
 
301
 
 
302
    def __str__(self):
 
303
        return "\n".join(self.rows())
 
304
 
 
305
    if sys.version_info.major == 2:
 
306
        __unicode__ = __str__
 
307
        def __str__(self):
 
308
            return str(self).encode(locale.getpreferredencoding())
 
309
 
 
310
    def rows(self):
 
311
        format_string = self.row_formatting_string()
 
312
        rows = [self.header_line(format_string)]
 
313
        rows.extend(self.client_line(client, format_string)
 
314
                    for client in self.clients)
 
315
        return rows
 
316
 
 
317
    def row_formatting_string(self):
 
318
        "Format string used to format table rows"
 
319
        return " ".join("{{{key}:{width}}}".format(
 
320
            width=max(len(self.tablewords[key]),
 
321
                      max(len(self.string_from_client(client, key))
 
322
                          for client in self.clients)),
 
323
            key=key)
 
324
                                 for key in self.keywords)
 
325
 
 
326
    def string_from_client(self, client, key):
 
327
        return self.valuetostring(client[key], key)
 
328
 
 
329
    @staticmethod
295
330
    def valuetostring(value, keyword):
296
331
        if isinstance(value, dbus.Boolean):
297
332
            return "Yes" if value else "No"
300
335
            return milliseconds_to_string(value)
301
336
        return str(value)
302
337
 
303
 
    # Create format string to print table rows
304
 
    format_string = " ".join("{{{key}:{width}}}".format(
305
 
        width=max(len(tablewords[key]),
306
 
                  max(len(valuetostring(client[key], key))
307
 
                      for client in clients)),
308
 
        key=key)
309
 
                             for key in keywords)
310
 
    # Print header line
311
 
    print(format_string.format(**tablewords))
312
 
    for client in clients:
313
 
        print(format_string
314
 
              .format(**{key: valuetostring(client[key], key)
315
 
                         for key in keywords}))
 
338
    def header_line(self, format_string):
 
339
        return format_string.format(**self.tablewords)
 
340
 
 
341
    def client_line(self, client, format_string):
 
342
        return format_string.format(
 
343
            **{key: self.string_from_client(client, key)
 
344
               for key in self.keywords})
316
345
 
317
346
 
318
347
def has_actions(options):
477
506
                      separators=(',', ': '))
478
507
            print()
479
508
        else:
480
 
            print_clients(clients.values(), keywords)
 
509
            print(TableOfClients(clients.values(), keywords))
481
510
    else:
482
511
        # Process each client in the list by all selected options
483
512
        for client in clients:
570
599
            value = string_to_delta("2h")
571
600
        self.assertEqual(value, datetime.timedelta(0, 7200))
572
601
 
 
602
class Test_TableOfClients(unittest.TestCase):
 
603
    def setUp(self):
 
604
        self.tablewords = {
 
605
            "Attr1": "X",
 
606
            "AttrTwo": "Yy",
 
607
            "AttrThree": "Zzz",
 
608
            "Bool": "A D-BUS Boolean",
 
609
            "NonDbusBoolean": "A Non-D-BUS Boolean",
 
610
            "Integer": "An Integer",
 
611
            "Timeout": "Timedelta 1",
 
612
            "Interval": "Timedelta 2",
 
613
            "ApprovalDelay": "Timedelta 3",
 
614
            "ApprovalDuration": "Timedelta 4",
 
615
            "ExtendedTimeout": "Timedelta 5",
 
616
            "String": "A String",
 
617
        }
 
618
        self.keywords = ["Attr1", "AttrTwo"]
 
619
        self.clients = [
 
620
            {
 
621
                "Attr1": "x1",
 
622
                "AttrTwo": "y1",
 
623
                "AttrThree": "z1",
 
624
                "Bool": dbus.Boolean(False),
 
625
                "NonDbusBoolean": False,
 
626
                "Integer": 0,
 
627
                "Timeout": 0,
 
628
                "Interval": 1000,
 
629
                "ApprovalDelay": 2000,
 
630
                "ApprovalDuration": 3000,
 
631
                "ExtendedTimeout": 4000,
 
632
                "String": "",
 
633
            },
 
634
            {
 
635
                "Attr1": "x2",
 
636
                "AttrTwo": "y2",
 
637
                "AttrThree": "z2",
 
638
                "Bool": dbus.Boolean(True),
 
639
                "NonDbusBoolean": True,
 
640
                "Integer": 1,
 
641
                "Timeout": 93785000,
 
642
                "Interval": 93786000,
 
643
                "ApprovalDelay": 93787000,
 
644
                "ApprovalDuration": 93788000,
 
645
                "ExtendedTimeout": 93789000,
 
646
                "String": "A huge string which will not fit," * 10,
 
647
            },
 
648
        ]
 
649
    def test_short_header(self):
 
650
        rows = TableOfClients(self.clients, self.keywords,
 
651
                              self.tablewords).rows()
 
652
        expected_rows = [
 
653
            "X  Yy",
 
654
            "x1 y1",
 
655
            "x2 y2"]
 
656
        self.assertEqual(rows, expected_rows)
 
657
    def test_booleans(self):
 
658
        keywords = ["Bool", "NonDbusBoolean"]
 
659
        rows = TableOfClients(self.clients, keywords,
 
660
                              self.tablewords).rows()
 
661
        expected_rows = [
 
662
            "A D-BUS Boolean A Non-D-BUS Boolean",
 
663
            "No              False              ",
 
664
            "Yes             True               ",
 
665
        ]
 
666
        self.assertEqual(rows, expected_rows)
 
667
    def test_milliseconds_detection(self):
 
668
        keywords = ["Integer", "Timeout", "Interval", "ApprovalDelay",
 
669
                    "ApprovalDuration", "ExtendedTimeout"]
 
670
        rows = TableOfClients(self.clients, keywords,
 
671
                              self.tablewords).rows()
 
672
        expected_rows = ("""
 
673
An Integer Timedelta 1 Timedelta 2 Timedelta 3 Timedelta 4 Timedelta 5
 
674
0          00:00:00    00:00:01    00:00:02    00:00:03    00:00:04   
 
675
1          1T02:03:05  1T02:03:06  1T02:03:07  1T02:03:08  1T02:03:09 
 
676
"""
 
677
        ).splitlines()[1:]
 
678
        self.assertEqual(rows, expected_rows)
 
679
    def test_empty_and_long_string_values(self):
 
680
        keywords = ["String"]
 
681
        rows = TableOfClients(self.clients, keywords,
 
682
                              self.tablewords).rows()
 
683
        expected_rows = ("""
 
684
A String                                                                                                                                                                                                                                                                                                                                  
 
685
                                                                                                                                                                                                                                                                                                                                          
 
686
A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,A huge string which will not fit,
 
687
"""
 
688
        ).splitlines()[1:]
 
689
        self.assertEqual(rows, expected_rows)
 
690
 
 
691
 
573
692
 
574
693
def should_only_run_tests():
575
694
    parser = argparse.ArgumentParser(add_help=False)